mirror of
https://github.com/QingdaoU/OnlineJudgeFE.git
synced 2024-12-28 23:41:47 +00:00
support multiple languages using i18n
This commit is contained in:
commit
52fd9fbb88
@ -35,7 +35,7 @@ npm run dev
|
||||
|
||||
## Screenshots
|
||||
|
||||
[Check here.](https://github.com/QingdaoU/OnlineJudge/tree/2.0)
|
||||
[Check here.](https://github.com/QingdaoU/OnlineJudge)
|
||||
|
||||
## Browser Support
|
||||
|
||||
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -16733,6 +16733,11 @@
|
||||
"integrity": "sha1-aDvR0CbA07PJN9WHVnnpqH7GzY8=",
|
||||
"dev": true
|
||||
},
|
||||
"vue-i18n": {
|
||||
"version": "7.7.0",
|
||||
"resolved": "http://registry.npm.taobao.org/vue-i18n/download/vue-i18n-7.7.0.tgz",
|
||||
"integrity": "sha1-8xdYHg68Q8EoZiUBz6vW7NXn/Os="
|
||||
},
|
||||
"vue-katex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "http://registry.npm.taobao.org/vue-katex/download/vue-katex-0.1.2.tgz",
|
||||
|
@ -34,6 +34,7 @@
|
||||
"vue-codemirror-lite": "^1.0.4",
|
||||
"vue-cropper": "^0.2.9",
|
||||
"vue-echarts": "^2.6.0",
|
||||
"vue-i18n": "^7.7.0",
|
||||
"vue-katex": "^0.1.2",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.0.1",
|
||||
|
104
src/i18n/admin/en-US.js
Normal file
104
src/i18n/admin/en-US.js
Normal file
@ -0,0 +1,104 @@
|
||||
export const m = {
|
||||
// SideMenu.vue
|
||||
Dashboard: 'Dashboard',
|
||||
General: 'General',
|
||||
User: 'User',
|
||||
Announcement: 'Announcement',
|
||||
System_Config: 'System Config',
|
||||
Judge_Server: 'Judge Server',
|
||||
Prune_Test_Case: 'Prune Test Case',
|
||||
Problem: 'Problem',
|
||||
Problem_List: 'Problem List',
|
||||
Create_Problem: 'Create Problem',
|
||||
Export_Import_Problem: 'Export Or Import Problem',
|
||||
Contest: 'Contest',
|
||||
Contest_List: 'Contest List',
|
||||
Create_Contest: 'Create Contest',
|
||||
// User.vue
|
||||
User_User: 'User',
|
||||
Import_User: 'Import User',
|
||||
Generate_User: 'Generate User',
|
||||
// User.vue-dialog
|
||||
User_Info: 'User',
|
||||
User_Username: 'Username',
|
||||
User_Real_Name: 'Real Name',
|
||||
User_Email: 'Email',
|
||||
User_New_Password: 'New Password',
|
||||
User_Type: 'User Type',
|
||||
Problem_Permission: 'Problem Permission',
|
||||
Two_Factor_Auth: 'Two Factor Auth',
|
||||
Is_Disabled: 'Is Disabled',
|
||||
// Announcement.vue
|
||||
General_Announcement: 'Announcement',
|
||||
Announcement_Title: 'Title',
|
||||
Announcement_Content: 'Conten',
|
||||
Announcement_Status: 'Status',
|
||||
// Conf.vue
|
||||
SMTP_Config: 'SMTP Config',
|
||||
Server: 'Server',
|
||||
Port: 'Port',
|
||||
Email: 'Email',
|
||||
Password: 'Password',
|
||||
Website_Config: 'Web Config',
|
||||
Base_Url: 'Base Url',
|
||||
Name: 'Name',
|
||||
Shortcut: 'Shortcut',
|
||||
Footer: 'Footer',
|
||||
Allow_Register: 'Allow Register',
|
||||
Submission_List_Show_All: 'Submission List Show All',
|
||||
// JudgeServer.vue
|
||||
Judge_Server_Token: 'Judge Server Token',
|
||||
Judge_Server_Info: 'Judge Server',
|
||||
IP: 'IP',
|
||||
Judger_Version: 'Judger Version',
|
||||
Service_URL: 'Service URL',
|
||||
Last_Heartbeat: 'Last Heartbeat',
|
||||
Create_Time: 'Create Time',
|
||||
// PruneTestCase
|
||||
Test_Case_Prune_Test_Case: 'Prune Test Case',
|
||||
// Problem.vue
|
||||
Display_ID: 'Display ID',
|
||||
Title: 'Title',
|
||||
Description: 'Description',
|
||||
Input_Description: 'Input Description',
|
||||
Output_Description: 'Output Description',
|
||||
Time_Limit: 'Time Limit',
|
||||
Memory_limit: 'Memory limit',
|
||||
Difficulty: 'Difficulty',
|
||||
Visible: 'Visible',
|
||||
Languages: 'Languages',
|
||||
Input_Samples: 'Input Samples',
|
||||
Output_Samples: 'Output Samples',
|
||||
Add_Sample: 'Add Sample',
|
||||
Code_Template: 'Code_Template',
|
||||
Special_Judge: 'Special Judge',
|
||||
Use_Special_Judge: 'Use Special Judge',
|
||||
Special_Judge_Code: 'Special Judge Code',
|
||||
SPJ_language: 'SPJ language',
|
||||
Compile: 'Compile',
|
||||
TestCase: 'TestCase',
|
||||
Type: 'Type',
|
||||
Input: 'Input',
|
||||
Output: 'Output',
|
||||
Score: 'Score',
|
||||
Hint: 'Hint',
|
||||
Source: 'Source',
|
||||
// Contest.vue
|
||||
ContestTitle: 'Title',
|
||||
ContestDescription: 'Description',
|
||||
Contest_Start_Time: 'Start Time',
|
||||
Contest_End_Time: 'End Time',
|
||||
Contest_Password: 'Password',
|
||||
Contest_Rule_Type: 'Contest Rule Type',
|
||||
Real_Time_Rank: 'Real Time Rank',
|
||||
Contest_Status: 'Status',
|
||||
Allowed_IP_Ranges: 'Allowed IP Ranges',
|
||||
CIDR_Network: 'CIDR Network',
|
||||
// Dashboard.vue
|
||||
Last_Login: 'Last Login',
|
||||
System_Overview: 'System Overview',
|
||||
DashBoardJudge_Server: 'Judge Server',
|
||||
HTTPS_Status: 'HTTPS Status',
|
||||
Force_HTTPS: 'Force HTTPS',
|
||||
CDN_HOST: 'CDN HOST'
|
||||
}
|
104
src/i18n/admin/zh-CN.js
Normal file
104
src/i18n/admin/zh-CN.js
Normal file
@ -0,0 +1,104 @@
|
||||
export const m = {
|
||||
// SideMenu.vue
|
||||
Dashboard: '仪表盘',
|
||||
General: '常用设置',
|
||||
User: '用户管理',
|
||||
Announcement: '公告管理',
|
||||
System_Config: '系统配置',
|
||||
Judge_Server: '判题服务器',
|
||||
Prune_Test_Case: '测试用例',
|
||||
Problem: '问题',
|
||||
Problem_List: '问题列表',
|
||||
Create_Problem: '增加题目',
|
||||
Export_Import_Problem: '导入导出题目',
|
||||
Contest: '测试&练习',
|
||||
Contest_List: '测试列表',
|
||||
Create_Contest: '创建测试',
|
||||
// User.vue
|
||||
User_User: '用户',
|
||||
Import_User: '导入用户',
|
||||
Generate_User: '生成用户',
|
||||
// User.vue-dialog
|
||||
User_Info: '用户信息',
|
||||
User_Username: '用户名',
|
||||
User_Real_Name: '真实姓名',
|
||||
User_Email: '用户邮箱',
|
||||
User_New_Password: '用户密码',
|
||||
User_Type: '用户类型',
|
||||
Problem_Permission: '问题权限',
|
||||
Two_Factor_Auth: '双因素认证',
|
||||
Is_Disabled: '是否可用',
|
||||
// Announcement.vue
|
||||
General_Announcement: '公告',
|
||||
Announcement_Title: '标题',
|
||||
Announcement_Content: '内容',
|
||||
Announcement_Status: '状态',
|
||||
// Conf.vue
|
||||
SMTP_Config: 'SMTP Config',
|
||||
Server: '服务器',
|
||||
Port: '端口',
|
||||
Email: '邮箱',
|
||||
Password: '授权码',
|
||||
Website_Config: 'Web Config',
|
||||
Base_Url: 'Base Url',
|
||||
Name: '名称',
|
||||
Shortcut: '简称',
|
||||
Footer: '页脚',
|
||||
Allow_Register: '是否允许注册',
|
||||
Submission_List_Show_All: '显示全部题目的提交',
|
||||
// JudgeServer.vue
|
||||
Judge_Server_Token: '判题服务器接口',
|
||||
Judge_Server_Info: '判题服务器',
|
||||
IP: 'IP',
|
||||
Judger_Version: '判题机版本',
|
||||
Service_URL: '服务器URL',
|
||||
Last_Heartbeat: '上一次心跳',
|
||||
Create_Time: '创建时间',
|
||||
// PruneTestCase
|
||||
Test_Case_Prune_Test_Case: '精简测试用例',
|
||||
// Problem.vue
|
||||
Display_ID: 'Display ID',
|
||||
Title: '题目',
|
||||
Description: '描述',
|
||||
Input_Description: '输入描述',
|
||||
Output_Description: '输出描述',
|
||||
Time_Limit: '时间限制',
|
||||
Memory_limit: '内存限制',
|
||||
Difficulty: '难度',
|
||||
Visible: '是否可见',
|
||||
Languages: '可选编程语言',
|
||||
Input_Samples: '输入样例',
|
||||
Output_Samples: '输出样例',
|
||||
Add_Sample: '添加样例',
|
||||
Code_Template: '代码模板',
|
||||
Special_Judge: 'Special Judge',
|
||||
Use_Special_Judge: '使用Special Judge',
|
||||
Special_Judge_Code: 'Special Judge Code',
|
||||
SPJ_language: 'SPJ language',
|
||||
Compile: '编译',
|
||||
TestCase: '测试用例',
|
||||
Type: '测试类型',
|
||||
Input: '输入',
|
||||
Output: '输出',
|
||||
Score: '分数',
|
||||
Hint: '提示',
|
||||
Source: '来源',
|
||||
// Contest.vue
|
||||
ContestTitle: '标题',
|
||||
ContestDescription: '描述',
|
||||
Contest_Start_Time: '开始时间',
|
||||
Contest_End_Time: '结束时间',
|
||||
Contest_Password: '密码',
|
||||
Contest_Rule_Type: '规则',
|
||||
Real_Time_Rank: '实时Rank',
|
||||
Contest_Status: '状态',
|
||||
Allowed_IP_Ranges: '允许的IP范围',
|
||||
CIDR_Network: 'CIDR Network',
|
||||
// Dashboard.vue
|
||||
Last_Login: '最后登录状态',
|
||||
System_Overview: '系统状况',
|
||||
DashBoardJudge_Server: '判题服务器',
|
||||
HTTPS_Status: 'HTTPS 状态',
|
||||
Force_HTTPS: '强制 HTTPS',
|
||||
CDN_HOST: 'CDN HOST'
|
||||
}
|
105
src/i18n/oj/en-US.js
Normal file
105
src/i18n/oj/en-US.js
Normal file
@ -0,0 +1,105 @@
|
||||
export const m = {
|
||||
// Problem.vue
|
||||
Description: 'Description',
|
||||
Input: 'Input',
|
||||
Output: 'Output',
|
||||
Sample_Input: 'Sample Input',
|
||||
Sample_Output: 'Sample Output',
|
||||
Hint: 'Hint',
|
||||
Source: 'Source',
|
||||
Status: 'Status',
|
||||
Information: 'Information',
|
||||
Time_Limit: 'Time Limit',
|
||||
Memory_Limit: 'Memory Limit',
|
||||
Created: 'Created By',
|
||||
Level: 'Level',
|
||||
Score: 'Score',
|
||||
Tags: 'Tags',
|
||||
Show: 'Show',
|
||||
// About.vue
|
||||
Result_Explanation: 'Result Explanation',
|
||||
Pending_Juding: 'You solution will be judged soon, please wait for result.',
|
||||
Compile_Error: "Failed to compile your source code. Click on the link to see compiler's output.",
|
||||
Accepted: 'Congratulations. Your solution is correct.',
|
||||
Wrong_Answer: "Your program's output doesn't match judger's answer.",
|
||||
Runtime_Error: 'Your program terminated abnormally. Possible reasons are: segment fault, divided by zero or exited with code other than 0.',
|
||||
Time_Limit_Exceeded: 'The CPU time your program used has exceeded limit. Java has a triple time limit.',
|
||||
Memory_Limit_Exceeded: 'The memory your program actually used has exceeded limit.',
|
||||
System_Error: 'Oops, something has gone wrong with the judger. Please report this to administrator.',
|
||||
// FAQ.vue
|
||||
Frequently_Asked_Questions: 'Frequently Asked Questions',
|
||||
// ContestDetail.vue
|
||||
Problems: 'Problems',
|
||||
Announcements: 'Announcements',
|
||||
Submissions: 'Submissions',
|
||||
Rankings: 'Rankings',
|
||||
Overview: 'Overview',
|
||||
Admin_Helper: 'Admin Helper',
|
||||
// ContestProblemList
|
||||
Problems_List: 'Problems List',
|
||||
|
||||
// NavBar.vue
|
||||
Home: 'Home',
|
||||
NavProblems: 'Problems',
|
||||
Contests: 'Contests',
|
||||
NavStatus: 'Status',
|
||||
Rank: 'Rank',
|
||||
ACM_Rank: 'ACM Rank',
|
||||
OI_Rank: 'OI Rank',
|
||||
About: 'About',
|
||||
Judger: 'Judger',
|
||||
FAQ: 'FAQ',
|
||||
Login: 'Login',
|
||||
Register: 'Register',
|
||||
MyHome: 'Home',
|
||||
MySubmissions: 'Submissions',
|
||||
Settings: 'Settings',
|
||||
Management: 'Management',
|
||||
Logout: 'Logout',
|
||||
// announcements.vue
|
||||
Refresh: 'Refresh',
|
||||
Back: 'Back',
|
||||
No_Announcements: 'No Announcements',
|
||||
// Setting.vue
|
||||
Profile: 'Profile',
|
||||
Account: 'Account',
|
||||
Security: 'Security',
|
||||
// AccoutSetting.vue
|
||||
ChangePassword: 'Change Password',
|
||||
ChangeEmail: 'Change Email',
|
||||
Update_Password: 'Update Password',
|
||||
// ProfileSetting.vue
|
||||
Avatar_Setting: 'Avatar Setting',
|
||||
Profile_Setting: 'Profile Setting',
|
||||
// SecuritySettig
|
||||
Sessions: 'Sessions',
|
||||
Two_Factor_Authentication: 'Two Factor Authentication',
|
||||
// Login.vue
|
||||
LoginUsername: 'Username',
|
||||
LoginPassword: 'Password',
|
||||
TFA_Code: 'Code from your TFA app',
|
||||
No_Account: 'No account? Register now!',
|
||||
Forget_Password: 'Forget Password',
|
||||
UserLogin: 'Login',
|
||||
// Register.vue
|
||||
RegisterUsername: 'Username',
|
||||
Email_Address: 'Email Address',
|
||||
RegisterPassword: 'Password',
|
||||
Password_Again: 'Password Again',
|
||||
Captcha: 'Captcha',
|
||||
UserRegister: 'Register',
|
||||
Already_Registed: 'Already registed? Login now!',
|
||||
// ResetPassword.vue and ApplyResetPassword.vue
|
||||
Reset_Password: 'Lost Password',
|
||||
RPassword: 'Password',
|
||||
RPassword_Again: 'Password Again',
|
||||
RCaptcha: 'Captcha',
|
||||
ApplyEmail: 'Your Email Address',
|
||||
Send_Password_Reset_Email: 'Send Password Reset Email',
|
||||
// UserHome.vue
|
||||
UserHomeSolved: 'Solved',
|
||||
UserHomeserSubmissions: 'Submissions',
|
||||
UserHomeScore: 'Score',
|
||||
List_Solved_Problems: 'List of solved problems',
|
||||
UserHomeIntro: 'The guy is so lazy that has not solved any problem yet.'
|
||||
}
|
105
src/i18n/oj/zh-CN.js
Normal file
105
src/i18n/oj/zh-CN.js
Normal file
@ -0,0 +1,105 @@
|
||||
export const m = {
|
||||
// Problem.vue
|
||||
Description: '题目描述',
|
||||
Input: '输入',
|
||||
Output: '输出',
|
||||
Sample_Input: '输入样例',
|
||||
Sample_Output: '输出样例',
|
||||
Hint: '提示',
|
||||
Source: '题目来源',
|
||||
Status: '状态',
|
||||
Information: '题目信息',
|
||||
Time_Limit: '时间限制',
|
||||
Memory_Limit: '内存限制',
|
||||
Created: '出题人',
|
||||
Level: '难度',
|
||||
Score: '分数',
|
||||
Tags: '标签',
|
||||
Show: '显示',
|
||||
// About.vue
|
||||
Result_Explanation: '结果解释',
|
||||
Pending_Juding: '您的解答将很快被测评,请等待结果。',
|
||||
Compile_Error: '无法编译您的源代码,点击链接查看编译器的输出。',
|
||||
Accepted: '你的解题方法是正确的。',
|
||||
Wrong_Answer: '你的程序输出结果与判题程序的答案不符。',
|
||||
Runtime_Error: '您的程序异常终止,可能的原因是:段错误,被零除或用非0的代码退出程序。',
|
||||
Time_Limit_Exceeded: '您的程序使用的CPU时间已超出限制,Java有三倍的时间限制。',
|
||||
Memory_Limit_Exceeded: '程序实际使用的内存已超出限制。',
|
||||
System_Error: '糟糕,判题程序出了问题。请报告给管理员。',
|
||||
// FAQ.vue
|
||||
Frequently_Asked_Questions: '常见问题',
|
||||
// ContestDetail.vue
|
||||
Problems: '题目',
|
||||
Announcements: '公告',
|
||||
Submissions: '提交信息',
|
||||
Rankings: 'Rank排名',
|
||||
Overview: '概要',
|
||||
Admin_Helper: '管理员助手',
|
||||
// ContestProblemList.vue
|
||||
Problems_List: '问题列表',
|
||||
|
||||
// NavBar.vue
|
||||
Home: '首页',
|
||||
NavProblems: '问题',
|
||||
Contests: '练习&比赛',
|
||||
NavStatus: '状态',
|
||||
Rank: '排名',
|
||||
ACM_Rank: 'ACM 排名',
|
||||
OI_Rank: 'OI 排名',
|
||||
About: '关于',
|
||||
Judger: '判题解释',
|
||||
FAQ: '常见问题',
|
||||
Login: '登录',
|
||||
Register: '注册',
|
||||
MyHome: '我的主页',
|
||||
MySubmissions: '我的提交',
|
||||
Settings: '我的设置',
|
||||
Management: '后台管理',
|
||||
Logout: '退出',
|
||||
// announcements.vue
|
||||
Refresh: '刷新',
|
||||
Back: '返回',
|
||||
No_Announcements: '暂无公告',
|
||||
// Setting.vue
|
||||
Profile: '个人信息设置',
|
||||
Account: '账号设置',
|
||||
Security: '安全设置',
|
||||
// AccoutSetting.vue
|
||||
ChangePassword: '更改密码',
|
||||
ChangeEmail: '更改邮箱',
|
||||
Update_Password: '更新密码',
|
||||
// ProfileSetting.vue
|
||||
Avatar_Setting: '头像设置',
|
||||
Profile_Setting: '个人信息设置',
|
||||
// SecuritySettig
|
||||
Sessions: '登录记录',
|
||||
Two_Factor_Authentication: '双因素认证',
|
||||
// Login.vue
|
||||
LoginUsername: '用户名',
|
||||
LoginPassword: '密码',
|
||||
TFA_Code: '双因素认证号码',
|
||||
No_Account: '还没账号,立即注册!',
|
||||
Forget_Password: '忘记密码',
|
||||
UserLogin: '登录',
|
||||
// Register.vue
|
||||
RegisterUsername: '用户名',
|
||||
Email_Address: '电子邮箱',
|
||||
RegisterPassword: '密码',
|
||||
Password_Again: '确认密码',
|
||||
Captcha: '验证码',
|
||||
UserRegister: '注册',
|
||||
Already_Registed: '已经注册?现在登录!',
|
||||
// ResetPassword.vue and ApplyResetPassword.vue
|
||||
Reset_Password: '重置密码',
|
||||
RPassword: '密码',
|
||||
RPassword_Again: '确认密码',
|
||||
RCaptcha: '验证码',
|
||||
ApplyEmail: '电子邮箱',
|
||||
Send_Password_Reset_Email: '发送重置密码到邮箱',
|
||||
// UserHome.vue
|
||||
UserHomeSolved: '已解决数量',
|
||||
UserHomeserSubmissions: '提交次数',
|
||||
UserHomeScore: '分数',
|
||||
List_Solved_Problems: '已解决问题的列表',
|
||||
UserHomeIntro: '这个家伙太懒了,还没有做题呢...'
|
||||
}
|
@ -4,24 +4,24 @@
|
||||
<div class="logo">
|
||||
<img src="../../../assets/logo.svg" alt="oj admin"/>
|
||||
</div>
|
||||
<el-menu-item index="/"><i class="el-icon-fa-dashboard"></i>Dashboard</el-menu-item>
|
||||
<el-menu-item index="/"><i class="el-icon-fa-dashboard"></i>{{$t('m.Dashboard')}}</el-menu-item>
|
||||
<el-submenu v-if="isSuperAdmin" index="general">
|
||||
<template slot="title"><i class="el-icon-menu"></i>General</template>
|
||||
<el-menu-item index="/user">User</el-menu-item>
|
||||
<el-menu-item index="/announcement">Announcement</el-menu-item>
|
||||
<el-menu-item index="/conf">System Config</el-menu-item>
|
||||
<el-menu-item index="/judge-server">Judge Server</el-menu-item>
|
||||
<el-menu-item index="/prune-test-case">Prune Test Case</el-menu-item>
|
||||
<template slot="title"><i class="el-icon-menu"></i>{{$t('m.General')}}</template>
|
||||
<el-menu-item index="/user">{{$t('m.User')}}</el-menu-item>
|
||||
<el-menu-item index="/announcement">{{$t('m.Announcement')}}</el-menu-item>
|
||||
<el-menu-item index="/conf">{{$t('m.System_Config')}}</el-menu-item>
|
||||
<el-menu-item index="/judge-server">{{$t('m.Judge_Server')}}</el-menu-item>
|
||||
<el-menu-item index="/prune-test-case">{{$t('m.Prune_Test_Case')}}</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu index="problem" v-if="hasProblemPermission">
|
||||
<template slot="title"><i class="el-icon-fa-bars"></i>Problem</template>
|
||||
<el-menu-item index="/problems">Problem List</el-menu-item>
|
||||
<el-menu-item index="/problem/create">Create Problem</el-menu-item>
|
||||
<template slot="title"><i class="el-icon-fa-bars"></i>{{$t('m.Problem')}}</template>
|
||||
<el-menu-item index="/problems">{{$t('m.Problem_List')}}</el-menu-item>
|
||||
<el-menu-item index="/problem/create">{{$t('m.Create_Problem')}}</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu index="contest">
|
||||
<template slot="title"><i class="el-icon-fa-trophy"></i>Contest</template>
|
||||
<el-menu-item index="/contest">Contest List</el-menu-item>
|
||||
<el-menu-item index="/contest/create">Create Contest</el-menu-item>
|
||||
<template slot="title"><i class="el-icon-fa-trophy"></i>{{$t('m.Contest')}}</template>
|
||||
<el-menu-item index="/contest">{{$t('m.Contest_List')}}</el-menu-item>
|
||||
<el-menu-item index="/contest/create">{{$t('m.Create_Contest')}}</el-menu-item>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</template>
|
||||
@ -48,7 +48,7 @@
|
||||
<style scoped lang="less">
|
||||
.vertical_menu {
|
||||
overflow: auto;
|
||||
width: 200px;
|
||||
width: 205px;
|
||||
height: 100%;
|
||||
position: fixed !important;
|
||||
z-index: 100;
|
||||
|
@ -17,6 +17,8 @@ import Save from './components/btn/Save.vue'
|
||||
import Cancel from './components/btn/Cancel.vue'
|
||||
import './style.less'
|
||||
|
||||
import VueI18n from 'vue-i18n'
|
||||
|
||||
// register global utility filters.
|
||||
Object.keys(filters).forEach(key => {
|
||||
Vue.filter(key, filters[key])
|
||||
@ -32,6 +34,21 @@ Vue.component(Panel.name, Panel)
|
||||
Vue.component(Save.name, Save)
|
||||
Vue.component(Cancel.name, Cancel)
|
||||
|
||||
Vue.use(VueI18n)
|
||||
|
||||
// load language packages
|
||||
const i18n = new VueI18n({
|
||||
locale: 'zh-CN',
|
||||
messages: {
|
||||
'en-US': require('../../i18n/admin/en-US'),
|
||||
'zh-CN': require('../../i18n/admin/zh-CN')
|
||||
}
|
||||
})
|
||||
|
||||
Vue.use(Element, {
|
||||
i18n: (key, value) => i18n.t(key, value)
|
||||
})
|
||||
|
||||
Vue.prototype.$error = (msg) => {
|
||||
Vue.prototype.$message({'message': msg, 'type': 'error'})
|
||||
}
|
||||
@ -48,4 +65,4 @@ Vue.prototype.$success = (msg) => {
|
||||
}
|
||||
}
|
||||
|
||||
new Vue(Vue.util.extend({router, store}, App)).$mount('#app')
|
||||
new Vue(Vue.util.extend({router, store, i18n}, App)).$mount('#app')
|
||||
|
@ -17,6 +17,7 @@
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
<div class="footer">
|
||||
<el-button type="text" class="btn btn-success" @click="changeLocale()">简体中文 / English</el-button > |
|
||||
Build Version: {{ version }}
|
||||
</div>
|
||||
</div>
|
||||
@ -60,6 +61,14 @@
|
||||
this.$router.push({name: 'login'})
|
||||
})
|
||||
}
|
||||
},
|
||||
changeLocale () {
|
||||
// 通过默认locale切换语言
|
||||
if (this.$i18n.locale === 'zh-CN') {
|
||||
this.$i18n.locale = 'en-US'
|
||||
} else {
|
||||
this.$i18n.locale = 'zh-CN'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -4,46 +4,46 @@
|
||||
<el-form label-position="top">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="Title" required>
|
||||
<el-input v-model="contest.title" placeholder="Tittle"></el-input>
|
||||
<el-form-item :label="$t('m.ContestTitle')" required>
|
||||
<el-input v-model="contest.title" :placeholder="$t('m.ContestTitle')"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="Description" required>
|
||||
<el-form-item :label="$t('m.ContestDescription')" required>
|
||||
<Simditor v-model="contest.description"></Simditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Start Time" required>
|
||||
<el-form-item :label="$t('m.Contest_Start_Time')" required>
|
||||
<el-date-picker
|
||||
v-model="contest.start_time"
|
||||
type="datetime"
|
||||
placeholder="Start Time">
|
||||
:placeholder="$t('m.Contest_Start_Time')">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="End Time" required>
|
||||
<el-form-item :label="$t('m.Contest_End_Time')" required>
|
||||
<el-date-picker
|
||||
v-model="contest.end_time"
|
||||
type="datetime"
|
||||
placeholder="End Time">
|
||||
:placeholder="$t('m.Contest_End_Time')">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Password">
|
||||
<el-input v-model="contest.password" placeholder="Contest Password"></el-input>
|
||||
<el-form-item :label="$t('m.Contest_Password')">
|
||||
<el-input v-model="contest.password" :placeholder="$t('m.Contest_Password')"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Contest Rule Type">
|
||||
<el-form-item :label="$t('m.Contest_Rule_Type')">
|
||||
<el-radio class="radio" v-model="contest.rule_type" label="ACM" :disabled="disableRuleType">ACM</el-radio>
|
||||
<el-radio class="radio" v-model="contest.rule_type" label="OI" :disabled="disableRuleType">OI</el-radio>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Real Time Rank">
|
||||
<el-form-item :label="$t('m.Real_Time_Rank')">
|
||||
<el-switch
|
||||
v-model="contest.real_time_rank"
|
||||
active-color="#13ce66"
|
||||
@ -52,7 +52,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Status">
|
||||
<el-form-item :label="$t('m.Contest_Status')">
|
||||
<el-switch
|
||||
v-model="contest.visible"
|
||||
active-text=""
|
||||
@ -61,11 +61,11 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="Allowed IP Ranges">
|
||||
<el-form-item :label="$t('m.Allowed_IP_Ranges')">
|
||||
<div v-for="(range, index) in contest.allowed_ip_ranges" :key="index">
|
||||
<el-row :gutter="20" style="margin-bottom: 15px">
|
||||
<el-col :span="8">
|
||||
<el-input v-model="range.value" placeholder="CIDR Network"></el-input>
|
||||
<el-input v-model="range.value" :placeholder="$t('m.CIDR_Network')"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-button plain icon="el-icon-fa-plus" @click="addIPRange"></el-button>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="announcement view">
|
||||
<Panel title="Announcement">
|
||||
<Panel :title="$t('m.General_Announcement')">
|
||||
<div class="list">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
@ -74,17 +74,17 @@
|
||||
<el-dialog :title="announcementDialogTitle" :visible.sync="showEditAnnouncementDialog"
|
||||
@open="onOpenEditDialog" :close-on-click-modal="false">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="Title" required>
|
||||
<el-form-item :label="$t('m.Announcement_Title')" required>
|
||||
<el-input
|
||||
v-model="announcement.title"
|
||||
placeholder="Title" class="title-input">
|
||||
:placeholder="$t('m.Announcement_Title')" class="title-input">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Content" required>
|
||||
<el-form-item :label="$t('m.Announcement_Content')" required>
|
||||
<Simditor v-model="announcement.content"></Simditor>
|
||||
</el-form-item>
|
||||
<div class="visible-box">
|
||||
<span>Status</span>
|
||||
<span>{{$t('m.Announcement_Status')}}</span>
|
||||
<el-switch
|
||||
v-model="announcement.visible"
|
||||
active-text=""
|
||||
|
@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<div class="view">
|
||||
<Panel title="SMTP Config">
|
||||
<Panel :title="$t('m.SMTP_Config')">
|
||||
<el-form label-position="left" label-width="70px" :model="smtp">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Server" required>
|
||||
<el-form-item :label="$t('m.Server')" required>
|
||||
<el-input v-model="smtp.server" placeholder="SMTP Server Address"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Port" required>
|
||||
<el-form-item :label="$t('m.Port')" required>
|
||||
<el-input type="number" v-model="smtp.port" placeholder="SMTP Server Port"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Email" required>
|
||||
<el-form-item :label="$t('m.Email')" required>
|
||||
<el-input type="email" v-model="smtp.email" placeholder="Account Used To Send Email"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Password" label-width="90px" required>
|
||||
<el-form-item :label="$t('m.Password')" label-width="90px" required>
|
||||
<el-input v-model="smtp.password" type="password" placeholder="SMTP Server Password"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -39,33 +39,33 @@
|
||||
v-if="saved" :loading="loadingBtnTest">Send Test Email</el-button>
|
||||
</Panel>
|
||||
|
||||
<Panel title="Website Config">
|
||||
<Panel :title="$t('m.Website_Config')">
|
||||
<el-form label-position="left" label-width="100px" ref="form" :model="websiteConfig">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Base Url" required>
|
||||
<el-form-item :label="$t('m.Base_Url')" required>
|
||||
<el-input v-model="websiteConfig.website_base_url" placeholder="Website Base Url"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Name" required>
|
||||
<el-form-item :label="$t('m.Name')" required>
|
||||
<el-input v-model="websiteConfig.website_name" placeholder="Website Name"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Shortcut" required>
|
||||
<el-form-item :label="$t('m.Shortcut')" required>
|
||||
<el-input v-model="websiteConfig.website_name_shortcut" placeholder="Website Name Shortcut"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="Footer" required>
|
||||
<el-form-item :label="$t('m.Footer')" required>
|
||||
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4}" v-model="websiteConfig.website_footer"
|
||||
placeholder="Website Footer HTML"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Allow Register" label-width="200px">
|
||||
<el-form-item :label="$t('m.Allow_Register')" label-width="200px">
|
||||
<el-switch
|
||||
v-model="websiteConfig.allow_register"
|
||||
active-color="#13ce66"
|
||||
@ -74,7 +74,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Submission List Show All" label-width="200px">
|
||||
<el-form-item :label="$t('m.Submission_List_Show_All')" label-width="200px">
|
||||
<el-switch
|
||||
v-model="websiteConfig.submission_list_show_all"
|
||||
active-color="#13ce66"
|
||||
|
@ -13,7 +13,7 @@
|
||||
</el-row>
|
||||
<hr/>
|
||||
<div class="last-info">
|
||||
<p class="last-info-title">Last Login</p>
|
||||
<p class="last-info-title">{{$t('m.Last_Login')}}</p>
|
||||
<el-form label-width="80px" class="last-info-body">
|
||||
<el-form-item label="Time:">
|
||||
<span>{{session.last_activity | localtime}}</span>
|
||||
@ -30,19 +30,19 @@
|
||||
</el-form>
|
||||
</div>
|
||||
</el-card>
|
||||
<panel title="System Overview" v-if="isSuperAdmin">
|
||||
<p>Judge Server: {{infoData.judge_server_count}}</p>
|
||||
<p>HTTPS Status:
|
||||
<panel :title="$t('m.System_Overview')" v-if="isSuperAdmin">
|
||||
<p>{{$t('m.DashBoardJudge_Server')}}: {{infoData.judge_server_count}}</p>
|
||||
<p>{{$t('m.HTTPS_Status')}}:
|
||||
<el-tag :type="https ? 'success' : 'danger'" size="small">
|
||||
{{ https ? 'Enabled' : 'Disabled'}}
|
||||
</el-tag>
|
||||
</p>
|
||||
<p>Force HTTPS:
|
||||
<p>{{$t('m.Force_HTTPS')}}:
|
||||
<el-tag :type="forceHttps ? 'success' : 'danger'" size="small">
|
||||
{{forceHttps ? 'Enabled' : 'Disabled'}}
|
||||
</el-tag>
|
||||
</p>
|
||||
<p>CDN HOST:
|
||||
<p>{{$t('m.CDN_HOST')}}:
|
||||
<el-tag :type="cdn ? 'success' : 'warning'" size="small">
|
||||
{{cdn ? cdn : 'Not Use'}}
|
||||
</el-tag>
|
||||
@ -70,7 +70,7 @@
|
||||
</el-popover>
|
||||
</span>
|
||||
|
||||
<el-collapse v-model="activeNames" v-for="release, index in releases" :key="'release' + index">
|
||||
<el-collapse v-model="activeNames" v-for="(release, index) of releases" :key="'release' + index">
|
||||
<el-collapse-item :name="index+1">
|
||||
<template slot="title">
|
||||
<div v-if="release.new_version">{{release.title}}
|
||||
@ -81,7 +81,7 @@
|
||||
<p>Level: {{release.level}}</p>
|
||||
<p>Details: </p>
|
||||
<div class="release-body">
|
||||
<ul v-for="detail in release.details">
|
||||
<ul v-for="detail in release.details" :key="detail">
|
||||
<li v-html="detail"></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="view">
|
||||
<Panel title="Judge Server Token">
|
||||
<Panel :title="$t('m.Judge_Server_Token')">
|
||||
<code>{{ token }}</code>
|
||||
</Panel>
|
||||
<Panel title="Judge Server">
|
||||
<Panel :title="$t('m.Judge_Server_Info')">
|
||||
<el-table
|
||||
:data="servers"
|
||||
:default-expand-all="true"
|
||||
@ -11,14 +11,14 @@
|
||||
<el-table-column
|
||||
type="expand">
|
||||
<template slot-scope="props">
|
||||
<p>IP:
|
||||
<p>{{$t('m.IP')}}:
|
||||
<el-tag type="success">{{ props.row.ip }}</el-tag>
|
||||
Judger Version:
|
||||
{{$t('m.Judger_Version')}}:
|
||||
<el-tag type="success">{{ props.row.judger_version }}</el-tag>
|
||||
</p>
|
||||
<p>Service URL: <code>{{ props.row.service_url }}</code></p>
|
||||
<p>Last Heartbeat: {{ props.row.last_heartbeat | localtime}}</p>
|
||||
<p>Create Time: {{ props.row.create_time | localtime }}</p>
|
||||
<p>{{$t('m.Service_URL')}}: <code>{{ props.row.service_url }}</code></p>
|
||||
<p>{{$t('m.Last_Heartbeat')}}: {{ props.row.last_heartbeat | localtime}}</p>
|
||||
<p>{{$t('m.Create_Time')}}: {{ props.row.create_time | localtime }}</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<panel>
|
||||
<span slot="title">Prune Test Case
|
||||
<span slot="title">{{$t('m.Test_Case_Prune_Test_Case')}}
|
||||
<el-popover placement="right" trigger="hover">
|
||||
These test cases are not owned by any problem, you can clean them safely.
|
||||
<i slot="reference" class="el-icon-fa-question-circle import-user-icon"></i>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="view">
|
||||
<Panel title="User ">
|
||||
<Panel :title="$t('m.User_User') ">
|
||||
<div slot="header">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
@ -68,7 +68,7 @@
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<span slot="title">Import User
|
||||
<span slot="title">{{$t('m.Import_User')}}
|
||||
<el-popover placement="right" trigger="hover">
|
||||
<p>Only support csv file without headers, check the <a
|
||||
href="http://docs.onlinejudge.me/#/onlinejudge/guide/import_users">link</a> for details</p>
|
||||
@ -120,7 +120,7 @@
|
||||
</template>
|
||||
</Panel>
|
||||
|
||||
<Panel title="Generate User">
|
||||
<Panel :title="$t('m.Generate_User')">
|
||||
<el-form :model="formGenerateUser" ref="formGenerateUser">
|
||||
<el-row type="flex" justify="space-between">
|
||||
<el-col :span="4">
|
||||
@ -152,7 +152,7 @@
|
||||
</el-row>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="generateUser" icon="el-icon-fa-users" :loading="loadingGenerate">Generate
|
||||
<el-button type="primary" @click="generateUser" icon="el-icon-fa-users" :loading="loadingGenerate">Generate & Export
|
||||
</el-button>
|
||||
<span class="userPreview" v-if="formGenerateUser.number_from && formGenerateUser.number_to &&
|
||||
formGenerateUser.number_from <= formGenerateUser.number_to">
|
||||
@ -168,31 +168,31 @@
|
||||
</el-form>
|
||||
</Panel>
|
||||
<!--对话框-->
|
||||
<el-dialog title="User" :visible.sync="showUserDialog" :close-on-click-modal="false">
|
||||
<el-dialog :title="$t('m.User_Info')" :visible.sync="showUserDialog" :close-on-click-modal="false">
|
||||
<el-form :model="user" label-width="120px" label-position="left">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Username" required>
|
||||
<el-form-item :label="$t('m.User_Username')" required>
|
||||
<el-input v-model="user.username"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Real Name" required>
|
||||
<el-form-item :label="$t('m.User_Real_Name')" required>
|
||||
<el-input v-model="user.real_name"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Email" required>
|
||||
<el-form-item :label="$t('m.User_Email')" required>
|
||||
<el-input v-model="user.email"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="New Password">
|
||||
<el-form-item :label="$t('m.User_New_Password')">
|
||||
<el-input v-model="user.password"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="User Type">
|
||||
<el-form-item :label="$t('m.User_Type')">
|
||||
<el-select v-model="user.admin_type">
|
||||
<el-option label="Regular User" value="Regular User"></el-option>
|
||||
<el-option label="Admin" value="Admin"></el-option>
|
||||
@ -201,7 +201,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Problem Permission">
|
||||
<el-form-item :label="$t('m.Problem_Permission')">
|
||||
<el-select v-model="user.problem_permission" :disabled="user.admin_type!=='Admin'">
|
||||
<el-option label="None" value="None"></el-option>
|
||||
<el-option label="Own" value="Own"></el-option>
|
||||
@ -210,7 +210,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Two Factor Auth">
|
||||
<el-form-item :label="$t('m.Two_Factor_Auth')">
|
||||
<el-switch
|
||||
v-model="user.two_factor_auth"
|
||||
:disabled="!user.real_tfa"
|
||||
@ -229,7 +229,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Is Disabled">
|
||||
<el-form-item :label="$t('m.Is_Disabled')">
|
||||
<el-switch
|
||||
v-model="user.is_disabled"
|
||||
active-text=""
|
||||
|
@ -5,50 +5,50 @@
|
||||
<el-form ref="form" :model="problem" :rules="rules" label-position="top" label-width="70px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item prop="_id" label="Display ID"
|
||||
<el-form-item prop="_id" :label="$t('m.Display_ID')"
|
||||
:required="this.routeName === 'create-contest-problem' || this.routeName === 'edit-contet-problem'">
|
||||
<el-input placeholder="Display ID" v-model="problem._id"></el-input>
|
||||
<el-input :placeholder="$t('m.Display_ID')" v-model="problem._id"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-form-item prop="title" label="Title" required>
|
||||
<el-input placeholder="Title" v-model="problem.title"></el-input>
|
||||
<el-form-item prop="title" :label="$t('m.Title')" required>
|
||||
<el-input :placeholder="$t('m.Title')" v-model="problem.title"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="description" label="Description" required>
|
||||
<el-form-item prop="description" :label="$t('m.Description')" required>
|
||||
<Simditor v-model="problem.description"></Simditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="input_description" label="Input Description" required>
|
||||
<el-form-item prop="input_description" :label="$t('m.Input_Description')" required>
|
||||
<Simditor v-model="problem.input_description"></Simditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="output_description" label="Output Description" required>
|
||||
<el-form-item prop="output_description" :label="$t('m.Output_Description')" required>
|
||||
<Simditor v-model="problem.output_description"></Simditor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Time Limit" required>
|
||||
<el-input type="Number" placeholder="Time Limit" v-model="problem.time_limit"></el-input>
|
||||
<el-form-item :label="$t('m.Time_Limit')" required>
|
||||
<el-input type="Number" :placeholder="$t('m.Time_Limit')" v-model="problem.time_limit"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Memory limit" required>
|
||||
<el-input type="Number" placeholder="Memory Limit" v-model="problem.memory_limit"></el-input>
|
||||
<el-form-item :label="$t('m.Memory_limit')" required>
|
||||
<el-input type="Number" :placeholder="$t('m.Memory_limit')" v-model="problem.memory_limit"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Difficulty">
|
||||
<el-select class="difficulty-select" size="small" placeholder="Difficulty" v-model="problem.difficulty">
|
||||
<el-form-item :label="$t('m.Difficulty')">
|
||||
<el-select class="difficulty-select" size="small" :placeholder="$t('m.Difficulty')" v-model="problem.difficulty">
|
||||
<el-option label="Low" value="Low"></el-option>
|
||||
<el-option label="Mid" value="Mid"></el-option>
|
||||
<el-option label="High" value="High"></el-option>
|
||||
@ -58,7 +58,7 @@
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="Visible">
|
||||
<el-form-item :label="$t('m.Visible')">
|
||||
<el-switch
|
||||
v-model="problem.visible"
|
||||
active-text=""
|
||||
@ -92,7 +92,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Languages" :error="error.languages" required>
|
||||
<el-form-item :label="$t('m.Languages')" :error="error.languages" required>
|
||||
<el-checkbox-group v-model="problem.languages">
|
||||
<el-tooltip class="spj-radio" v-for="lang in allLanguage.languages" :key="'spj'+lang.name" effect="dark"
|
||||
:content="lang.description" placement="top-start">
|
||||
@ -110,21 +110,21 @@
|
||||
</el-button>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Input Samples" required>
|
||||
<el-form-item :label="$t('m.Input_Samples')" required>
|
||||
<el-input
|
||||
:rows="5"
|
||||
type="textarea"
|
||||
placeholder="Input Samples"
|
||||
:placeholder="$t('m.Input_Samples')"
|
||||
v-model="sample.input">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Output Samples" required>
|
||||
<el-form-item :label="$t('m.Output_Samples')" required>
|
||||
<el-input
|
||||
:rows="5"
|
||||
type="textarea"
|
||||
placeholder="Output Samples"
|
||||
:placeholder="$t('m.Output_Samples')"
|
||||
v-model="sample.output">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
@ -134,10 +134,10 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="add-sample-btn">
|
||||
<button type="button" class="add-samples" @click="addSample()"><i class="el-icon-plus"></i>Add Sample
|
||||
<button type="button" class="add-samples" @click="addSample()"><i class="el-icon-plus"></i>{{$t('m.Add_Sample')}}
|
||||
</button>
|
||||
</div>
|
||||
<el-form-item label="Code Template">
|
||||
<el-form-item :label="$t('m.Code_Template')">
|
||||
<el-row>
|
||||
<el-col :span="24" v-for="(v, k) in template" :key="'template'+k">
|
||||
<el-form-item>
|
||||
@ -149,15 +149,15 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="Special Judge" :error="error.spj">
|
||||
<el-form-item :label="$t('m.Special_Judge')" :error="error.spj">
|
||||
<el-col :span="24">
|
||||
<el-checkbox v-model="problem.spj" @click.native.prevent="switchSpj()">Use Special Judge</el-checkbox>
|
||||
<el-checkbox v-model="problem.spj" @click.native.prevent="switchSpj()">{{$t('m.Use_Special_Judge')}}</el-checkbox>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="problem.spj">
|
||||
<Accordion title="Special Judge Code">
|
||||
<Accordion :title="$t('m.Special_Judge_Code')">
|
||||
<template slot="header">
|
||||
<span>SPJ language</span>
|
||||
<span>{{$t('m.SPJ_language')}}</span>
|
||||
<el-radio-group v-model="problem.spj_language">
|
||||
<el-tooltip class="spj-radio" v-for="lang in allLanguage.spj_languages" :key="lang.name" effect="dark"
|
||||
:content="lang.description" placement="top-start">
|
||||
@ -166,7 +166,7 @@
|
||||
</el-radio-group>
|
||||
<el-button type="primary" size="small" icon="el-icon-fa-random" @click="compileSPJ"
|
||||
:loading="loadingCompile">
|
||||
Compile
|
||||
{{$t('m.Compile')}}
|
||||
</el-button>
|
||||
</template>
|
||||
<code-mirror v-model="problem.spj_code" :mode="spjMode"></code-mirror>
|
||||
@ -174,7 +174,7 @@
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="4">
|
||||
<el-form-item label="TestCase" :error="error.testcase">
|
||||
<el-form-item :label="$t('m.TestCase')" :error="error.testcase">
|
||||
<el-upload
|
||||
action="/api/admin/test_case"
|
||||
name="file"
|
||||
@ -187,7 +187,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="Type">
|
||||
<el-form-item :label="$t('m.Type')">
|
||||
<el-radio-group v-model="problem.rule_type" :disabled="disableRuleType">
|
||||
<el-radio label="ACM">ACM</el-radio>
|
||||
<el-radio label="OI">OI</el-radio>
|
||||
@ -200,19 +200,19 @@
|
||||
style="width: 100%">
|
||||
<el-table-column
|
||||
prop="input_name"
|
||||
label="Input">
|
||||
:label="$t('m.Input')">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="output_name"
|
||||
label="Output">
|
||||
:label="$t('m.Output')">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="score"
|
||||
label="Score">
|
||||
:label="$t('m.Score')">
|
||||
<template slot-scope="scope">
|
||||
<el-input
|
||||
size="small"
|
||||
placeholder="Score"
|
||||
:placeholder="$t('m.Score')"
|
||||
v-model="scope.row.score"
|
||||
:disabled="problem.rule_type !== 'OI'">
|
||||
</el-input>
|
||||
@ -221,11 +221,11 @@
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item style="margin-top: 20px" label="Hint">
|
||||
<el-form-item style="margin-top: 20px" :label="$t('m.Hint')">
|
||||
<Simditor v-model="problem.hint" placeholder=""></Simditor>
|
||||
</el-form-item>
|
||||
<el-form-item label="Source">
|
||||
<el-input placeholder="Source" v-model="problem.source"></el-input>
|
||||
<el-form-item :label="$t('m.Source')">
|
||||
<el-input :placeholder="$t('m.Source')" v-model="problem.source"></el-input>
|
||||
</el-form-item>
|
||||
<save @click.native="submit()">Save</save>
|
||||
</el-form>
|
||||
|
@ -6,7 +6,8 @@
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
<div class="footer">
|
||||
<p v-html="website.website_footer"></p>
|
||||
<Button type="text" class="btn btn-success" @click="changeLocale()">简体中文 / English</Button>
|
||||
<p v-html="website.website_footer"></p>
|
||||
<p>Powered by <a href="https://github.com/QingdaoU/OnlineJudge">OnlineJudge</a>
|
||||
<span v-if="version"> Version: {{ version }}</span>
|
||||
</p>
|
||||
@ -40,7 +41,15 @@
|
||||
this.getWebsiteConfig()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['getWebsiteConfig', 'changeDomTitle'])
|
||||
...mapActions(['getWebsiteConfig', 'changeDomTitle']),
|
||||
changeLocale () {
|
||||
// 通过默认locale切换语言
|
||||
if (this.$i18n.locale === 'zh-CN') {
|
||||
this.$i18n.locale = 'en-US'
|
||||
} else {
|
||||
this.$i18n.locale = 'zh-CN'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['website'])
|
||||
|
@ -4,42 +4,42 @@
|
||||
<div class="logo"><span>{{website.website_name}}</span></div>
|
||||
<Menu-item name="/">
|
||||
<Icon type="home"></Icon>
|
||||
Home
|
||||
{{$t('m.Home')}}
|
||||
</Menu-item>
|
||||
<Menu-item name="/problems">
|
||||
<Icon type="ios-keypad"></Icon>
|
||||
Problems
|
||||
{{$t('m.NavProblems')}}
|
||||
</Menu-item>
|
||||
<Menu-item name="/contests">
|
||||
<Icon type="trophy"></Icon>
|
||||
Contests
|
||||
{{$t('m.Contests')}}
|
||||
</Menu-item>
|
||||
<Menu-item name="/status">
|
||||
<Icon type="ios-pulse-strong"></Icon>
|
||||
Status
|
||||
{{$t('m.NavStatus')}}
|
||||
</Menu-item>
|
||||
<Submenu name="">
|
||||
<template slot="title">
|
||||
<Icon type="podium"></Icon>
|
||||
Rank
|
||||
{{$t('m.Rank')}}
|
||||
</template>
|
||||
<Menu-item name="/acm-rank">
|
||||
ACM Rank
|
||||
{{$t('m.ACM_Rank')}}
|
||||
</Menu-item>
|
||||
<Menu-item name="/oi-rank">
|
||||
OI Rank
|
||||
{{$t('m.OI_Rank')}}
|
||||
</Menu-item>
|
||||
</Submenu>
|
||||
<Submenu name="">
|
||||
<template slot="title">
|
||||
<Icon type="information-circled"></Icon>
|
||||
About
|
||||
{{$t('m.About')}}
|
||||
</template>
|
||||
<Menu-item name="/about">
|
||||
Judger
|
||||
{{$t('m.Judger')}}
|
||||
</Menu-item>
|
||||
<Menu-item name="/FAQ">
|
||||
FAQ
|
||||
{{$t('m.FAQ')}}
|
||||
</Menu-item>
|
||||
</Submenu>
|
||||
<template v-if="!isAuthenticated">
|
||||
@ -47,13 +47,13 @@
|
||||
<Button type="ghost"
|
||||
ref="loginBtn"
|
||||
shape="circle"
|
||||
@click="handleBtnClick('login')">Login
|
||||
@click="handleBtnClick('login')">{{$t('m.Login')}}
|
||||
</Button>
|
||||
<Button v-if="website.allow_register"
|
||||
type="ghost"
|
||||
shape="circle"
|
||||
@click="handleBtnClick('register')"
|
||||
style="margin-left: 5px;">Register
|
||||
style="margin-left: 5px;">{{$t('m.Register')}}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
@ -63,11 +63,11 @@
|
||||
<Icon type="arrow-down-b"></Icon>
|
||||
</Button>
|
||||
<Dropdown-menu slot="list">
|
||||
<Dropdown-item name="/user-home">Home</Dropdown-item>
|
||||
<Dropdown-item name="/status?myself=1">Submissions</Dropdown-item>
|
||||
<Dropdown-item name="/setting/profile">Settings</Dropdown-item>
|
||||
<Dropdown-item v-if="isAdminRole" name="/admin">Management</Dropdown-item>
|
||||
<Dropdown-item divided name="/logout">Logout</Dropdown-item>
|
||||
<Dropdown-item name="/user-home">{{$t('m.MyHome')}}</Dropdown-item>
|
||||
<Dropdown-item name="/status?myself=1">{{$t('m.MySubmissions')}}</Dropdown-item>
|
||||
<Dropdown-item name="/setting/profile">{{$t('m.Settings')}}</Dropdown-item>
|
||||
<Dropdown-item v-if="isAdminRole" name="/admin">{{$t('m.Management')}}</Dropdown-item>
|
||||
<Dropdown-item divided name="/logout">{{$t('m.Logout')}}</Dropdown-item>
|
||||
</Dropdown-menu>
|
||||
</Dropdown>
|
||||
</template>
|
||||
@ -151,10 +151,12 @@
|
||||
}
|
||||
|
||||
.drop-menu {
|
||||
float: right;
|
||||
margin-right: 30px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
&-title {
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
.btn-menu {
|
||||
|
@ -4,11 +4,11 @@ import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from '@/store'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import locale from 'iview/src/locale/lang/en-US'
|
||||
import VueAnalytics from 'vue-analytics'
|
||||
import { GOOGLE_ANALYTICS_ID } from '@/utils/constants'
|
||||
|
||||
import iView from 'iview'
|
||||
import locale from 'iview/dist/locale/en-US'
|
||||
import 'iview/dist/styles/iview.css'
|
||||
|
||||
import Panel from '@oj/components/Panel.vue'
|
||||
@ -18,6 +18,7 @@ import '@/styles/index.less'
|
||||
|
||||
import highlight from '@/plugins/highlight'
|
||||
import katex from '@/plugins/katex'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import filters from '@/utils/filters.js'
|
||||
|
||||
import ECharts from 'vue-echarts/components/ECharts.vue'
|
||||
@ -39,6 +40,8 @@ Object.keys(filters).forEach(key => {
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(iView, {locale})
|
||||
Vue.use(VueI18n)
|
||||
|
||||
Vue.use(VueClipboard)
|
||||
Vue.use(highlight)
|
||||
Vue.use(katex)
|
||||
@ -47,6 +50,15 @@ Vue.use(VueAnalytics, {
|
||||
router
|
||||
})
|
||||
|
||||
// load language packages
|
||||
const i18n = new VueI18n({
|
||||
locale: 'zh-CN',
|
||||
messages: {
|
||||
'en-US': require('../../i18n/oj/en-US'),
|
||||
'zh-CN': require('../../i18n/oj/zh-CN')
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('ECharts', ECharts)
|
||||
Vue.component(VerticalMenu.name, VerticalMenu)
|
||||
Vue.component(VerticalMenuItem.name, VerticalMenuItem)
|
||||
@ -60,4 +72,4 @@ Vue.prototype.$error = (s) => Vue.prototype.$Message.error(s)
|
||||
Vue.prototype.$info = (s) => Vue.prototype.$Message.info(s)
|
||||
Vue.prototype.$success = (s) => Vue.prototype.$Message.success(s)
|
||||
|
||||
new Vue(Vue.util.extend({router, store}, App)).$mount('#app')
|
||||
new Vue(Vue.util.extend({router, store, i18n}, App)).$mount('#app')
|
||||
|
@ -36,41 +36,39 @@
|
||||
<VerticalMenu @on-click="handleRoute">
|
||||
<VerticalMenu-item :route="{name: 'contest-details', params: {contestID: contestID}}">
|
||||
<Icon type="home"></Icon>
|
||||
Overview
|
||||
{{$t('m.Overview')}}
|
||||
</VerticalMenu-item>
|
||||
|
||||
<VerticalMenu-item :disabled="contestMenuDisabled"
|
||||
:route="{name: 'contest-announcement-list', params: {contestID: contestID}}">
|
||||
<Icon type="chatbubble-working"></Icon>
|
||||
Announcements
|
||||
{{$t('m.Announcements')}}
|
||||
</VerticalMenu-item>
|
||||
|
||||
<VerticalMenu-item :disabled="contestMenuDisabled"
|
||||
:route="{name: 'contest-problem-list', params: {contestID: contestID}}">
|
||||
<Icon type="ios-photos"></Icon>
|
||||
Problems
|
||||
{{$t('m.Problems')}}
|
||||
</VerticalMenu-item>
|
||||
|
||||
<VerticalMenu-item v-if="OIContestRealTimePermission"
|
||||
:disabled="contestMenuDisabled"
|
||||
:route="{name: 'contest-submission-list'}">
|
||||
<Icon type="navicon-round"></Icon>
|
||||
Submissions
|
||||
{{$t('m.Submissions')}}
|
||||
</VerticalMenu-item>
|
||||
|
||||
<VerticalMenu-item v-if="OIContestRealTimePermission"
|
||||
:disabled="contestMenuDisabled"
|
||||
:route="{name: 'contest-rank', params: {contestID: contestID}}">
|
||||
<Icon type="stats-bars"></Icon>
|
||||
Rankings
|
||||
{{$t('m.Rankings')}}
|
||||
</VerticalMenu-item>
|
||||
|
||||
|
||||
|
||||
<VerticalMenu-item v-if="showAdminHelper"
|
||||
:route="{name: 'acm-helper', params: {contestID: contestID}}">
|
||||
<Icon type="ios-paw"></Icon>
|
||||
Admin Helper
|
||||
{{$t('m.Admin_Helper')}}
|
||||
</VerticalMenu-item>
|
||||
</VerticalMenu>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<Panel>
|
||||
<div slot="title">Problems List</div>
|
||||
<div slot="title">{{$t('m.Problems_List')}}</div>
|
||||
<Table v-if="contestRuleType == 'ACM' || OIContestRealTimePermission"
|
||||
:columns="ACMTableColumns"
|
||||
:data="problems"
|
||||
|
@ -4,13 +4,13 @@
|
||||
{{title}}
|
||||
</div>
|
||||
<div slot="extra">
|
||||
<Button v-if="listVisible" type="info" @click="init" :loading="btnLoading">Refresh</Button>
|
||||
<Button v-else type="ghost" icon="ios-undo" @click="goBack">Back</Button>
|
||||
<Button v-if="listVisible" type="info" @click="init" :loading="btnLoading">{{$t('m.Refresh')}}</Button>
|
||||
<Button v-else type="ghost" icon="ios-undo" @click="goBack">{{$t('m.Back')}}</Button>
|
||||
</div>
|
||||
|
||||
<transition-group name="announcement-animate" mode="in-out">
|
||||
<div class="no-announcement" v-if="!announcements.length" key="no-announcement">
|
||||
<p>No announcements</p>
|
||||
<p>{{$t('m.No_Announcements')}}</p>
|
||||
</div>
|
||||
<template v-if="listVisible">
|
||||
<ul class="announcements-container" key="list">
|
||||
@ -163,7 +163,7 @@
|
||||
.no-announcement {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
}changeLocale
|
||||
|
||||
.announcement-animate-enter-active {
|
||||
animation: fadeIn 1s;
|
||||
|
@ -6,7 +6,7 @@
|
||||
<Button type="text" class="contest-title" @click="goContest">{{contests[index].title}}</Button>
|
||||
</div>
|
||||
<Carousel v-model="index" trigger="hover" autoplay :autoplay-speed="6000" class="contest">
|
||||
<CarouselItem v-for="contest, index in contests" :key="index">
|
||||
<CarouselItem v-for="(contest, index) of contests" :key="index">
|
||||
<div class="contest-content">
|
||||
<div class="contest-content-tags">
|
||||
<Button type="info" shape="circle" size="small" icon="calendar">
|
||||
|
@ -15,20 +15,20 @@
|
||||
<div slot="title">Result Explanation</div>
|
||||
<div class="content">
|
||||
<ul>
|
||||
<li><b>Pending & Juding</b> : You solution will be judged soon, please wait for result</li>
|
||||
<li><b>Compile Error</b> : Failed to compile your source code. Click on the link to see compiler's output.
|
||||
<li><b>Pending & Juding</b> : {{$t('m.Pending_Juding')}}</li>
|
||||
<li><b>Compile Error</b> : {{$t('m.Compile_Error')}}
|
||||
</li>
|
||||
<li><b>Accepted</b> : Congratulations. Your solution is correct.</li>
|
||||
<li><b>Wrong Answer</b> : Your program's output doesn't match judger's answer.</li>
|
||||
<li><b>Accepted</b> : {{$t('m.Accepted')}}</li>
|
||||
<li><b>Wrong Answer</b> : {{$t('m.Wrong_Answer')}}</li>
|
||||
<li>
|
||||
<b>Runtime Error</b>
|
||||
: Your program terminated abnormally. Possible reasons are: segment fault, divided by zero or exited with code other than 0.
|
||||
: {{$t('m.Runtime_Error')}}
|
||||
</li>
|
||||
<li><b>Time Limit Exceeded</b>
|
||||
: The CPU time your program used has exceeded limit. Java has a triple time limit.
|
||||
: {{$t('m.Time_Limit_Exceeded')}}
|
||||
</li>
|
||||
<li><b>Memory Limit Exceeded</b> : The memory your program actually used has exceeded limit.</li>
|
||||
<li><b>System Error</b> : Oops, something has gone wrong with the judger. Please report this to administrator.
|
||||
<li><b>Memory Limit Exceeded</b> : {{$t('m.Memory_Limit_Exceeded')}}</li>
|
||||
<li><b>System Error</b> : {{$t('m.System_Error')}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<panel>
|
||||
<div slot="title">Frequently Asked Questions</div>
|
||||
<div slot="title">{{$t('m.Frequently_Asked_Questions')}}</div>
|
||||
<div class="content markdown-body">
|
||||
<ul>
|
||||
<li>Where is the input and the output?
|
||||
|
@ -5,19 +5,19 @@
|
||||
<Panel :padding="40" shadow>
|
||||
<div slot="title">{{problem.title}}</div>
|
||||
<div id="problem-content" class="markdown-body" v-katex>
|
||||
<p class="title">Description</p>
|
||||
<p class="title">{{$t('m.Description')}}</p>
|
||||
<p class="content" v-html=problem.description></p>
|
||||
|
||||
<p class="title">Input</p>
|
||||
<!-- {{$t('m.music')}} -->
|
||||
<p class="title">{{$t('m.Input')}}</p>
|
||||
<p class="content" v-html=problem.input_description></p>
|
||||
|
||||
<p class="title">Output</p>
|
||||
<p class="title">{{$t('m.Output')}}</p>
|
||||
<p class="content" v-html=problem.output_description></p>
|
||||
|
||||
<div v-for="sample, index in problem.samples">
|
||||
<div v-for="(sample, index) of problem.samples" :key="index">
|
||||
<div class="flex-container sample">
|
||||
<div class="sample-input">
|
||||
<p class="title">Sample Input {{index + 1}}
|
||||
<p class="title">{{$t('m.Sample_Input')}} {{index + 1}}
|
||||
<a class="copy"
|
||||
v-clipboard:copy="sample.input"
|
||||
v-clipboard:success="onCopy"
|
||||
@ -28,21 +28,21 @@
|
||||
<pre>{{sample.input}}</pre>
|
||||
</div>
|
||||
<div class="sample-output">
|
||||
<p class="title">Sample Output {{index + 1}}</p>
|
||||
<p class="title">{{$t('m.Sample_Output')}} {{index + 1}}</p>
|
||||
<pre>{{sample.output}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="problem.hint">
|
||||
<p class="title">Hint</p>
|
||||
<p class="title">{{$t('m.Hint')}}</p>
|
||||
<Card dis-hover>
|
||||
<div class="content" v-html=problem.hint></div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div v-if="problem.source">
|
||||
<p class="title">Source</p>
|
||||
<p class="title">{{$t('m.Source')}}</p>
|
||||
<p class="content">{{problem.source}}</p>
|
||||
</div>
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
<Col :span="10">
|
||||
<div class="status" v-if="statusVisible">
|
||||
<template v-if="!this.contestID || (this.contestID && OIContestRealTimePermission)">
|
||||
<span>Status:</span>
|
||||
<span>{{$t('m.Status')}}</span>
|
||||
<Tag type="dot" :color="submissionStatus.color" @click.native="handleRoute('/status/'+submissionId)">
|
||||
{{submissionStatus.text}}
|
||||
</Tag>
|
||||
@ -130,29 +130,29 @@
|
||||
<Card id="info">
|
||||
<div slot="title" class="header">
|
||||
<Icon type="information-circled"></Icon>
|
||||
<span class="card-title">Information</span>
|
||||
<span class="card-title">{{$t('m.Information')}}</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li><p>ID</p>
|
||||
<p>{{problem._id}}</p></li>
|
||||
<li>
|
||||
<p>Time Limit</p>
|
||||
<p>{{$t('m.Time_Limit')}}</p>
|
||||
<p>{{problem.time_limit}}MS</p></li>
|
||||
<li>
|
||||
<p>Memory Limit</p>
|
||||
<p>{{$t('m.Memory_Limit')}}</p>
|
||||
<p>{{problem.memory_limit}}MB</p></li>
|
||||
<li>
|
||||
<p>Created By</p>
|
||||
<p>{{$t('m.Created')}}</p>
|
||||
<p>{{problem.created_by.username}}</p></li>
|
||||
<li v-if="problem.difficulty">
|
||||
<p>Level</p>
|
||||
<p>{{$t('m.Level')}}</p>
|
||||
<p>{{problem.difficulty}}</p></li>
|
||||
<li v-if="problem.total_score">
|
||||
<p>Score</p>
|
||||
<p>{{$t('m.Score')}}</p>
|
||||
<p>{{problem.total_score}}</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Tags</p>
|
||||
<p>{{$t('m.Tags')}}</p>
|
||||
<p>
|
||||
<Poptip trigger="hover" placement="left-end">
|
||||
<a>Show</a>
|
||||
|
@ -18,9 +18,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Menu-item name="/setting/profile">Profile</Menu-item>
|
||||
<Menu-item name="/setting/account">Account</Menu-item>
|
||||
<Menu-item name="/setting/security">Security</Menu-item>
|
||||
<Menu-item name="/setting/profile">{{$t('m.Profile')}}</Menu-item>
|
||||
<Menu-item name="/setting/account">{{$t('m.Account')}}</Menu-item>
|
||||
<Menu-item name="/setting/security">{{$t('m.Security')}}</Menu-item>
|
||||
</Menu>
|
||||
</div>
|
||||
<div class="panel">
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="setting-main">
|
||||
<div class="flex-container">
|
||||
<div class="left">
|
||||
<p class="section-title">Change Password</p>
|
||||
<p class="section-title">{{$t('m.ChangePassword')}}</p>
|
||||
<Form class="setting-content" ref="formPassword" :model="formPassword" :rules="rulePassword">
|
||||
<FormItem label="Old Password" prop="old_password">
|
||||
<Input v-model="formPassword.old_password" type="password"/>
|
||||
@ -19,14 +19,14 @@
|
||||
<FormItem v-if="visible.passwordAlert">
|
||||
<Alert type="success">You will need to login again after 5 seconds..</Alert>
|
||||
</FormItem>
|
||||
<Button type="primary" @click="changePassword">Update Password</Button>
|
||||
<Button type="primary" @click="changePassword">{{$t('m.Update_Password')}}</Button>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div class="middle separator"></div>
|
||||
|
||||
<div class="right">
|
||||
<p class="section-title">Change Email</p>
|
||||
<p class="section-title">{{$t('m.ChangeEmail')}}</p>
|
||||
<Form class="setting-content" ref="formEmail" :model="formEmail" :rules="ruleEmail">
|
||||
<FormItem label="Current Password" prop="password">
|
||||
<Input v-model="formEmail.password" type="password"/>
|
||||
@ -40,7 +40,7 @@
|
||||
<FormItem v-if="visible.tfaRequired" label="Two Factor Auth" prop="tfa_code">
|
||||
<Input v-model="formEmail.tfa_code"/>
|
||||
</FormItem>
|
||||
<Button type="primary" @click="changeEmail">Change Email</Button>
|
||||
<Button type="primary" @click="changeEmail">{{$t('m.ChangeEmail')}}</Button>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="setting-main">
|
||||
<div class="section-title">Avatar Setting</div>
|
||||
<div class="section-title">{{$t('m.Avatar_Setting')}}</div>
|
||||
<template v-if="!avatarOption.imgSrc">
|
||||
<Upload type="drag"
|
||||
class="mini-container"
|
||||
@ -62,7 +62,7 @@
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<div class="section-title">Profile Setting</div>
|
||||
<div class="section-title">{{$t('m.Profile_Setting')}}</div>
|
||||
<Form ref="formProfile" :model="formProfile">
|
||||
<Row type="flex" :gutter="30" justify="space-around">
|
||||
<Col :span="11">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="setting-main">
|
||||
<p class="section-title">Sessions</p>
|
||||
<p class="section-title">{{$t('m.Sessions')}}</p>
|
||||
<div class="flex-container setting-content">
|
||||
<template v-for="session in sessions">
|
||||
<Card :padding="20" class="flex-child">
|
||||
@ -28,7 +28,7 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<p class="section-title">Two Factor Authentication</p>
|
||||
<p class="section-title">{{$t('m.Two_Factor_Authentication')}}</p>
|
||||
<div class="mini-container setting-content">
|
||||
<Form>
|
||||
<Alert v-if="TFAOpened"
|
||||
|
@ -31,7 +31,7 @@
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Button type="info" icon="refresh" @click="getSubmissions">Refresh</Button>
|
||||
<Button type="info" icon="refresh" @click="getSubmissions">{{$t('m.Refresh')}}</Button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<Panel :padding="30" class="container">
|
||||
<div slot="title" class="center">Lost Password</div>
|
||||
<div slot="title" class="center">{{$t('m.Reset_Password')}}</div>
|
||||
<template v-if="!successApply">
|
||||
<Form :rules="ruleResetPassword" :model=formResetPassword ref="formResetPassword">
|
||||
<Form-item prop="email">
|
||||
<Input v-model="formResetPassword.email" placeholder="Your Email Address" size="large">
|
||||
<Input v-model="formResetPassword.email" :placeholder="$t('m.ApplyEmail')" size="large">
|
||||
<Icon type="ios-email-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</Form-item>
|
||||
<Form-item prop="captcha" style="margin-bottom:10px">
|
||||
<div class="oj-captcha">
|
||||
<div class="oj-captcha-code">
|
||||
<Input v-model="formResetPassword.captcha" placeholder="Captcha" size="large">
|
||||
<Input v-model="formResetPassword.captcha" :placeholder="$t('m.RCaptcha')" size="large">
|
||||
<Icon type="ios-lightbulb-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</div>
|
||||
@ -26,7 +26,7 @@
|
||||
<Button type="primary"
|
||||
@click="sendEmail"
|
||||
class="btn" long
|
||||
:loading="btnLoading">Send Password Reset Email
|
||||
:loading="btnLoading">{{$t('m.Send_Password_Reset_Email')}}
|
||||
</Button>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
@ -2,17 +2,17 @@
|
||||
<div>
|
||||
<Form ref="formLogin" :model="formLogin" :rules="ruleLogin">
|
||||
<FormItem prop="username">
|
||||
<Input type="text" v-model="formLogin.username" placeholder="Username" size="large" @on-enter="handleLogin">
|
||||
<Input type="text" v-model="formLogin.username" :placeholder="$t('m.LoginUsername')" size="large" @on-enter="handleLogin">
|
||||
<Icon type="ios-person-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<Input type="password" v-model="formLogin.password" placeholder="Password" size="large" @on-enter="handleLogin">
|
||||
<Input type="password" v-model="formLogin.password" :placeholder="$t('m.LoginPassword')" size="large" @on-enter="handleLogin">
|
||||
<Icon type="ios-locked-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="tfa_code" v-if="tfaRequired">
|
||||
<Input v-model="formLogin.tfa_code" placeholder="Code from your TFA app">
|
||||
<Input v-model="formLogin.tfa_code" :placeholder="$t('m.TFA_Code')">
|
||||
<Icon type="ios-lightbulb-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
@ -23,10 +23,10 @@
|
||||
@click="handleLogin"
|
||||
class="btn" long
|
||||
:loading="btnLoginLoading">
|
||||
Login
|
||||
{{$t('m.UserLogin')}}
|
||||
</Button>
|
||||
<a v-if="website.allow_register" @click.stop="handleBtnClick('register')">No account? Register now!</a>
|
||||
<a @click.stop="goResetPassword" style="float: right">Forget Password</a>
|
||||
<a v-if="website.allow_register" @click.stop="handleBtnClick('register')">{{$t('m.No_Account')}}</a>
|
||||
<a @click.stop="goResetPassword" style="float: right">{{$t('m.Forget_Password')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -2,29 +2,29 @@
|
||||
<div>
|
||||
<Form ref="formRegister" :model="formRegister" :rules="ruleRegister">
|
||||
<FormItem prop="username">
|
||||
<Input type="text" v-model="formRegister.username" placeholder="Username" size="large" @on-enter="handleRegister">
|
||||
<Input type="text" v-model="formRegister.username" :placeholder="$t('m.RegisterUsername')" size="large" @on-enter="handleRegister">
|
||||
<Icon type="ios-person-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="email">
|
||||
<Input v-model="formRegister.email" placeholder="Email Address" size="large" @on-enter="handleRegister">
|
||||
<Input v-model="formRegister.email" :placeholder="$t('m.Email_Address')" size="large" @on-enter="handleRegister">
|
||||
<Icon type="ios-email-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<Input type="password" v-model="formRegister.password" placeholder="Password" size="large" @on-enter="handleRegister">
|
||||
<Input type="password" v-model="formRegister.password" :placeholder="$t('m.RegisterPassword')" size="large" @on-enter="handleRegister">
|
||||
<Icon type="ios-locked-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="passwordAgain">
|
||||
<Input type="password" v-model="formRegister.passwordAgain" placeholder="Password Again" size="large" @on-enter="handleRegister">
|
||||
<Input type="password" v-model="formRegister.passwordAgain" :placeholder="$t('m.Password_Again')" size="large" @on-enter="handleRegister">
|
||||
<Icon type="ios-locked-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem prop="captcha" style="margin-bottom:10px">
|
||||
<div class="oj-captcha">
|
||||
<div class="oj-captcha-code">
|
||||
<Input v-model="formRegister.captcha" placeholder="Captcha" size="large" @on-enter="handleRegister">
|
||||
<Input v-model="formRegister.captcha" :placeholder="$t('m.Captcha')" size="large" @on-enter="handleRegister">
|
||||
<Icon type="ios-lightbulb-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</div>
|
||||
@ -42,13 +42,13 @@
|
||||
@click="handleRegister"
|
||||
class="btn" long
|
||||
:loading="btnRegisterLoading">
|
||||
Register
|
||||
{{$t('m.UserRegister')}}
|
||||
</Button>
|
||||
<Button
|
||||
type="ghost"
|
||||
@click="switchMode('login')"
|
||||
class="btn" long>
|
||||
Already registed? Login now!
|
||||
{{$t('m.Already_Registed')}}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<Panel :padding="30" class="container">
|
||||
<div slot="title" class="center">Reset Password</div>
|
||||
<div slot="title" class="center">{{$t('m.Reset_Password')}}</div>
|
||||
<template v-if="!resetSuccess">
|
||||
<Form :model=formResetPassword ref="formResetPassword" :rules="ruleResetPassword">
|
||||
<Form-item prop="password">
|
||||
<Input type="password" v-model="formResetPassword.password" placeholder="Password" size="large">
|
||||
<Input type="password" v-model="formResetPassword.password" :placeholder="$t('m.RPassword')" size="large">
|
||||
<Icon type="ios-locked-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</Form-item>
|
||||
<Form-item prop="passwordAgain">
|
||||
<Input type="password" v-model="formResetPassword.passwordAgain" placeholder="Password Again" size="large">
|
||||
<Input type="password" v-model="formResetPassword.passwordAgain" :placeholder="$t('m.RPassword_Again')" size="large">
|
||||
<Icon type="ios-locked-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</Form-item>
|
||||
<Form-item prop="captcha" style="margin-bottom:10px">
|
||||
<div id="captcha">
|
||||
<div id="captchaCode">
|
||||
<Input v-model="formResetPassword.captcha" placeholder="Captcha" size="large">
|
||||
<Input v-model="formResetPassword.captcha" :placeholder="$t('m.RCaptcha')" size="large">
|
||||
<Icon type="ios-lightbulb-outline" slot="prepend"></Icon>
|
||||
</Input>
|
||||
</div>
|
||||
|
@ -16,20 +16,20 @@
|
||||
|
||||
<div class="flex-container">
|
||||
<div class="left">
|
||||
<p>Solved</p>
|
||||
<p>{{$t('m.UserHomeSolved')}}</p>
|
||||
<p class="emphasis">{{profile.accepted_number}}</p>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<p>Submissions</p>
|
||||
<p>{{$t('m.UserHomeserSubmissions')}}</p>
|
||||
<p class="emphasis">{{profile.submission_number}}</p>
|
||||
</div>
|
||||
<div class="right">
|
||||
<p>Score</p>
|
||||
<p>{{$t('m.UserHomeScore')}}</p>
|
||||
<p class="emphasis">{{profile.total_score}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="problems">
|
||||
<div v-if="problems.length">List of solved problems
|
||||
<div v-if="problems.length">{{$t('m.List_Solved_Problems')}}
|
||||
<Poptip v-if="refreshVisible" trigger="hover" placement="right-start">
|
||||
<Icon type="ios-help-outline"></Icon>
|
||||
<div slot="content">
|
||||
@ -38,9 +38,9 @@
|
||||
</div>
|
||||
</Poptip>
|
||||
</div>
|
||||
<p v-else>The guy is so lazy that has not solved any problem yet.</p>
|
||||
<p v-else>{{$t('m.UserHomeIntro')}}</p>
|
||||
<div class="btns">
|
||||
<div class="problem-btn" v-for="problemID in problems">
|
||||
<div class="problem-btn" v-for="problemID of problems" :key="problemID">
|
||||
<Button type="ghost" @click="goProblem(problemID)">{{problemID}}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user