修改了从roller文件夹 #3

Closed
pav86znph wants to merge 0 commits from master into feature/lxh

25
.gitignore vendored

@ -1,25 +0,0 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
**/.idea

8
.idea/.gitignore vendored

@ -1,8 +0,0 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义XML文档的版本和编码 -->
<project version="4">
<!-- 定义项目版本 -->
<component name="CompilerConfiguration">
<!-- 定义编译器配置 -->
<annotationProcessing>
<!-- 定义注解处理 -->
<profile name="Maven default annotation processors profile" enabled="true">
<!-- 定义Maven默认注解处理器配置 -->
<sourceOutputDir name="target/generated-sources/annotations" />
<!-- 定义源代码输出目录 -->
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<!-- 定义测试代码输出目录 -->
<outputRelativeToContentRoot value="true" />
<!-- 定义输出目录相对于内容根目录 -->
<module name="exam" />
<!-- 定义模块名称 -->
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<!-- 定义Javac设置 -->
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<!-- 定义附加选项覆盖 -->
<module name="exam" options="-parameters" />
<!-- 定义模块名称和选项 -->
</option>
</component>
</project>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义XML文档的版本和编码 -->
<project version="4">
<!-- 定义项目版本 -->
<component name="Encoding">
<!-- 定义组件名称 -->
<file url="file://$PROJECT_DIR$/backend/src/main/java" charset="UTF-8" />
<!-- 定义文件路径和字符编码 -->
</component>
</project>

@ -1,69 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AliAccessStaticViaInstance" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliDeprecation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliEqualsAvoidNull" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliMissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AliWrapperTypeEquality" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaAvoidUseTimer" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaMethodTooLong" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPackageNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSneakyThrowsWithoutExceptionType" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaStringConcat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSwitchExpression" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadPoolCreation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaThreadShouldSetName" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义项目版本 -->
<project version="4">
<!-- 定义远程仓库配置 -->
<component name="RemoteRepositoriesConfiguration">
<!-- 定义第一个远程仓库 -->
<remote-repository>
<!-- 定义远程仓库ID -->
<option name="id" value="central" />
<!-- 定义远程仓库名称 -->
<option name="name" value="Central Repository" />
<!-- 定义远程仓库URL -->
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<!-- 定义第二个远程仓库 -->
<remote-repository>
<!-- 定义远程仓库ID -->
<option name="id" value="central" />
<!-- 定义远程仓库名称 -->
<option name="name" value="Maven Central repository" />
<!-- 定义远程仓库URL -->
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<!-- 定义第三个远程仓库 -->
<remote-repository>
<!-- 定义远程仓库ID -->
<option name="id" value="jboss.community" />
<!-- 定义远程仓库名称 -->
<option name="name" value="JBoss Community repository" />
<!-- 定义远程仓库URL -->
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 项目版本 -->
<project version="4">
<!-- 外部存储配置管理器 -->
<component name="ExternalStorageConfigurationManager" enabled="true" />
<!-- Maven项目管理器 -->
<component name="MavenProjectsManager">
<!-- 原始文件列表 -->
<option name="originalFiles">
<list>
<!-- 后端项目的pom.xml文件 -->
<option value="$PROJECT_DIR$/backend/pom.xml" />
</list>
</option>
</component>
<!-- 项目根管理器 -->
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK">
<!-- 输出目录 -->
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义XML文档的版本和编码 -->
<project version="4">
<!-- 定义项目的版本 -->
<component name="ProjectModuleManager">
<!-- 定义项目的模块管理器 -->
<modules>
<!-- 定义项目的模块 -->
<module fileurl="file://$PROJECT_DIR$/.idea/spring-boot-online-exam-master.iml" filepath="$PROJECT_DIR$/.idea/spring-boot-online-exam-master.iml" />
<!-- 定义项目的模块文件路径 -->
</modules>
</component>
</project>
<!-- 定义项目的根元素 -->

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/web" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义XML文档的版本和编码 -->
<project version="4">
<!-- 定义一个项目版本为4 -->
<component name="DdlMappings">
<!-- 定义一个组件名称为DdlMappings -->
<mapping uuid="3f2269d9-40c7-4022-bc5b-913dfbbc6cdc" name="@localhost Mapping">
<!-- 定义一个映射uuid为3f2269d9-40c7-4022-bc5b-913dfbbc6cdc名称为@localhost Mapping -->
<data-sources db="52ce0e2c-1ca8-4087-a535-1632d84f6e81" ddl="7ee42c98-c0b3-46e7-9153-4802360edee6" />
<!-- 定义数据源数据库为52ce0e2c-1ca8-4087-a535-1632d84f6e81DDL为7ee42c98-c0b3-46e7-9153-4802360edee6 -->
</mapping>
</component>
</project>

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义一个项目版本号为4 -->
<project version="4">
<!-- 定义一个组件名称为SqlDialectMappings -->
<component name="SqlDialectMappings">
<!-- 定义一个文件URL为PROJECT方言为MySQL -->
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

@ -1,201 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<!-- 定义项目版本 -->
<component name="Palette2">
<!-- 定义调色板组件 -->
<group name="Swing">
<!-- 定义Swing组件组 -->
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义水平间距组件 -->
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义垂直间距组件 -->
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义面板组件 -->
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<!-- 定义滚动面板组件 -->
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义按钮组件 -->
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<!-- 定义默认约束 -->
<initial-values>
<!-- 定义初始值 -->
<property name="text" value="Button" />
<!-- 定义按钮文本 -->
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义单选按钮组件 -->
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<!-- 定义默认约束 -->
<initial-values>
<!-- 定义初始值 -->
<property name="text" value="RadioButton" />
<!-- 定义单选按钮文本 -->
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义复选框组件 -->
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<!-- 定义默认约束 -->
<initial-values>
<!-- 定义初始值 -->
<property name="text" value="CheckBox" />
<!-- 定义复选框文本 -->
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义标签组件 -->
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<!-- 定义默认约束 -->
<initial-values>
<!-- 定义初始值 -->
<property name="text" value="Label" />
<!-- 定义标签文本 -->
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义文本框组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<!-- 定义默认约束 -->
<preferred-size width="150" height="-1" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义密码框组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<!-- 定义默认约束 -->
<preferred-size width="150" height="-1" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义格式化文本框组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<!-- 定义默认约束 -->
<preferred-size width="150" height="-1" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义文本区域组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义文本面板组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义编辑面板组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义组合框组件 -->
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义表格组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义列表组件 -->
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义树组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="150" height="50" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义选项卡面板组件 -->
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="200" height="200" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义分割面板组件 -->
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<!-- 定义默认约束 -->
<preferred-size width="200" height="200" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<!-- 定义微调器组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义滑块组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义分隔符组件 -->
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义进度条组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义工具栏组件 -->
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<!-- 定义默认约束 -->
<preferred-size width="-1" height="20" />
<!-- 定义首选大小 -->
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<!-- 定义工具栏分隔符组件 -->
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
<!-- 定义默认约束 -->
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<!-- 定义滚动条组件 -->
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
<!-- 定义默认约束 -->
</item>
</group>
</component>
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -1,7 +0,0 @@
# build docker for project
FROM waterknife/centos-nginx-jdk8-mysql
WORKDIR /lsg/
COPY backend/target/*.jar ./app.jar
COPY entrypoint.sh ./
RUN chmod 777 entrypoint.sh
EXPOSE 9527

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 Liang Shan Guang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,18 +0,0 @@
ResultVO<RecordDetailVo> getExamRecordDetail(@PathVariable String recordId) {
// 定义返回结果
ResultVO<RecordDetailVo> resultVO;
try {
// 调用examService获取考试记录详情
RecordDetailVo recordDetailVo = examService.getRecordDetail(recordId);
// 返回成功结果
resultVO = new ResultVO<>(0, "获取考试记录详情成功", recordDetailVo);
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
// 返回失败结果
resultVO = new ResultVO<>(-1, "获取考试记录详情失败", null);
}
// 返回结果
return resultVO;
}
}

@ -1,6 +0,0 @@
.idea/
*.iml
src/main/resources/public
src/main/resources/static
target/
dist/

@ -1,52 +0,0 @@
# 在线考试系统的后端实现
## 拦截器注入application.yml中的属性
> 拦截器执行在自动bean初始化之前会导致拦截器中无法注入配置属性按照下面的步骤即可正常注入
+ 给拦截器加`@Component`注解
![拦截器注入配置文件属性](images/拦截器注入配置文件属性.png)
+ 在配置类中用`@Autowired`注入
![拦截器注入配置文件属性2](images/拦截器注入配置文件属性2.png)
## 代码调试的时候如何打印完整的SQL语句和参数
> 主要是指application.yml的配置
参考博客[JPA打印SQL参数](https://mp.weixin.qq.com/s/zyTOdTwFhi2CwxCI9P1kQw)
+ 打印SQL语句
```yaml
spring:
jpa:
# 调试的时候用用于打印完成SQL语句(但是不打印参数),联合下面的logging.level一同打印最完整的SQL信息(语句+参数)
show-sql: true
```
+ 不打印SQL语句
```yaml
spring:
jpa:
# 调试的时候用用于打印完成SQL语句(但是不打印参数),联合下面的logging.level一同打印最完整的SQL信息(语句+参数)
show-sql: false
```
+ 打印SQL参数
```yaml
# SQL语句打印(能打印参数设置为trace是打印完整语句默认我们就关掉吧)
logging:
level:
org.hibernate.type.descriptor.sql.BasicBinder: trace
```
+ 不打印SQL参数
```yaml
# SQL语句打印(能打印参数设置为trace是打印完整语句默认我们就关掉吧)
logging:
level:
org.hibernate.type.descriptor.sql.BasicBinder: off
```
## SpringBoot整合vue工程到static目录中遇到的问题
+ [Spring Boot整合Vue解决静态资源映射页面刷新失效路径配置等问题](https://blog.csdn.net/godelgnis/article/details/89683760)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.huawei.l00379880</groupId>
<artifactId>exam</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>exam</name>
<description>基于SpringBoot的在线考试系统</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<!-- 常用Java工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.10</version>
</dependency>
<!-- FastDFS文件服务器的客户端 -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.5</version>
</dependency>
<!-- FastDFS文件传输需要 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- JWT相关 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -1,15 +0,0 @@
package lsgwr.exam;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring BootSpring Boot
*/
@SpringBootApplication
public class ExamApplication {
public static void main(String[] args) {
SpringApplication.run(ExamApplication.class, args);
}
}

@ -1,39 +0,0 @@
/***********************************************************
* @Description : 访
* @author : 广(Laing Shan Guang)
* @date : 2019-05-17 00:11
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@Slf4j
public class CORSConf {
// 创建一个 WebMvcConfigurer Bean
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
// 重写 addCorsMappings 方法
@Override
public void addCorsMappings(CorsRegistry registry) {
// 记录初始化 CORSConfiguration 配置
log.info("初始化 CORSConfiguration 配置");
// 添加映射
registry.addMapping("/**")
// 允许所有请求头
.allowedHeaders("*")
// 允许所有请求方法
.allowedMethods("*")
// 允许所有请求来源
.allowedOrigins("*");
}
};
}
}

@ -1,29 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-22 08:21
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.config;
import lsgwr.exam.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
// 注入LoginInterceptor
@Autowired
private LoginInterceptor loginInterceptor;
// 添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截user下的api
registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**");
}
}

@ -1,23 +0,0 @@
package lsgwr.exam.config;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@Configuration
public class ServletConfig {
// 创建一个WebServerFactoryCustomizer bean用于自定义WebServerFactory
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
// 返回一个lambda表达式用于自定义WebServerFactory
return factory -> {
// 创建一个ErrorPage对象用于处理404错误
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/");
// 将ErrorPage对象添加到WebServerFactory中
factory.addErrorPages(error404Page);
};
}
}

@ -1,76 +0,0 @@
/***********************************************************
* @Description : Swagger2
* @author : 广(Laing Shan Guang)
* @date : 2019-05-15 07:39
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket api() {
// 创建一个参数构建器
ParameterBuilder ticketPar = new ParameterBuilder();
// 创建一个参数集合
List<Parameter> pars = new ArrayList<>();
// 设置参数名
ticketPar.name("Access-Token").description("Rest接口权限认证token,无需鉴权可为空")
// 设置参数类型
.modelRef(new ModelRef("string")).parameterType("header")
// header中的ticket参数非必填传空也可以
.required(false).build();
// 根据每个方法名也知道当前方法在设置什么参数
pars.add(ticketPar.build());
return new Docket(DocumentationType.SWAGGER_2)
// 设置文档信息
.apiInfo(apiInfo())
// 选择要扫描的接口
.select()
// 自行修改为自己的包路径
.apis(RequestHandlerSelectors.basePackage("lsgwr"))
// 选择所有的路径
.paths(PathSelectors.any())
// 构建Docket
.build()
// 设置全局参数
.globalOperationParameters(pars);
}
private ApiInfo apiInfo() {
// 创建ApiInfo对象
return new ApiInfoBuilder()
// 设置API标题
.title("online exam by springboot")
// 设置API描述
.description("在线考试系统 by 梁山广 at 2021")
// 设置API服务条款URL
.termsOfServiceUrl("https://github.com/19920625lsg/spring-boot-online-exam")
// 设置API版本
.version("2.0")
// 设置API联系人信息
.contact(new Contact("liangshanguang", "https://github.com/lsgwr/spring-boot-online-exam", "liangshanguang2@gmail.com"))
// 构建ApiInfo对象
.build();
}
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 08:20
* Description :
*/
package lsgwr.exam.config;

@ -1,376 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-28 08:04
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.controller;
import lsgwr.exam.entity.Exam;
import lsgwr.exam.entity.ExamRecord;
import lsgwr.exam.service.ExamService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lsgwr.exam.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
@RestController
@Api(tags = "Exam APIs")
//将此控制器中的所有端点映射到/api/exam URL路径
@RequestMapping("/api/exam")
public class ExamController {
@Autowired //注入一个ExamService实例用于处理与考试和问题相关的业务逻辑
private ExamService examService;
/**
* @Description: 使examService.getQuestionAll(),
*
* ResultVO,
*
* &#064;ApiOperationAPI,SwaggerUI
*/
@GetMapping("/question/all")
@ApiOperation("获取所有问题的列表")
// 获取全部问题列表。
ResultVO<List<QuestionVo>> getQuestionAll() {
// 定义返回值。
ResultVO<List<QuestionVo>> resultVO;
try {
// 调用examService获取全部问题列表。
List<QuestionVo> questionAll = examService.getQuestionAll();
// 返回成功结果。
resultVO = new ResultVO<>(0, "获取全部问题列表成功", questionAll);
} catch (Exception e) {
// 打印异常信息。
e.printStackTrace();
// 返回失败结果。
resultVO = new ResultVO<>(-1, "获取全部问题列表失败", null);
}
// 返回结果。
return resultVO;
}
@PostMapping("/question/update")
@ApiOperation("更新问题")
ResultVO<QuestionVo> questionUpdate(@RequestBody QuestionVo questionVo) {
// 完成问题的更新。
System.out.println(questionVo);
try {
// 调用examService的updateQuestion方法更新问题。
QuestionVo questionVoResult = examService.updateQuestion(questionVo);
// 返回更新成功的结果。
return new ResultVO<>(0, "更新问题成功", questionVoResult);
} catch (Exception e) {
// 打印异常信息。
e.printStackTrace();
// 返回更新失败的结果。
return new ResultVO<>(-1, "更新问题失败", null);
}
}
/**
*
* @Description: QuestionCreateSimplifyVo
* QuestionCreateVoID
*
* 使examService.questionCreate()
*
* @param questionCreateSimplifyVo
*
* QuestionCreateSimplifyVo
*
* @param request HttpServletRequestID
*
* @return ResultVO<String>
*
*
*/
@PostMapping("/question/create")
@ApiOperation("创建问题")
ResultVO<String> questionCreate(@RequestBody QuestionCreateSimplifyVo questionCreateSimplifyVo, HttpServletRequest request) {
// 创建一个QuestionCreateVo对象。
QuestionCreateVo questionCreateVo = new QuestionCreateVo();
// 把能拷贝过来的属性都拷贝过来。
BeanUtils.copyProperties(questionCreateSimplifyVo, questionCreateVo);
// 设置创建者信息。
String userId = (String) request.getAttribute("user_id");
questionCreateVo.setQuestionCreatorId(userId);
System.out.println(questionCreateVo);
try {
// 调用examService的questionCreate方法创建问题。
examService.questionCreate(questionCreateVo);
// 返回问题创建成功的ResultVO。
return new ResultVO<>(0, "问题创建成功", null);
} catch (Exception e) {
// 打印异常信息。
e.printStackTrace();
// 返回创建问题失败的ResultVO。
return new ResultVO<>(-1, "创建问题失败", null);
}
}
/**
* @Description: ,
*
* 使examService.getSelections()ResultVO
*
* @return ResultVO<QuestionAllVo>
*/
@GetMapping("/question/selection")
@ApiOperation("获取问题分类的相关选项")
// 获取问题分类选项。
ResultVO<QuestionSelectionVo> getSelections() {
// 调用examService的getSelections方法获取问题分类选项。
QuestionSelectionVo questionSelectionVo = examService.getSelections();
// 如果获取成功。
if (questionSelectionVo != null) {
// 返回成功的结果。
return new ResultVO<>(0, "获取问题分类选项成功", questionSelectionVo);
} else {
// 否则返回失败的结果。
return new ResultVO<>(-1, "获取问题分类选项失败", null);
}
}
@GetMapping("/question/detail/{id}")
@ApiOperation("根据问题的id获取问题的详细信息")
ResultVO<QuestionDetailVo> getQuestionDetail(@PathVariable String id) {
// 根据问题id获取问题的详细信息。
System.out.println(id);
ResultVO<QuestionDetailVo> resultVO;
try {
// 调用examService的getQuestionDetail方法根据问题id获取问题的详细信息。
QuestionDetailVo questionDetailVo = examService.getQuestionDetail(id);
// 如果获取成功则返回ResultVO对象状态码为0提示信息为"获取问题详情成功"数据为questionDetailVo。
resultVO = new ResultVO<>(0, "获取问题详情成功", questionDetailVo);
} catch (Exception e) {
// 如果获取失败则打印异常信息并返回ResultVO对象状态码为-1提示信息为"获取问题详情失败"数据为null。
e.printStackTrace();
resultVO = new ResultVO<>(-1, "获取问题详情失败", null);
}
// 返回ResultVO对象。
return resultVO;
}
@GetMapping("/all")
@ApiOperation("获取全部考试的列表")
ResultVO<List<ExamVo>> getExamAll() {
// 需要拼接前端需要的考试列表对象。
ResultVO<List<ExamVo>> resultVO;
try {
// 调用examService的getExamAll方法获取全部考试的列表。
List<ExamVo> examVos = examService.getExamAll();
// 将获取到的考试列表封装到ResultVO对象中并返回。
resultVO = new ResultVO<>(0, "获取全部考试的列表成功", examVos);
} catch (Exception e) {
// 捕获异常,并打印异常信息。
e.printStackTrace();
// 将异常信息封装到ResultVO对象中并返回。
resultVO = new ResultVO<>(-1, "获取全部考试的列表失败", null);
}
return resultVO;
}
@GetMapping("/question/type/list")
@ApiOperation("获取问题列表,按照单选、多选和判断题分类返回")
ResultVO<ExamQuestionTypeVo> getExamQuestionTypeList() {
// 获取问题的分类列表。
ResultVO<ExamQuestionTypeVo> resultVO;
try {
// 调用examService的getExamQuestionType方法获取问题分类列表。
ExamQuestionTypeVo examQuestionTypeVo = examService.getExamQuestionType();
// 如果获取成功,则返回成功的结果。
resultVO = new ResultVO<>(0, "获取问题列表成功", examQuestionTypeVo);
} catch (Exception e) {
// 如果获取失败,则打印异常信息,并返回失败的结果。
e.printStackTrace();
resultVO = new ResultVO<>(-1, "获取问题列表失败", null);
}
// 返回结果。
return resultVO;
}
@PostMapping("/create")
@ApiOperation("创建考试")
ResultVO<Exam> createExam(@RequestBody ExamCreateVo examCreateVo, HttpServletRequest request) {
// 从前端传参数过来,在这里完成考试的入库。
ResultVO<Exam> resultVO;
// 获取当前用户的id。
String userId = (String) request.getAttribute("user_id");
try {
// 调用examService的create方法将examCreateVo和userId作为参数传入创建考试。
Exam exam = examService.create(examCreateVo, userId);
// 创建一个ResultVO对象将创建成功的考试信息返回。
resultVO = new ResultVO<>(0, "创建考试成功", exam);
} catch (Exception e) {
// 捕获异常打印异常信息并创建一个ResultVO对象将创建失败的考试信息返回。
e.printStackTrace();
resultVO = new ResultVO<>(-1, "创建考试失败", null);
}
// 返回ResultVO对象。
return resultVO;
}
@PostMapping("/update")
@ApiOperation("更新考试")
ResultVO<Exam> updateExam(@RequestBody ExamVo examVo, HttpServletRequest request) {
// 从前端传参数过来,在这里完成考试的入库。
ResultVO<Exam> resultVO;
// 获取当前用户id。
String userId = (String) request.getAttribute("user_id");
try {
// 调用service层更新考试。
Exam exam = examService.update(examVo, userId);
// 返回更新成功的resultVO。
resultVO = new ResultVO<>(0, "更新考试成功", exam);
} catch (Exception e) {
// 打印异常信息。
e.printStackTrace();
// 返回更新失败的resultVO。
resultVO = new ResultVO<>(-1, "更新考试失败", null);
}
return resultVO;
}
/**
* @Description:
*
* @return ResultVO<List<ExamCardVo>>
*
*
*/
@GetMapping("/card/list")
@ApiOperation("获取考试列表,适配前端卡片列表")
ResultVO<List<ExamCardVo>> getExamCardList() {
// 获取考试列表卡片。
ResultVO<List<ExamCardVo>> resultVO;
try {
// 调用examService的getExamCardList方法获取考试列表卡片。
List<ExamCardVo> examCardVoList = examService.getExamCardList();
// 如果获取成功,则返回成功的结果。
resultVO = new ResultVO<>(0, "获取考试列表卡片成功", examCardVoList);
} catch (Exception e) {
// 如果获取失败,则打印异常信息,并返回失败的结果。
e.printStackTrace();
resultVO = new ResultVO<>(-1, "获取考试列表卡片失败", null);
}
// 返回结果
return resultVO;
}
/**
* @Description: id
*
* @param id id
*
* @return ResultVO<ExamDetailVo>
*/
@GetMapping("/detail/{id}")
@ApiOperation("根据考试的id获取考试详情")
ResultVO<ExamDetailVo> getExamDetail(@PathVariable String id) {
// 根据id获取考试详情。
ResultVO<ExamDetailVo> resultVO;
try {
ExamDetailVo examDetail = examService.getExamDetail(id);
resultVO = new ResultVO<>(0, "获取考试详情成功", examDetail);
} catch (Exception e) {
resultVO = new ResultVO<>(-1, "获取考试详情失败", null);
}
return resultVO;
}
/**
* @Description: 使examService.finishExam,
*
* ResultVO,
* @param examId id
*
* @param answersMap
*
* @param request id
* @return
*/
@PostMapping("/finish/{examId}")
@ApiOperation("根据用户提交的答案对指定id的考试判分")
// 完成考试
ResultVO<ExamRecord> finishExam(@PathVariable String examId, @RequestBody HashMap<String, List<String>> answersMap, HttpServletRequest request) {
// 定义返回结果。
ResultVO<ExamRecord> resultVO;
try {
// 拦截器里设置上的用户id。
String userId = (String) request.getAttribute("user_id");
// 下面根据用户提交的信息进行判分,返回用户的得分情况。
ExamRecord examRecord = examService.judge(userId, examId, answersMap);
// 返回结果。
resultVO = new ResultVO<>(0, "考卷提交成功", examRecord);
} catch (Exception e) {
e.printStackTrace();
// 返回错误结果。
resultVO = new ResultVO<>(-1, "考卷提交失败", null);
}
return resultVO;
}
/**
* @Description: 使examService.getExamRecordList,
* ResultVO,
*
* @param request id
*
* @return ResultVO<List<ExamRecordVo>>
*
* ResultVOResultVO
*/
@GetMapping("/record/list")
@ApiOperation("获取当前用户的考试记录")
// 获取考试记录列表。
ResultVO<List<ExamRecordVo>> getExamRecordList(HttpServletRequest request) {
ResultVO<List<ExamRecordVo>> resultVO;
try {
// 拦截器里设置上的用户id。
String userId = (String) request.getAttribute("user_id");
// 下面根据用户账号拿到他(她所有的考试信息)注意要用VO封装下。
List<ExamRecordVo> examRecordVoList = examService.getExamRecordList(userId);
resultVO = new ResultVO<>(0, "获取考试记录成功", examRecordVoList);
} catch (Exception e) {
e.printStackTrace();
resultVO = new ResultVO<>(-1, "获取考试记录失败", null);
}
return resultVO;
}
/**
* @Description: 使examService.getExamRecordDetail,
*
* ResultVO,id
*
* @param recordId id
*
* @return ResultVO<RecordDetailVo>
* ResultVO
*
* ResultVO
*/
@GetMapping("/record/detail/{recordId}")
@ApiOperation("根据考试记录id获取考试记录详情")
ResultVO<RecordDetailVo> getExamRecordDetail(@PathVariable String recordId) {
// 定义返回结果。
ResultVO<RecordDetailVo> resultVO;
try {
// 调用examService获取考试记录详情。
RecordDetailVo recordDetailVo = examService.getRecordDetail(recordId);
// 返回成功结果。
resultVO = new ResultVO<>(0, "获取考试记录详情成功", recordDetailVo);
} catch (Exception e) {
// 打印异常信息。
e.printStackTrace();
// 返回失败结果。
resultVO = new ResultVO<>(-1, "获取考试记录详情失败", null);
}
// 返回结果。
return resultVO;
}
}

@ -1,103 +0,0 @@
package lsgwr.exam.controller;
import lsgwr.exam.qo.DownloadQo;
import lsgwr.exam.qo.UploadModel;
import lsgwr.exam.qo.UploadModel2;
import lsgwr.exam.utils.FileTransUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/***********************************************************
*
* @note : ,SwaggerSwaggerUI
*
*
*
* @author : 广
*
* * Ajax
*
* ResponseEntity
* *
*
* * 1.
* - `MultipartFile`
* * 2.
* - `MultipartFile []`
* * 3. - `@ModelAttribute`
* @version : V1.0 at 2018/7/16 20:43
***********************************************************/
@RestController
@Api(tags = "Upload And Download APIs")
@RequestMapping("/api/file")
@Slf4j
public class UploadDownloadController {
// @Autowired
// AITestConfig aiTestConfig;
//
// @PostMapping("/upload/single")
// @ApiOperation("单文件上传")
// public String uploadFile(@RequestParam("file") MultipartFile uploadfile) {
// return FileTransUtil.uploadFile(uploadfile, "/root/" + File.separator + uploadfile.getOriginalFilename());
// }
@ApiOperation("单文件上传,支持同时传入参数")
@PostMapping("/api/upload/singleAndparas")
// 单文件上传。
public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(uploadfile, dir);
}
// 单文件上传支持同时传入参数Model。
@ApiOperation("单文件上传,支持同时传入参数,Model")
@PostMapping("/upload/single/model")
public String singleUploadFileModel(@ModelAttribute("model") UploadModel2 model) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(model.getFile(), model.getDir());
}
// 多文件上传,支持同时传入参数。
@ApiOperation("多文件上传,支持同时传入参数")
@PostMapping("upload/multiAndparas")
public String uploadFileMulti(@RequestParam("dir") String dir, @RequestParam("files") MultipartFile[] uploadfiles) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(uploadfiles, dir);
}
// 多文件上传,支持同时传入参数。
@ApiOperation("多文件上传,支持同时传入参数")
@PostMapping(value = "/upload/multi/model")
public String multiUploadFileModel(@ModelAttribute(("model")) UploadModel model) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(model.getFiles(), model.getDir());
}
// Get下载文件
@ApiOperation("Get下载文件")
@GetMapping(value = "/download/get")
public ResponseEntity<InputStreamResource> downloadFileGet(@RequestParam String filePath) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(filePath);
}
// Post下载文件
@ApiOperation("Post下载文件")
@PostMapping(value = "/download/post")
public ResponseEntity<InputStreamResource> downloadFilePost(@RequestBody DownloadQo downloadQo) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(downloadQo.getPath());
}
}

@ -1,99 +0,0 @@
/***********************************************************
* @Description : REST
* @author : 广(Laing Shan Guang)
* @date : 2019-05-16 23:45
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.controller;
import lsgwr.exam.dto.RegisterDTO;
import lsgwr.exam.entity.User;
import lsgwr.exam.enums.ResultEnum;
import lsgwr.exam.qo.LoginQo;
import lsgwr.exam.service.UserService;
import lsgwr.exam.vo.ResultVO;
import lsgwr.exam.vo.UserInfoVo;
import lsgwr.exam.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@Api(tags = "User APIs")
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
@ApiOperation("注册")
ResultVO<User> register(@RequestBody RegisterDTO registerDTO) {
ResultVO<User> resultVO;
// 注册信息的完善,还有唯一性校验没(用户名、邮箱和手机号)已经在user表中通过unique来设置了
User user = userService.register(registerDTO);
if (user != null) {
// 注册成功
resultVO = new ResultVO<>(ResultEnum.REGISTER_SUCCESS.getCode(), ResultEnum.REGISTER_SUCCESS.getMessage(), user);
} else {
resultVO = new ResultVO<>(ResultEnum.REGISTER_FAILED.getCode(), ResultEnum.REGISTER_FAILED.getMessage(), null);
}
return resultVO;
}
@PostMapping("/login")
@ApiOperation("根据用户名或邮箱登录,登录成功返回token")
ResultVO<String> login(@RequestBody LoginQo loginQo) { // 这里不用手机号是因为手机号和用户名难以进行格式区分,而用户名和
// 用户登录
ResultVO<String> resultVO;
String token = userService.login(loginQo);
if (token != null) {
// 登录成功
resultVO = new ResultVO<>(ResultEnum.LOGIN_SUCCESS.getCode(), ResultEnum.LOGIN_SUCCESS.getMessage(), token);
} else {
// 登录失败
resultVO = new ResultVO<>(ResultEnum.LOGIN_FAILED.getCode(), ResultEnum.LOGIN_FAILED.getMessage(), null);
}
return resultVO;
}
@GetMapping("/user-info")
@ApiOperation("获取用户信息")
// 根据请求获取用户信息
ResultVO<UserVo> getUserInfo(HttpServletRequest request) {
// 从请求中获取用户ID
String userId = (String) request.getAttribute("user_id");
// 根据用户ID获取用户信息
UserVo userVo = userService.getUserInfo(userId);
// 返回用户信息
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userVo);
}
@GetMapping("/info")
@ApiOperation("获取用户的详细信息,包括个人信息页面和操作权限")
// 获取用户信息的接口
ResultVO<UserInfoVo> getInfo(HttpServletRequest request) {
// 打印进入接口的日志
System.out.println("进入/user/info的获取用户信息的接口");
// 获取用户ID
String userId = (String) request.getAttribute("user_id");
// 调用userService获取用户信息
UserInfoVo userInfoVo = userService.getInfo(userId);
// 返回结果
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userInfoVo);
}
@GetMapping("/test")
@ApiOperation("测试接口")
String test(HttpServletRequest request) {
// 下面这两个属性都是登录拦截器从token中解析地当用户名不对或者token过期时是走不到接口内的
String userId = (String) request.getAttribute("user_id");
String username = (String) request.getAttribute("username");
System.out.println("用户id" + userId);
System.out.println("用户名:" + username);
return "用户id" + userId + "\n用户名" + username;
}
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 08:20
* Description : REST
*/
package lsgwr.exam.controller;

@ -1,33 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-16 23:40
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.dto;
import lombok.Data;
@Data
public class RegisterDTO {
/**
*
*/
private String email;
/**
*
*/
private String password;
/**
*
*/
private String password2;
/**
*
*/
private String mobile;
/**
*
*/
private String captcha;
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-16 23:38
* Description :
*/
package lsgwr.exam.dto;

@ -1,32 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 12:31
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class Action {
// 定义一个主键
@Id
// 自动生成主键
@GeneratedValue
private Integer actionId;
// 定义一个动作名称
private String actionName;
// 定义一个动作描述
private String actionDescription;
// 定义一个默认选中状态
private Boolean defaultCheck;
}

@ -1,81 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:42
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
@Entity
@Data
@DynamicUpdate
public class Exam {
// 考试ID
@Id
private String examId;
// 考试名称
private String examName;
// 考试头像
private String examAvatar;
// 考试描述
private String examDescription;
// 考试问题ID
private String examQuestionIds;
// 考试单选题ID
private String examQuestionIdsRadio;
// 考试多选题ID
private String examQuestionIdsCheck;
// 考试判断题ID
private String examQuestionIdsJudge;
// 考试总分
private Integer examScore;
// 考试单选题总分
private Integer examScoreRadio;
// 考试多选题总分
private Integer examScoreCheck;
// 考试判断题总分
private Integer examScoreJudge;
// 考试创建者ID
private String examCreatorId;
// 考试时间限制
private Integer examTimeLimit;
// 考试开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examStartDate;
// 考试结束时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examEndDate;
/**
*
*
* , Java
*
*
*/
// 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* Java
*
*
* @DynamicUpdate
*
*
*/
// 更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

@ -1,75 +0,0 @@
/***********************************************************
* @Description : id()
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:43
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
@Data
@Entity
public class ExamRecord {
/**
*
*
*
*
*
*/
@Id
private String examRecordId;
/**
*
* id
*
*/
private String examId;
/**
*
* (_
*
* -),
*/
private String answerOptionIds;
/**
*
* userid
*
*/
private String examJoinerId;
/**
*
*
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examJoinDate;
/**
*
* ()
*
*/
private Integer examTimeCost;
/**
*
*
*
*/
private Integer examJoinScore;
/**
*
*
*
*/
private Integer examResultLevel;
}

@ -1,27 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:44
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class ExamRecordLevel {
// 考试记录等级ID
@Id
@GeneratedValue
private Integer examRecordLevelId;
// 考试记录等级名称
private String examRecordLevelName;
// 考试记录等级描述
private String examRecordLevelDescription;
}

@ -1,31 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 12:30
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class Page {
// 定义一个页面ID使用@Id注解表示该字段为主键使用@GeneratedValue注解表示该字段自动生成
@Id
@GeneratedValue
private Integer pageId;
// 定义一个页面名称
private String pageName;
// 定义一个页面描述
private String pageDescription;
// 定义一个动作ID用于存储页面上的动作
private String actionIds;
}

@ -1,58 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:46
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
@Data
@Entity
@DynamicUpdate
public class Question {
// 问题ID
@Id
private String questionId;
// 问题名称
private String questionName;
// 问题分数
private Integer questionScore;
// 问题创建者ID
private String questionCreatorId;
// 问题等级ID
private Integer questionLevelId;
// 问题类型ID
private Integer questionTypeId;
// 问题分类ID
private Integer questionCategoryId;
// 问题描述
private String questionDescription;
// 问题选项ID
private String questionOptionIds;
// 问题答案选项ID
private String questionAnswerOptionIds;
/**
* , Java
*/
// 创建时间格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* Java
* @DynamicUpdate
*/
// 更新时间格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

@ -1,36 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:46
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class QuestionCategory {
// 主键
@Id
// 自动生成主键
@GeneratedValue
// 将该字段映射到JSON中的id字段
@JsonProperty("id")
private Integer questionCategoryId;
// 将该字段映射到JSON中的name字段
@JsonProperty("name")
private String questionCategoryName;
// 将该字段映射到JSON中的description字段
@JsonProperty("description")
private String questionCategoryDescription;
}

@ -1,32 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:47
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
@Data
public class QuestionLevel {
// 定义实体类,表示问题等级
@Id
@GeneratedValue
// 定义主键,自动生成
@JsonProperty("id")
private Integer questionLevelId;
@JsonProperty("name")
private String questionLevelName;
@JsonProperty("description")
private String questionLevelDescription;
}

@ -1,25 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:48
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
@Data
@Entity
public class QuestionOption {
// 定义问题选项的ID
@Id
private String questionOptionId;
// 定义问题选项的内容
private String questionOptionContent;
// 定义问题选项的描述
private String questionOptionDescription;
}

@ -1,35 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:48
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class QuestionType {
// 主键
@Id
// 自动生成主键
@GeneratedValue
// 将该字段映射到JSON中的id字段
@JsonProperty("id")
private Integer questionTypeId;
// 将该字段映射到JSON中的name字段
@JsonProperty("name")
private String questionTypeName;
// 将该字段映射到JSON中的description字段
@JsonProperty("description")
private String questionTypeDescription;
}

@ -1,37 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:49
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
public class Role {
// 角色ID
@Id
@GeneratedValue
private Integer roleId;
// 角色名称
private String roleName;
// 角色描述
private String roleDescription;
// 角色详情
private String roleDetail;
/**
*
*
* 访(-)
*
*
*/
private String rolePageIds;
}

@ -1,65 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:49
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
@Data
@Entity
@DynamicUpdate
public class User {
// 用户ID
@Id
private String userId;
// 用户名
private String userUsername;
// 用户昵称
private String userNickname;
// 用户密码
private String userPassword;
// 用户角色ID
private Integer userRoleId;
// 用户头像
private String userAvatar;
// 用户描述
private String userDescription;
// 用户邮箱
private String userEmail;
// 用户电话
private String userPhone;
/**
*
*
* ,
*
* Java
*
*
*/
// 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
*
* Java
* @DynamicUpdate
*
*
*/
// 更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 00:34
* Description :
*/
package lsgwr.exam.entity;

@ -1,32 +0,0 @@
package lsgwr.exam.enums;
import lombok.Getter;
/**
*
*
*
* @author liangshanguang
*
*
*/
@Getter
public enum LoginTypeEnum {
/**
*
* 12
*
*
*/
USERNAME(1, "用户名"),
EMAIL(2, "邮箱");
LoginTypeEnum(Integer type, String name) {
this.type = type;
this.name = name;
}
private Integer type;
private String name;
}

@ -1,29 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-18 12:00
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.enums;
import lombok.Getter;
@Getter
public enum QuestionEnum {
/**
*
*/
RADIO(1, "单选题"),
CHECK(2, "多选题"),
JUDGE(3, "判断题");
QuestionEnum(Integer id, String role) {
this.id = id;
this.role = role;
}
private Integer id;
private String role;
}

@ -1,30 +0,0 @@
package lsgwr.exam.enums;
import lombok.Getter;
@Getter
public enum ResultEnum {
// 下面是本项目用到的所有错误码
REGISTER_SUCCESS(0, "注册成功"),
REGISTER_FAILED(-2, "注册失败"),
LOGIN_SUCCESS(0, "登录成功"),
LOGIN_FAILED(-1, "用户名或者密码错误"),
GET_INFO_SUCCESS(0, "获取用户信息成功"),
PARAM_ERR(1, "参数不正确"),
PRODUCT_NOT_EXIST(10, "用户不存在"),
PRODUCT_STOCK_ERR(11, "考试信息异常"),
ORDER_STATUS_ERR(14, "考试状态异常"),
ORDER_UPDATE_ERR(15, "考试更新异常"),
ORDER_DETAIL_EMPTY(16, "用户详情为空");
// 构造方法,用于初始化错误码和错误信息
ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
// 错误码
private Integer code;
// 错误信息
private String message;
}

@ -1,33 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-18 12:00
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.enums;
import lombok.Getter;
@Getter
public enum RoleEnum {
/**
*
*
* role
*
*
*/
ADMIN(1, "管理员"),
TEACHER(2, "教师"),
STUDENT(3, "学生");
RoleEnum(Integer id, String role) {
this.id = id;
this.role = role;
}
private Integer id;
private String role;
}

@ -1,32 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-17 07:50
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.exception;
import lsgwr.exam.enums.ResultEnum;
import lombok.Getter;
@Getter
public class ExamException extends RuntimeException {
// 定义异常代码
private Integer code;
// 构造函数传入ResultEnum枚举类型
public ExamException(ResultEnum resultEnum) {
// 调用父类构造函数传入ResultEnum枚举类型的消息
super(resultEnum.getMessage());
// 将ResultEnum枚举类型的代码赋值给异常代码
this.code = resultEnum.getCode();
}
// 构造函数,传入异常代码和消息
public ExamException( Integer code, String message) {
// 调用父类构造函数,传入消息
super(message);
// 将传入的异常代码赋值给异常代码
this.code = code;
}
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-17 07:51
* Description :
*/
package lsgwr.exam.exception;

@ -1,131 +0,0 @@
/***********************************************************
* @Description : Token
* @author : 广(Laing Shan Guang)
* @date : 2019-05-22 07:35
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.interceptor;
import com.google.gson.Gson;
import lsgwr.exam.utils.JwtUtils;
import lsgwr.exam.vo.JsonData;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* https://stackoverflow.com/questions/43591582/application-properties-value-in-spring-boot-interceptor
*
* @author liangshanguang
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
*
* @Component使pplication.yml
*
*
*/
@Value("${interceptors.auth-ignore-uris}")
private String authIgnoreUris;
/**
*
*
* controller
*
*
* @param request
*
* @param response
*
* @param handler
*
* @return
*
* @throws Exception
*
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 打印进入拦截器
System.out.println("进入拦截器啦!");
// 获取请求的URI
String uri = request.getRequestURI();
// 打印URI
System.out.println(uri);
// 打印无需拦截的接口路径
System.out.println("无需拦截的接口路径:" + authIgnoreUris);
// 将无需拦截的接口路径分割成数组
String[] authIgnoreUriArr = authIgnoreUris.split(",");
// 登录和注册接口不需要进行token拦截和校验
for (String authIgnoreUri : authIgnoreUriArr) {
// 如果请求的URI在无需拦截的接口路径中则直接返回true
if (authIgnoreUri.equals(uri)) {
return true;
}
}
// 注意要和前端适配Access-Token属性前端会在登陆后的每个接口请求头加Access-Token属性
// 获取请求头中的token
String token = request.getHeader("Access-Token");
// 如果token不在header中则可能在参数中
if (token == null) {
// 从参数中获取token
token = request.getParameter("token");
}
// 如果token不为空
if (token != null) {
// 请求中是携带参数的
// 校验token
Claims claims = JwtUtils.checkJWT(token);
// 如果token校验失败
if (claims == null) {
// 返回null说明用户篡改了token导致校验失败
// 返回错误信息
sendJsonMessage(response, JsonData.buildError("token无效请重新登录"));
return false;
}
// 用户的的主键id
String id = (String) claims.get("id");
// 用户名
String username = (String) claims.get("username");
// 把这两个参数放到请求中从而可以在controller中获取到不需要在controller中在用Jwt解密了,request.getAttribute("属性名")即可获取
// 将用户id和用户名放到请求中
request.setAttribute("user_id", id);
request.setAttribute("username", username);
return true;
}
// 如果token为空则返回错误信息
sendJsonMessage(response, JsonData.buildError("token为null,请先登录!"));
return false;
}
/**
*
*
* @param response
* @param obj
* @throws Exception
*/
// 发送JSON消息
public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {
// 创建Gson对象
Gson g = new Gson();
// 设置响应内容类型为JSON
response.setContentType("application/json; charset=utf-8");
// 获取响应的PrintWriter对象
PrintWriter writer = response.getWriter();
// 将对象转换为JSON字符串并写入响应
writer.print(g.toJson(obj));
// 关闭PrintWriter对象
writer.close();
// 刷新响应缓冲区
response.flushBuffer();
}
}

@ -1,18 +0,0 @@
package lsgwr.exam.qo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/***********************************************************
* @note :
* @author : 广
* @version : V1.0 at 2019/5/19 20:10
***********************************************************/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DownloadQo {
// 下载路径
String path;
}

@ -1,35 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-19 20:18
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.qo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginQo {
/**
*
* 12
*
*/
private Integer loginType;
/**
*
* /
*
*/
private String userInfo;
/**
*
*
*
*/
private String password;
}

@ -1,35 +0,0 @@
package lsgwr.exam.qo;
/***********************************************************
* @Description :
* @author : 广
* @date : 2017/8/19 15:51
* @version : V1.0
***********************************************************/
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UploadModel {
/**
*
*
*
*
*
*/
private MultipartFile[] files;
/**
*
*
*
*
*
*/
private String dir;
}

@ -1,35 +0,0 @@
package lsgwr.exam.qo;
/***********************************************************
* @Description :
* @author : 广
* @date : 2018/5/19 15:51
* @version : V1.0
***********************************************************/
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UploadModel2 {
/**
*
*
*
*
*
*/
private MultipartFile file;
/**
*
*
*
*
*
*/
private String dir;
}

@ -1,6 +0,0 @@
/***********************************************************
* @note : (Query Object)
* @author : 广
* @version : V1.0 at 2018/7/18 17:32
***********************************************************/
package lsgwr.exam.qo;

@ -1,13 +0,0 @@
/***********************************************************
* @Description : Action
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 12:39
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.Action;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ActionRepository extends JpaRepository<Action, Integer> {
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:24
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.ExamRecordLevel;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ExamRecordLevelRepository extends JpaRepository<ExamRecordLevel, Integer> {
}

@ -1,22 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:23
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.ExamRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ExamRecordRepository extends JpaRepository<ExamRecord, String> {
/**
*
*
* @param userId id
* @return
*/
List<ExamRecord> findByExamJoinerIdOrderByExamJoinDateDesc(String userId);
}

@ -1,18 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:22
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.Exam;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface ExamRepository extends JpaRepository<Exam, String> {
@Query("select e from Exam e order by e.updateTime desc")
List<Exam> findAll();
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 12:41
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.Page;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PageRepository extends JpaRepository<Page, Integer> {
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:25
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.QuestionCategory;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionCategoryRepository extends JpaRepository<QuestionCategory, Integer> {
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:26
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.QuestionLevel;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionLevelRepository extends JpaRepository<QuestionLevel, Integer> {
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:27
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.QuestionOption;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionOptionRepository extends JpaRepository<QuestionOption, String> {
}

@ -1,19 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:25
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.Question;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface QuestionRepository extends JpaRepository<Question, String> {
List<Question> findByQuestionTypeId(Integer id);
@Query("select q from Question q order by q.updateTime desc")
List<Question> findAll();
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:28
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.QuestionType;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionTypeRepository extends JpaRepository<QuestionType, Integer> {
}

@ -1,13 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:29
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Integer> {
}

@ -1,28 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-14 08:30
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.repository;
import lsgwr.exam.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, String> {
/**
*
*
* @param username
* @return (unique 1)
*/
User findByUserUsername(String username);
/**
*
*
* @param email
* @return (unique 1)
*/
User findByUserEmail(String email);
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 08:20
* Description :
*/
package lsgwr.exam.repository;

@ -1,211 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-28 08:05
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.service;
import lsgwr.exam.entity.Exam;
import lsgwr.exam.entity.ExamRecord;
import lsgwr.exam.vo.*;
import java.util.HashMap;
import java.util.List;
public interface ExamService {
/**
*
*
*
*
*/
List<QuestionVo> getQuestionAll();
/**
*
*
*
*
* @param questionVo
*
*
*
*/
QuestionVo updateQuestion(QuestionVo questionVo);
/**
*
*
*
*
*
* @param questionCreateVo
*
*
*/
void questionCreate(QuestionCreateVo questionCreateVo);
/**
*
*
*
*
* @return
*
*
*/
QuestionSelectionVo getSelections();
/**
*
*
*
*
* @param id id
*
*
* @return VO
*
*
*/
QuestionDetailVo getQuestionDetail(String id);
/**
*
*
*
*
*
*/
List<ExamVo> getExamAll();
/**
* 便
*
*
*
*
* @return
*
*
*
*/
ExamQuestionTypeVo getExamQuestionType();
/**
*
*
*
*
* @param examCreateVo
*
*
*
* @param userId id
*
*
*
* @return
*
*
*
*/
Exam create(ExamCreateVo examCreateVo, String userId);
/**
*
*
*
*
* @return
*
*
*/
List<ExamCardVo> getExamCardList();
/**
* id
*
*
*
*
* @param id exam
*
*
*
* @return VO
*
*
*/
ExamDetailVo getExamDetail(String id);
/**
*
*
*
*
* @param userId
*
*
* @param examId
*
*
* @param answersMap
*
*
* @return
*
*
*/
ExamRecord judge(String userId, String examId, HashMap<String, List<String>> answersMap);
/**
* id
*
*
*
* @param userId id
*
*
* @return
*
*
*/
List<ExamRecordVo> getExamRecordList(String userId);
/**
*
*
*
*
* @param recordId id
*
*
*
* @return
*
*
*
*/
RecordDetailVo getRecordDetail(String recordId);
/**
*
*
* @param examVo
*
*
* @param userId
*
*
*
* @return
*
*
*
*
*/
Exam update(ExamVo examVo, String userId);
}

@ -1,69 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-17 08:02
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.service;
import lsgwr.exam.dto.RegisterDTO;
import lsgwr.exam.entity.User;
import lsgwr.exam.qo.LoginQo;
import lsgwr.exam.vo.UserInfoVo;
import lsgwr.exam.vo.UserVo;
public interface UserService {
/**
*
*
*
*
* @param registerDTO
*
*
*
* @return
*
*
*/
User register(RegisterDTO registerDTO);
/**
* token
*
*
*
* @param loginQo
*
*
* @return tokennull
*
*
*/
String login(LoginQo loginQo);
/**
* id
*
*
*
*
* @return
*
*
*/
UserVo getUserInfo(String userId);
/**
* ()
*
*
* @param userId id
*
*
* @return
*
*
*/
UserInfoVo getInfo(String userId);
}

@ -1,738 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-28 08:06
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lsgwr.exam.entity.*;
import lsgwr.exam.enums.QuestionEnum;
import lsgwr.exam.repository.*;
import lsgwr.exam.service.ExamService;
import lsgwr.exam.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.*;
@Service
@Transactional
public class ExamServiceImpl implements ExamService {
// 试卷仓库
private final ExamRepository examRepository;
// 考试记录仓库
private final ExamRecordRepository examRecordRepository;
// 问题仓库
private final QuestionRepository questionRepository;
// 用户仓库
private final UserRepository userRepository;
// 问题等级仓库
private final QuestionLevelRepository questionLevelRepository;
// 问题类型仓库
private final QuestionTypeRepository questionTypeRepository;
// 问题类别仓库
private final QuestionCategoryRepository questionCategoryRepository;
// 问题选项仓库
// 定义一个final类型的QuestionOptionRepository对象
private final QuestionOptionRepository questionOptionRepository;
// 构造函数传入多个Repository对象
public ExamServiceImpl(QuestionRepository questionRepository, UserRepository userRepository, QuestionLevelRepository questionLevelRepository, QuestionTypeRepository questionTypeRepository, QuestionCategoryRepository questionCategoryRepository, QuestionOptionRepository questionOptionRepository, ExamRepository examRepository, ExamRecordRepository examRecordRepository) {
// 将传入的Repository对象赋值给对应的成员变量
this.questionRepository = questionRepository;//
this.userRepository = userRepository;//
this.questionLevelRepository = questionLevelRepository;//
this.questionTypeRepository = questionTypeRepository;
this.questionCategoryRepository = questionCategoryRepository;
this.questionOptionRepository = questionOptionRepository;
this.examRepository = examRepository;
this.examRecordRepository = examRecordRepository;
}
@Override
public List<QuestionVo> getQuestionAll() {
List<Question> questionList = questionRepository.findAll();
return getQuestionVos(questionList);
}
private List<QuestionVo> getQuestionVos(List<Question> questionList) {
// 需要自定义的question列表
List<QuestionVo> questionVoList = new ArrayList<>();
// 循环完成每个属性的定制,
for (Question question : questionList) {
QuestionVo questionVo = getQuestionVo(question);
questionVoList.add(questionVo);
}
return questionVoList;
}
private QuestionVo getQuestionVo(Question question) {
QuestionVo questionVo = new QuestionVo();
// 先复制能复制的属性,
BeanUtils.copyProperties(question, questionVo);
// 设置问题的创建者。
questionVo.setQuestionCreator(
Objects.requireNonNull(
userRepository.findById(
question.getQuestionCreatorId()
).orElse(null)
).getUserUsername());
// 设置问题的难度。
questionVo.setQuestionLevel(
Objects.requireNonNull(
questionLevelRepository.findById(
question.getQuestionLevelId()
).orElse(null)
).getQuestionLevelDescription());
// 设置题目的类别,比如单选、多选、判断等。
questionVo.setQuestionType(
Objects.requireNonNull(
questionTypeRepository.findById(
question.getQuestionTypeId()
).orElse(null)
).getQuestionTypeDescription());
// 设置题目分类,比如数学、语文、英语、生活、人文等。
questionVo.setQuestionCategory(
Objects.requireNonNull(
questionCategoryRepository.findById(
question.getQuestionCategoryId()
).orElse(null)
).getQuestionCategoryName()
);
// 选项的自定义Vo列表。
List<QuestionOptionVo> optionVoList = new ArrayList<>();
// 获得所有的选项列表。
List<QuestionOption> optionList = questionOptionRepository.findAllById(
Arrays.asList(question.getQuestionOptionIds().split("-"))
);
// 获取所有的答案列表optionList中每个option的isAnswer选项。
List<QuestionOption> answerList = questionOptionRepository.findAllById(
Arrays.asList(question.getQuestionAnswerOptionIds().split("-"))
);
// 根据选项和答案的id相同设置optionVo的isAnswer属性。
for (QuestionOption option : optionList) {
QuestionOptionVo optionVo = new QuestionOptionVo();
BeanUtils.copyProperties(option, optionVo);
for (QuestionOption answer : answerList) {
if (option.getQuestionOptionId().equals(answer.getQuestionOptionId())) {
optionVo.setAnswer(true);
}
}
optionVoList.add(optionVo);
}
// 设置题目的所有选项。
questionVo.setQuestionOptionVoList(optionVoList);
return questionVo;
}
@Override
public QuestionVo updateQuestion(QuestionVo questionVo) {
// 1.把需要的属性都设置好。
StringBuilder questionAnswerOptionIds = new StringBuilder();
List<QuestionOption> questionOptionList = new ArrayList<>();
List<QuestionOptionVo> questionOptionVoList = questionVo.getQuestionOptionVoList();
int size = questionOptionVoList.size();
for (int i = 0; i < questionOptionVoList.size(); i++) {
QuestionOptionVo questionOptionVo = questionOptionVoList.get(i);
QuestionOption questionOption = new QuestionOption();
// 2.把questionOptionVo中的属性值复制到questionOption中。
BeanUtils.copyProperties(questionOptionVo, questionOption);
questionOptionList.add(questionOption);
// 3.如果questionOptionVo中的answer属性为true则把questionOptionVo中的questionOptionId属性值添加到questionAnswerOptionIds中。
if (questionOptionVo.getAnswer()) {
if (i != size - 1) {
// 把更新后的答案的id加上去,记得用-连到一起。
questionAnswerOptionIds.append(questionOptionVo.getQuestionOptionId()).append("-");
} else {
// 最后一个不需要用-连接。
questionAnswerOptionIds.append(questionOptionVo.getQuestionOptionId());
}
}
}
// 1.更新问题。
// 根据问题id从数据库中查找问题
Question question = questionRepository.findById(questionVo.getQuestionId()).orElse(null);
// 断言问题不为空
assert question != null;
// 将questionVo中的属性值复制到question中
BeanUtils.copyProperties(questionVo, question);
// 将问题答案选项id转换为字符串并设置到question中
question.setQuestionAnswerOptionIds(questionAnswerOptionIds.toString());
// 保存更新后的question到数据库中
questionRepository.save(question);
// 2.更新所有的option。
// 将questionOptionList中的所有option保存到数据库中
questionOptionRepository.saveAll(questionOptionList);
// 返回更新后的问题,方便前端局部刷新。
// 将更新后的question转换为questionVo并返回
return getQuestionVo(question);
}
@Override
public void questionCreate(QuestionCreateVo questionCreateVo) {
// 问题创建
Question question = new Question();
// 把能复制的属性都复制过来。
BeanUtils.copyProperties(questionCreateVo, question);
// 设置下questionOptionIds和questionAnswerOptionIds需要自己用Hutool生成下。
List<QuestionOption> questionOptionList = new ArrayList<>();
List<QuestionOptionCreateVo> questionOptionCreateVoList = questionCreateVo.getQuestionOptionCreateVoList();
for (QuestionOptionCreateVo questionOptionCreateVo : questionOptionCreateVoList) {
QuestionOption questionOption = new QuestionOption();
// 设置选项的的内容。
questionOption.setQuestionOptionContent(questionOptionCreateVo.getQuestionOptionContent());
// 设置选项的id。
questionOption.setQuestionOptionId(IdUtil.simpleUUID());
questionOptionList.add(questionOption);
}
// 把选项都存起来然后才能用于下面设置Question的questionOptionIds和questionAnswerOptionIds。
questionOptionRepository.saveAll(questionOptionList);
String questionOptionIds = "";
String questionAnswerOptionIds = "";
// 经过上面的saveAll方法所有的option的主键id都已经持久化了。
for (int i = 0; i < questionOptionCreateVoList.size(); i++) {
// 获取指定选项。
QuestionOptionCreateVo questionOptionCreateVo = questionOptionCreateVoList.get(i);
// 获取保存后的指定对象。
QuestionOption questionOption = questionOptionList.get(i);
questionOptionIds += questionOption.getQuestionOptionId() + "-";
if (questionOptionCreateVo.getAnswer()) {
// 如果是答案的话。
questionAnswerOptionIds += questionOption.getQuestionOptionId() + "-";
}
}
// 把字符串最后面的"-"给去掉。
questionAnswerOptionIds = replaceLastSeparator(questionAnswerOptionIds);
questionOptionIds = replaceLastSeparator(questionOptionIds);
// 设置选项id组成的字符串。
question.setQuestionOptionIds(questionOptionIds);
// 设置答案选项id组成的字符串。
question.setQuestionAnswerOptionIds(questionAnswerOptionIds);
// 自己生成问题的id。
question.setQuestionId(IdUtil.simpleUUID());
// 先把创建时间和更新时间每次都取当前时间吧。
question.setCreateTime(new Date());
question.setUpdateTime(new Date());
// 保存问题到数据库。
questionRepository.save(question);
}
@Override
// 重写父类方法,获取问题选择列表
public QuestionSelectionVo getSelections() {
// 创建问题选择对象
QuestionSelectionVo questionSelectionVo = new QuestionSelectionVo();
// 设置问题类别列表
questionSelectionVo.setQuestionCategoryList(questionCategoryRepository.findAll());
// 设置问题等级列表
questionSelectionVo.setQuestionLevelList(questionLevelRepository.findAll());
// 设置问题类型列表
questionSelectionVo.setQuestionTypeList(questionTypeRepository.findAll());
// 返回问题选择对象
return questionSelectionVo;
}
/**
* split
*
* @param str
* @return
*/
public static String trimMiddleLine(String str) {
if (str.charAt(str.length() - 1) == '-') {
str = str.substring(0, str.length() - 1);
}
return str;
}
@Override
public QuestionDetailVo getQuestionDetail(String id) {
// 根据id查询问题
Question question = questionRepository.findById(id).orElse(null);
// 创建问题详情对象
QuestionDetailVo questionDetailVo = new QuestionDetailVo();
// 设置问题id
questionDetailVo.setId(id);
// 设置问题名称
questionDetailVo.setName(question.getQuestionName());
// 设置问题描述
questionDetailVo.setDescription(question.getQuestionDescription());
// 问题类型,单选题/多选题/判断题
questionDetailVo.setType(
Objects.requireNonNull(
questionTypeRepository.findById(
question.getQuestionTypeId()
).orElse(null)
).getQuestionTypeDescription()
);
// 获取当前问题的选项。
String optionIdsStr = trimMiddleLine(question.getQuestionOptionIds());
String[] optionIds = optionIdsStr.split("-");
// 获取选项列表。
List<QuestionOption> optionList = questionOptionRepository.findAllById(Arrays.asList(optionIds));
questionDetailVo.setOptions(optionList);
return questionDetailVo;
}
@Override
public List<ExamVo> getExamAll() {
List<Exam> examList = examRepository.findAll();
return getExamVos(examList);
}
private List<ExamVo> getExamVos(List<Exam> examList) {
// 需要自定义的exam列表。
List<ExamVo> examVoList = new ArrayList<>();
// 循环完成每个属性的定制。
for (Exam exam : examList) {
ExamVo examVo = new ExamVo();
// 先尽量复制能复制的所有属性。
BeanUtils.copyProperties(exam, examVo);
// 设置问题的创建者。
examVo.setExamCreator(
Objects.requireNonNull(
userRepository.findById(
exam.getExamCreatorId()
).orElse(null)
).getUserUsername()
);
// 获取所有单选题列表并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上。
List<ExamQuestionSelectVo> radioQuestionVoList = new ArrayList<>();
List<Question> radioQuestionList = questionRepository.findAllById(
Arrays.asList(exam.getExamQuestionIdsRadio().split("-"))
);
for (Question question : radioQuestionList) {
ExamQuestionSelectVo radioQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, radioQuestionVo);
radioQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。
radioQuestionVoList.add(radioQuestionVo);
}
examVo.setExamQuestionSelectVoRadioList(radioQuestionVoList);
// 获取所有多选题列表并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上。
List<ExamQuestionSelectVo> checkQuestionVoList = new ArrayList<>();
List<Question> checkQuestionList = questionRepository.findAllById(
Arrays.asList(exam.getExamQuestionIdsCheck().split("-"))
);
for (Question question : checkQuestionList) {
ExamQuestionSelectVo checkQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, checkQuestionVo);
checkQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。
checkQuestionVoList.add(checkQuestionVo);
}
examVo.setExamQuestionSelectVoCheckList(checkQuestionVoList);
// 获取所有多选题列表并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上。
List<ExamQuestionSelectVo> judgeQuestionVoList = new ArrayList<>();
List<Question> judgeQuestionList = questionRepository.findAllById(
Arrays.asList(exam.getExamQuestionIdsJudge().split("-"))
);
for (Question question : judgeQuestionList) {
ExamQuestionSelectVo judgeQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, judgeQuestionVo);
judgeQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。
judgeQuestionVoList.add(judgeQuestionVo);
}
examVo.setExamQuestionSelectVoJudgeList(judgeQuestionVoList);
// 把examVo加到examVoList中
examVoList.add(examVo);
}
return examVoList;
}
@Override
public ExamQuestionTypeVo getExamQuestionType() {
ExamQuestionTypeVo examQuestionTypeVo = new ExamQuestionTypeVo();
// 获取所有单选题列表并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上。
List<ExamQuestionSelectVo> radioQuestionVoList = new ArrayList<>();
List<Question> radioQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.RADIO.getId());
for (Question question : radioQuestionList) {
ExamQuestionSelectVo radioQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, radioQuestionVo);
radioQuestionVoList.add(radioQuestionVo);
}
examQuestionTypeVo.setExamQuestionSelectVoRadioList(radioQuestionVoList);
// 获取所有多选题列表并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上。
List<ExamQuestionSelectVo> checkQuestionVoList = new ArrayList<>();
List<Question> checkQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.CHECK.getId());
for (Question question : checkQuestionList) {
ExamQuestionSelectVo checkQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, checkQuestionVo);
checkQuestionVoList.add(checkQuestionVo);
}
examQuestionTypeVo.setExamQuestionSelectVoCheckList(checkQuestionVoList);
// 获取所有多选题列表并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上。
List<ExamQuestionSelectVo> judgeQuestionVoList = new ArrayList<>();
List<Question> judgeQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.JUDGE.getId());
for (Question question : judgeQuestionList) {
ExamQuestionSelectVo judgeQuestionVo = new ExamQuestionSelectVo();
BeanUtils.copyProperties(question, judgeQuestionVo);
judgeQuestionVoList.add(judgeQuestionVo);
}
examQuestionTypeVo.setExamQuestionSelectVoJudgeList(judgeQuestionVoList);
return examQuestionTypeVo;
}
@Override
public Exam create(ExamCreateVo examCreateVo, String userId) {
// 在线考试系统创建。
Exam exam = new Exam();
BeanUtils.copyProperties(examCreateVo, exam);
exam.setExamId(IdUtil.simpleUUID());
exam.setExamCreatorId(userId);
exam.setCreateTime(new Date());
exam.setUpdateTime(new Date());
// Todo:这两个日志后面是要在前端传入的,这里暂时定为当前日期
// 设置考试开始时间和结束时间
exam.setExamStartDate(new Date());
exam.setExamEndDate(new Date());
// 初始化选择题、判断题和单选题的id字符串
String radioIdsStr = "";
String checkIdsStr = "";
String judgeIdsStr = "";
// 获取选择题、判断题和单选题的列表
List<ExamQuestionSelectVo> radios = examCreateVo.getRadios();
List<ExamQuestionSelectVo> checks = examCreateVo.getChecks();
List<ExamQuestionSelectVo> judges = examCreateVo.getJudges();
// 初始化选择题、判断题和单选题的计数器
int radioCnt = 0, checkCnt = 0, judgeCnt = 0;
// 遍历单选题列表
for (ExamQuestionSelectVo radio : radios) {
// 如果单选题被选中
if (radio.getChecked()) {
// 将单选题的id添加到字符串中
radioIdsStr += radio.getQuestionId() + "-";
// 单选题计数器加1
radioCnt++;
}
}
// 去掉最后一个分隔符
radioIdsStr = replaceLastSeparator(radioIdsStr);
// 遍历判断题列表
for (ExamQuestionSelectVo check : checks) {
// 如果判断题被选中
if (check.getChecked()) {
// 将判断题的id添加到字符串中
checkIdsStr += check.getQuestionId() + "-";
// 判断题计数器加1
checkCnt++;
}
}
// 去掉最后一个分隔符
checkIdsStr = replaceLastSeparator(checkIdsStr);
// 遍历选择题列表
for (ExamQuestionSelectVo judge : judges) {
// 如果选择题被选中
if (judge.getChecked()) {
// 将选择题的id添加到字符串中
judgeIdsStr += judge.getQuestionId() + "-";
// 选择题计数器加1
judgeCnt++;
}
}
judgeIdsStr = replaceLastSeparator(judgeIdsStr);
exam.setExamQuestionIds(radioIdsStr + "-" + checkIdsStr + "-" + judgeIdsStr);
// 设置各个题目的id
exam.setExamQuestionIdsRadio(radioIdsStr);
exam.setExamQuestionIdsCheck(checkIdsStr);
exam.setExamQuestionIdsJudge(judgeIdsStr);
// 计算总分数
int examScore = radioCnt * exam.getExamScoreRadio() + checkCnt * exam.getExamScoreCheck() + judgeCnt * exam.getExamScoreJudge();
exam.setExamScore(examScore);
examRepository.save(exam);
return exam;
}
@Override
public Exam update(ExamVo examVo, String userId) {
// 创建一个新的Exam对象
Exam exam = new Exam();
// 将examVo中的属性值复制到exam对象中
BeanUtils.copyProperties(examVo, exam);
// 设置考试更新人为最新的创建人
exam.setExamCreatorId(userId);
// 记录考试更新日期
exam.setUpdateTime(new Date());
// 初始化选择题、判断题、单选题的id字符串
String radioIdsStr = "";
String checkIdsStr = "";
String judgeIdsStr = "";//djfndiosbchjdshjiowceduikmn
// 获取选择题、判断题、单选题的列表
List<ExamQuestionSelectVo> radios = examVo.getExamQuestionSelectVoRadioList();
List<ExamQuestionSelectVo> checks = examVo.getExamQuestionSelectVoCheckList();
List<ExamQuestionSelectVo> judges = examVo.getExamQuestionSelectVoJudgeList();
// 初始化选择题、判断题、单选题的数量
int radioCnt = 0, checkCnt = 0, judgeCnt = 0;
// 遍历选择题列表将选中的题目id添加到字符串中并统计选择题数量
for (ExamQuestionSelectVo radio : radios) {
if (radio.getChecked()) {
radioIdsStr += radio.getQuestionId() + "-";
radioCnt++;
}
}
// 去除最后一个分隔符
radioIdsStr = replaceLastSeparator(radioIdsStr);
// 遍历判断题列表将选中的题目id添加到字符串中并统计判断题数量
for (ExamQuestionSelectVo check : checks) {
if (check.getChecked()) {
checkIdsStr += check.getQuestionId() + "-";
checkCnt++;
}
}
// 去除最后一个分隔符
checkIdsStr = replaceLastSeparator(checkIdsStr);
// 遍历单选题列表将选中的题目id添加到字符串中并统计单选题数量
for (ExamQuestionSelectVo judge : judges) {
if (judge.getChecked()) {
judgeIdsStr += judge.getQuestionId() + "-";
judgeCnt++;
}
}
// 去除最后一个分隔符。
judgeIdsStr = replaceLastSeparator(judgeIdsStr);
// 设置各个题目的id。
exam.setExamQuestionIds(radioIdsStr + "-" + checkIdsStr + "-" + judgeIdsStr);
exam.setExamQuestionIdsRadio(radioIdsStr);
exam.setExamQuestionIdsCheck(checkIdsStr);
exam.setExamQuestionIdsJudge(judgeIdsStr);
// 计算总分数。
int examScore = radioCnt * exam.getExamScoreRadio() + checkCnt * exam.getExamScoreCheck() + judgeCnt * exam.getExamScoreJudge();
exam.setExamScore(examScore);
// 保存exam对象。
examRepository.save(exam);
// 返回exam对象。
return exam;
}
@Override
public List<ExamCardVo> getExamCardList() {
List<Exam> examList = examRepository.findAll();
List<ExamCardVo> examCardVoList = new ArrayList<>();
for (Exam exam : examList) {
ExamCardVo examCardVo = new ExamCardVo();
BeanUtils.copyProperties(exam, examCardVo);
examCardVoList.add(examCardVo);
}
return examCardVoList;
}
@Override
public ExamDetailVo getExamDetail(String id) {
Exam exam = examRepository.findById(id).orElse(null);
ExamDetailVo examDetailVo = new ExamDetailVo();
examDetailVo.setExam(exam);
assert exam != null;
examDetailVo.setRadioIds(exam.getExamQuestionIdsRadio().split("-"));
examDetailVo.setCheckIds(exam.getExamQuestionIdsCheck().split("-"));
examDetailVo.setJudgeIds(exam.getExamQuestionIdsJudge().split("-"));
return examDetailVo;
}
@Override
public ExamRecord judge(String userId, String examId, HashMap<String, List<String>> answersMap) {
// 开始考试判分啦~~~。
// 1.首先获取考试对象和选项数组。
ExamDetailVo examDetailVo = getExamDetail(examId);
Exam exam = examDetailVo.getExam();
// 2.然后获取该考试下所有的题目信息。
List<String> questionIds = new ArrayList<>();
// 2.1 题目id的数组。
List<String> radioIdList = Arrays.asList(examDetailVo.getRadioIds());
List<String> checkIdList = Arrays.asList(examDetailVo.getCheckIds());
List<String> judgeIdList = Arrays.asList(examDetailVo.getJudgeIds());
questionIds.addAll(radioIdList);
questionIds.addAll(checkIdList);
questionIds.addAll(judgeIdList);
// 2.2 每种题目的分数。
int radioScore = exam.getExamScoreRadio();
int checkScore = exam.getExamScoreCheck();
int judgeScore = exam.getExamScoreJudge();
// 2.3 根据问题id的数组拿到所有的问题对象供下面步骤用。
List<Question> questionList = questionRepository.findAllById(questionIds);
Map<String, Question> questionMap = new HashMap<>();
for (Question question : questionList) {
questionMap.put(question.getQuestionId(), question);
}
// 3.根据正确答案和用户作答信息进行判分。
Set<String> questionIdsAnswer = answersMap.keySet();
// 存储当前考试每个题目的得分情况。
Map<String, Integer> judgeMap = new HashMap<>();
// 考生作答地每个题目的选项(题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔),用于查看考试详情。
// 例子题目1的id_作答选项1-作答选项2&题目2的id_作答选项1&题目3_作答选项1-作答选项2-作答选项3。
StringBuilder answerOptionIdsSb = new StringBuilder();
// 用户此次考试的总分。
int totalScore = 0;
for (String questionId : questionIdsAnswer) {
// 获取用户作答地这个题的答案信息。
Question question = questionMap.get(questionId);
// 获取答案选项。
String questionAnswerOptionIds = replaceLastSeparator(question.getQuestionAnswerOptionIds());
List<String> questionAnswerOptionIdList = Arrays.asList(questionAnswerOptionIds.split("-"));
Collections.sort(questionAnswerOptionIdList);
String answerStr = listConcat(questionAnswerOptionIdList);
// 获取用户作答。
List<String> questionUserOptionIdList = answersMap.get(questionId);
Collections.sort(questionUserOptionIdList);
String userStr = listConcat(questionUserOptionIdList);
// 判断questionAnswerOptionIds和answersMap里面的答案是否相等。
if (answerStr.equals(userStr)) {
// 说明题目作答正确,下面根据题型给分。
int score = 0;
if (radioIdList.contains(questionId)) {
score = radioScore;
}
if (checkIdList.contains(questionId)) {
score = checkScore;
}
if (judgeIdList.contains(questionId)) {
score = judgeScore;
}
// 累计本次考试得分。
totalScore += score;
// True代表题目答对。
answerOptionIdsSb.append(questionId + "@True_" + userStr + "$");
judgeMap.put(questionId, score);
} else {
// 说明题目作答错误,直接判零分,False代表题目答错。
answerOptionIdsSb.append(questionId + "@False_" + userStr + "$");
judgeMap.put(questionId, 0);
}
}
// 4.计算得分记录本次考试结果存到ExamRecord中。
ExamRecord examRecord = new ExamRecord();
examRecord.setExamRecordId(IdUtil.simpleUUID());
examRecord.setExamId(examId);
// 注意去掉最后可能有的&_-。
examRecord.setAnswerOptionIds(replaceLastSeparator(answerOptionIdsSb.toString()));
examRecord.setExamJoinerId(userId);
examRecord.setExamJoinDate(new Date());
examRecord.setExamJoinScore(totalScore);
examRecordRepository.save(examRecord);
return examRecord;
}
@Override
public List<ExamRecordVo> getExamRecordList(String userId) {
// 获取指定用户下的考试记录列表。
List<ExamRecord> examRecordList = examRecordRepository.findByExamJoinerIdOrderByExamJoinDateDesc(userId);
List<ExamRecordVo> examRecordVoList = new ArrayList<>();
for (ExamRecord examRecord : examRecordList) {
ExamRecordVo examRecordVo = new ExamRecordVo();
// 根据考试记录中的考试ID获取考试信息
Exam exam = examRepository.findById(examRecord.getExamId()).orElse(null);
examRecordVo.setExam(exam);
// 根据用户ID获取用户信息
User user = userRepository.findById(userId).orElse(null);
examRecordVo.setUser(user);
// 设置考试记录信息
examRecordVo.setExamRecord(examRecord);
examRecordVoList.add(examRecordVo);
}
return examRecordVoList;
}
@Override
public RecordDetailVo getRecordDetail(String recordId) {
// 获取考试详情的封装对象。
ExamRecord record = examRecordRepository.findById(recordId).orElse(null);
RecordDetailVo recordDetailVo = new RecordDetailVo();
recordDetailVo.setExamRecord(record);
// 用户的答案,需要解析。
HashMap<String, List<String>> answersMap = new HashMap<>();
HashMap<String, String> resultsMap = new HashMap<>();
assert record != null;
String answersStr = record.getAnswerOptionIds();
// $分隔题目,因为$在正则中有特殊用途(行尾),所以需要括起来。
String[] questionArr = answersStr.split("[$]");
for (String questionStr : questionArr) {
System.out.println(questionStr);
// 区分开题目标题和选项。
String[] questionTitleResultAndOption = questionStr.split("_");
String[] questionTitleAndResult = questionTitleResultAndOption[0].split("@");
String[] questionOptions = questionTitleResultAndOption[1].split("-");
// 题目:答案选项。
answersMap.put(questionTitleAndResult[0], Arrays.asList(questionOptions));
// 题目True / False。
resultsMap.put(questionTitleAndResult[0], questionTitleAndResult[1]);
}
recordDetailVo.setAnswersMap(answersMap);
recordDetailVo.setResultsMap(resultsMap);
// 下面再计算正确答案的map。
ExamDetailVo examDetailVo = getExamDetail(record.getExamId());
List<String> questionIdList = new ArrayList<>();
questionIdList.addAll(Arrays.asList(examDetailVo.getRadioIds()));
questionIdList.addAll(Arrays.asList(examDetailVo.getCheckIds()));
questionIdList.addAll(Arrays.asList(examDetailVo.getJudgeIds()));
// 获取所有的问题对象。
List<Question> questionList = questionRepository.findAllById(questionIdList);
HashMap<String, List<String>> answersRightMap = new HashMap<>();
for (Question question : questionList) {
// 记得去掉最后可能出现的特殊字符。
String questionAnswerOptionIdsStr = replaceLastSeparator(question.getQuestionAnswerOptionIds());
String[] questionAnswerOptionIds = questionAnswerOptionIdsStr.split("-");
answersRightMap.put(question.getQuestionId(), Arrays.asList(questionAnswerOptionIds));
}
recordDetailVo.setAnswersRightMap(answersRightMap);
return recordDetailVo;
}
/**
* -
*
* @param str
* @return -
*/
private String replaceLastSeparator(String str) {
String lastChar = str.substring(str.length() - 1);
// 题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔。
if ("-".equals(lastChar) || "_".equals(lastChar) || "$".equals(lastChar)) {
str = StrUtil.sub(str, 0, str.length() - 1);
}
return str;
}
/**
* -
*
* @param strList
* @return -
*/
private String listConcat(List<String> strList) {
StringBuilder sb = new StringBuilder();
for (String str : strList) {
sb.append(str);
sb.append("-");
}
return replaceLastSeparator(sb.toString());
}
}
//注释完毕

@ -1,196 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-17 08:03
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import lsgwr.exam.dto.RegisterDTO;
import lsgwr.exam.entity.Action;
import lsgwr.exam.entity.Page;
import lsgwr.exam.entity.Role;
import lsgwr.exam.entity.User;
import lsgwr.exam.enums.LoginTypeEnum;
import lsgwr.exam.enums.RoleEnum;
import lsgwr.exam.qo.LoginQo;
import lsgwr.exam.repository.ActionRepository;
import lsgwr.exam.repository.PageRepository;
import lsgwr.exam.repository.RoleRepository;
import lsgwr.exam.repository.UserRepository;
import lsgwr.exam.service.UserService;
import lsgwr.exam.utils.JwtUtils;
import lsgwr.exam.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PageRepository pageRepository;
@Autowired
ActionRepository actionRepository;
@Override
public User register(RegisterDTO registerDTO) {
try {
User user = new User();
user.setUserId(IdUtil.simpleUUID());
// 好像还缺少个用户名,用"exam_user_手机号"来注册需要校验唯一性数据字段已经设置unique了失败会异常地
String defaultUsername = "user";
user.setUserUsername(defaultUsername + "_" + registerDTO.getMobile());
// 初始化昵称和用户名相同
user.setUserNickname(user.getUserUsername());
// 这里还需要进行加密处理后续解密用Base64.decode()
user.setUserPassword(Base64.encode(registerDTO.getPassword()));
// 默认设置为学生身份,需要老师和学生身份地话需要管理员修改
user.setUserRoleId(RoleEnum.STUDENT.getId());
// 设置头像图片地址, 先默认一个地址,后面用户可以自己再改
String defaultAvatar = "http://d.lanrentuku.com/down/png/1904/business_avatar/8_avatar_2754583.png";
user.setUserAvatar(defaultAvatar);
// 设置描述信息,随便设置段默认的
user.setUserDescription("welcome to online exam system");
// 需要验证这个邮箱是不是已经存在数据字段已经设置unique了失败会异常地
user.setUserEmail(registerDTO.getEmail());
// 需要验证手机号是否已经存在数据字段已经设置unique了失败会异常地
user.setUserPhone(registerDTO.getMobile());
userRepository.save(user);
System.out.println(user);
return user;
} catch (Exception e) {
e.printStackTrace(); // 用户已经存在
// 出异常返回null表示注册失败
return null;
}
}
@Override
public String login(LoginQo loginQo) {
User user;
if (LoginTypeEnum.USERNAME.getType().equals(loginQo.getLoginType())) {
// 登陆者用地是用户名
user = userRepository.findByUserUsername(loginQo.getUserInfo());
} else {
// 登陆者用地是邮箱
user = userRepository.findByUserEmail(loginQo.getUserInfo());
}
if (user != null) {
// 如果user不是null即能找到才能验证用户名和密码
// 数据库存的密码
String passwordDb = Base64.decodeStr(user.getUserPassword());
// 用户请求参数中的密码
String passwordQo = loginQo.getPassword();
System.out.println(passwordDb);
System.out.println(passwordQo);
if (passwordQo.equals(passwordDb)) {
// 如果密码相等地话说明认证成功,返回生成的token有效期为一天
return JwtUtils.genJsonWebToken(user);
}
}
return null;
}
@Override
public UserVo getUserInfo(String userId) {
// 根据用户ID从数据库中查找用户信息
User user = userRepository.findById(userId).orElse(null);
// 创建一个UserVo对象
UserVo userVo = new UserVo();
// 断言user对象不为空
assert user != null;
// 将user对象的属性复制到userVo对象中
BeanUtils.copyProperties(user, userVo);
// 返回userVo对象
return userVo;
}
@Override
public UserInfoVo getInfo(String userId) {
// 根据用户ID查询用户信息
User user = userRepository.findById(userId).orElse(null);
// 断言用户信息不为空
assert user != null;
// 创建用户信息视图对象
UserInfoVo userInfoVo = new UserInfoVo();
// 1.尽可能的拷贝属性
BeanUtils.copyProperties(user, userInfoVo);
// 获取用户角色ID
Integer roleId = user.getUserRoleId();
// 根据角色ID查询角色信息
Role role = roleRepository.findById(roleId).orElse(null);
// 断言角色信息不为空
assert role != null;
// 获取角色名称
String roleName = role.getRoleName();
// 2.设置角色名称
userInfoVo.setRoleName(roleName);
// 3.设置当前用户的角色细节
RoleVo roleVo = new RoleVo();
BeanUtils.copyProperties(role, roleVo);
// 4.设置角色的可访问页面
String rolePageIds = role.getRolePageIds();
String[] pageIdArr = rolePageIds.split("-");
List<PageVo> pageVoList = new ArrayList<>();
for (String pageIdStr : pageIdArr) {
// 获取页面的id
Integer pageId = Integer.parseInt(pageIdStr);
// 4.1 向Role中添加Page
Page page = pageRepository.findById(pageId).orElse(null);
PageVo pageVo = new PageVo();
BeanUtils.copyProperties(page, pageVo);
// 4.2 向Page中添加action
// 创建一个ActionVo类型的列表
List<ActionVo> actionVoList = new ArrayList<>();
// 获取页面中的actionIds字符串
String actionIdsStr = page.getActionIds();
// 将actionIds字符串按照"-"进行分割,得到一个字符串数组
String[] actionIdArr = actionIdsStr.split("-");
// 遍历字符串数组
for (String actionIdStr : actionIdArr) {
// 将字符串转换为整数
Integer actionId = Integer.parseInt(actionIdStr);
// 根据actionId从数据库中查找对应的Action对象
Action action = actionRepository.findById(actionId).orElse(null);
// 创建一个ActionVo对象
ActionVo actionVo = new ActionVo();
// 断言action对象不为空
assert action != null;
// 将action对象的属性值复制到actionVo对象中
BeanUtils.copyProperties(action, actionVo);
// 将actionVo对象添加到列表中
actionVoList.add(actionVo);
}
// 设置actionVoList到pageVo中然后把pageVo加到pageVoList中
pageVo.setActionVoList(actionVoList);
// 设置pageVoList下面再设置到RoleVo中
pageVoList.add(pageVo);
}
// 设置PageVo的集合到RoleVo中
roleVo.setPageVoList(pageVoList);
// 最终把PageVo设置到UserInfoVo中这样就完成了拼接
userInfoVo.setRoleVo(roleVo);
return userInfoVo;
}
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 08:20
* Description :
*/
package lsgwr.exam.service;

@ -1,153 +0,0 @@
package lsgwr.exam.utils;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/***********************************************************
* @note :
* @author : 广
* @version : V1.0 at 2019/5/19 16:15
***********************************************************/
@Slf4j
public class FileTransUtil {
/**
*
*
* @param uploadfile
* @param dir
* @return
*/
public static String uploadFile(MultipartFile uploadfile, String dir) {
log.info("Single file upload!");
if (uploadfile.isEmpty()) {
return "文件名不能为空";
}
try {
saveUploadedFiles(Arrays.asList(uploadfile), dir);
} catch (IOException e) {
e.printStackTrace();
return "后台服务异常";
}
log.info("file upload successfully! " + dir);
return "文件上传成功";
}
/**
*
*
* @param uploadfiles
* @param dir
* @return
*/
public static String uploadFiles(MultipartFile[] uploadfiles, String dir) {
// 打印调试信息
log.debug("Multiple file upload!");
// 将上传的文件名拼接成一个字符串
String uploadedFileName = Arrays.stream(uploadfiles).map(x -> x.getOriginalFilename()).filter(x -> !StringUtils.isEmpty(x)).collect(Collectors.joining(" , "));
// 如果文件名为空,则返回错误信息
if (StringUtils.isEmpty(uploadedFileName)) {
return "文件名不能为空";
}
try {
// 调用工具类保存上传的文件
FileTransUtil.saveUploadedFiles(Arrays.asList(uploadfiles), dir);
} catch (IOException e) {
// 如果保存文件时发生异常,则返回错误信息
return "后台服务异常";
}
// 打印上传成功的日志信息
log.info("file upload successfully! " + uploadedFileName);
// 返回上传成功的提示信息
return "文件上传成功";
}
/**
*
*
* @param files
* @throws IOException
*/
// 保存上传的文件
public static void saveUploadedFiles(List<MultipartFile> files, String dir) throws IOException {
// 遍历文件列表
for (MultipartFile file : files) {
// 如果文件为空,则跳过
if (file.isEmpty()) {
continue;
}
// 如果文件夹不存在,则创建
if (!FileUtil.exist(dir)) {
// 文件夹不存在就创建
FileUtil.mkdir(dir);
}
// 获取文件的字节数组
byte[] bytes = file.getBytes();
// 获取文件的原始文件名,并替换反斜杠为正斜杠
String fileName = file.getOriginalFilename().replace("\\", "/");
// 如果文件名中包含斜杠,则说明是上传文件夹
if (fileName.lastIndexOf('/')>0){
// 上传文件夹的时候会有这种情况
// 获取文件夹路径
String fileDir = dir + "/" + fileName.substring(0, fileName.lastIndexOf('/'));
// 如果文件夹不存在,则创建
if (!FileUtil.exist(fileDir)) {
// 文件夹不存在就创建,创建文件夹的时候会用到
FileUtil.mkdir(fileDir);
}
}
// 获取文件的路径
Path path = Paths.get(dir + "/" + fileName);
// 将文件写入路径
Files.write(path, bytes);
}
}
/**
*
*
* @param filePath
* @return
* @throws IOException
*/
public static ResponseEntity<InputStreamResource> downloadFile(String filePath) throws IOException {
// 记录下载文件的信息
log.info("downloading file : " + filePath);
// 创建文件系统资源
FileSystemResource file = new FileSystemResource(filePath);
// 创建响应头
HttpHeaders headers = new HttpHeaders();
// 设置缓存控制
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
// 设置文件下载时的文件名
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", new String(file.getFilename().getBytes("gbk"), "iso-8859-1")));
// 设置缓存控制
headers.add("Pragma", "no-cache");
// 设置缓存控制
headers.add("Expires", "0");
// 打印文件名
System.out.println(file.getFilename());
// 返回响应实体
return ResponseEntity
.ok()
.headers(headers)
.contentLength(file.contentLength())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(file.getInputStream()));
}
}

@ -1,189 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-19 10:27
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.utils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
@Service
public class FileUtils {
/**
* urlfile
*
* @param url
* @param suffix
*/
// 根据URL创建文件
public static File createFileByUrl(String url, String suffix) {
// 从URL获取图片字节数组
byte[] byteFile = getImageFromNetByUrl(url);
// 如果字节数组不为空
if (byteFile != null) {
// 从字节数组获取文件
File file = getFileFromBytes(byteFile, suffix);
// 返回文件
return file;
} else {
// 否则返回null
return null;
}
}
/**
*
*
* @param strUrl
* @return
*/
private static byte[] getImageFromNetByUrl(String strUrl) {
try {
// 创建URL对象
URL url = new URL(strUrl);
// 打开连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置请求方法
conn.setRequestMethod("GET");
// 设置连接超时时间
conn.setConnectTimeout(5 * 1000);
// 通过输入流获取图片数据
InputStream inStream = conn.getInputStream();
// 得到图片的二进制数据
byte[] btImg = readInputStream(inStream);
return btImg;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
*
*
* @param inStream
* @return
* @throws Exception
*/
private static byte[] readInputStream(InputStream inStream) throws Exception {
// 创建一个ByteArrayOutputStream对象用于存储读取的字节数据
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// 创建一个字节数组,用于存储每次读取的字节数据
byte[] buffer = new byte[1024];
// 定义一个变量,用于存储每次读取的字节数
int len = 0;
// 循环读取输入流中的数据,直到读取完毕
while ((len = inStream.read(buffer)) != -1) {
// 将读取的字节数据写入ByteArrayOutputStream对象中
outStream.write(buffer, 0, len);
}
// 关闭输入流
inStream.close();
// 将ByteArrayOutputStream对象中的字节数据转换为字节数组并返回
return outStream.toByteArray();
}
// 创建临时文件
// 根据字节数组和后缀名创建临时文件
private static File getFileFromBytes(byte[] b, String suffix) {
// 定义输出流
BufferedOutputStream stream = null;
// 定义文件
File file = null;
try {
// 创建临时文件
file = File.createTempFile("pattern", "." + suffix);
// 输出临时文件位置
System.out.println("临时文件位置:" + file.getCanonicalPath());
// 创建文件输出流
FileOutputStream fstream = new FileOutputStream(file);
// 创建缓冲输出流
stream = new BufferedOutputStream(fstream);
// 将字节数组写入文件
stream.write(b);
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
} finally {
// 关闭输出流
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// 打印异常信息
e.printStackTrace();
}
}
}
// 返回文件
return file;
}
// 创建一个MultipartFile对象根据给定的url
public static MultipartFile createImg(String url) {
try {
// File转换成MutipartFile
File file = FileUtils.createFileByUrl(url, "jpg");
FileInputStream inputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), inputStream);
return multipartFile;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static MultipartFile fileToMultipart(String filePath) {
try {
// File转换成MutipartFile
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), "png", "image/png", inputStream);
return multipartFile;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
FileUtils.createFileByUrl("http://122.112.151.149:8888/group1/M00/00/00/wKgAkF0HyPeAAisRAADs167VCfA155.png", "png");
FileUtils.createImg("http://122.112.151.149:8888/group1/M00/00/00/wKgAkF0HyPeAAisRAADs167VCfA155.png");
}
public static boolean base64ToFile(String filePath, String base64Data) throws Exception {
// 定义变量dataPrix和data用于存储base64Data中的数据
String dataPrix = "";
String data = "";
// 判断base64Data是否为空
if (base64Data == null || "".equals(base64Data)) {
return false;
} else {
// 将base64Data按照"base64,"进行分割获取dataPrix和data
String[] d = base64Data.split("base64,");
if (d != null && d.length == 2) {
dataPrix = d[0];
data = d[1];
} else {
return false;
}
}
// 因为BASE64Decoder的jar问题此处使用spring框架提供的工具包
byte[] bs = Base64Utils.decodeFromString(data);
// 使用apache提供的工具类操作流
org.apache.commons.io.FileUtils.writeByteArrayToFile(new File(filePath), bs);
return true;
}
}

@ -1,64 +0,0 @@
/***********************************************************
* @Description : JWTJWTtokentoken
* @author : 广(Laing Shan Guang)
* @date : 2019-05-21 08:15
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.utils;
import lsgwr.exam.entity.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtils {
/**
* token
*/
private static final String SUBJECT = "lsg_exam";
/**
* 1
*/
private static final long EXPIRE = 1000 * 60 * 60 * 24;
private static final String APP_SECRET = "liangshanguang";
public static String genJsonWebToken(User user) {
// 判断用户信息是否为空
if (user == null || user.getUserId() == null || user.getUserUsername() == null || user.getUserAvatar() == null) {
return null;
}
// 使用Jwts.builder()创建一个JWT对象
return Jwts.builder().setSubject(SUBJECT)
// 下面3行设置token中间字段携带用户的信息
.claim("id", user.getUserId())
.claim("username", user.getUserUsername())
.claim("avatar", user.getUserAvatar())
// 设置签发时间
.setIssuedAt(new Date())
// 设置过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
// 使用HS256算法进行签名
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
// 生成的结果字符串太长,这里压缩下
.compact();
}
/**
* token
*
* @param token token
* @return
*/
public static Claims checkJWT(String token) {
try {
// 使用Jwts解析token并设置签名密钥为APP_SECRET
return Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token).getBody();
} catch (Exception e) {
// 篡改token会导致校验失败走到异常分支这里返回null
return null;
}
}
}

@ -1,33 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-17 07:43
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.utils;
import lsgwr.exam.vo.ResultVO;
public class ResultVOUtil {
// 返回一个包含code、msg和object的ResultVO对象
public static ResultVO success(Integer code, String msg, Object object) {
return new ResultVO(code, msg, object);
}
// 返回一个包含object的ResultVO对象默认code为0msg为"成功"
public static ResultVO success(Object object) {
return new ResultVO(0, "成功", object);
}
// 返回一个默认的ResultVO对象默认code为0msg为"成功"object为null
public static ResultVO success() {
return new ResultVO(0, "成功", null);
}
// 返回一个包含code和msg的ResultVO对象默认object为null
public static ResultVO error(Integer code, String msg) {
return new ResultVO(code, msg, null);
}
}

@ -1,5 +0,0 @@
/*
* Created By Liang Shan Guang at 2019-05-14 08:19
* Description : , Hutool
*/
package lsgwr.exam.utils;

@ -1,25 +0,0 @@
/***********************************************************
* @Description : Action
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 13:50
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class ActionVo {
// 使用@JsonProperty注解将actionName属性映射到JSON中的action字段
@JsonProperty("action")
private String actionName;
// 使用@JsonProperty注解将actionDescription属性映射到JSON中的describe字段
@JsonProperty("describe")
private String actionDescription;
// 使用@JsonProperty注解将defaultCheck属性映射到JSON中的defaultCheck字段
@JsonProperty("defaultCheck")
private Boolean defaultCheck;
}

@ -1,36 +0,0 @@
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @Description: ,便JSON
* API,JSON
* Lombok@Datagettersetter
* Jackson@JsonPropertyJSON使
*/
@Data
public class ExamCardVo {
//考试ID
@JsonProperty("id")
private String examId;
//考试名称
@JsonProperty("title")
private String examName;
//考试头像
@JsonProperty("avatar")
private String examAvatar;
//考试描述
@JsonProperty("content")
private String examDescription;
//考试分数
@JsonProperty("score")
private Integer examScore;
//考试限制的时间,单位为分钟
@JsonProperty("elapse")
private Integer examTimeLimit;
}

@ -1,58 +0,0 @@
/***********************************************************
* @Description : examCreatorIdtoken
* @author : 广(Laing Shan Guang)
* @date : 2019-06-17 08:14
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class ExamCreateVo {
@JsonProperty("name")
private String examName;
@JsonProperty("avatar")
private String examAvatar;
@JsonProperty("desc")
private String examDescription;
//试时长,单位分钟
@JsonProperty("elapse")
private Integer examTimeLimit;
//单选题
private List<ExamQuestionSelectVo> radios;
//多选题
private List<ExamQuestionSelectVo> checks;
//判断题
private List<ExamQuestionSelectVo> judges;
//单选题的分数
@JsonProperty("radioScore")
private Integer examScoreRadio;
//多选题的分数
@JsonProperty("checkScore")
private Integer examScoreCheck;
//判断题每题的分数
@JsonProperty("judgeScore")
private Integer examScoreJudge;
}

@ -1,30 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-24 08:14
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import lsgwr.exam.entity.Exam;
import lombok.Data;
@Data
public class ExamDetailVo {
//试的基本信息对象
private Exam exam;
//单选题的id数组
private String[] radioIds;
//多选题的id数组
private String[] checkIds;
//判断题的id数组
private String[] judgeIds;
}

@ -1,35 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-22 17:00
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class ExamPageVo {
//分页时每个分页的大小
private Integer pageSize;
//当前是在第几页注意要比前端传过来地小1
private Integer pageNo;
//一共有多少条符合条件的记录
private Long totalCount;
//一共有多少页
private Integer totalPage;
//当前页的详细数据
@JsonProperty("data")
private List<ExamVo> examVoList;
}

@ -1,28 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-17 23:10
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class ExamQuestionSelectVo {
// 问题ID
@JsonProperty("id")
private String questionId;
// 问题名称
@JsonProperty("name")
private String questionName;
/**
* .falsetrue
*
*/
@JsonProperty("checked")
private Boolean checked = false;
}

@ -1,27 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-23 11:00
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class ExamQuestionTypeVo {
// 单选题列表
@JsonProperty("radios")
private List<ExamQuestionSelectVo> examQuestionSelectVoRadioList;
// 多选题列表
@JsonProperty("checks")
private List<ExamQuestionSelectVo> examQuestionSelectVoCheckList;
// 判断题列表
@JsonProperty("judges")
private List<ExamQuestionSelectVo> examQuestionSelectVoJudgeList;
}

@ -1,26 +0,0 @@
/***********************************************************
* @Description : VO
* @author : 广(Liang Shan Guang)
* @date : 2019/10/25 7:42
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import lsgwr.exam.entity.Exam;
import lsgwr.exam.entity.ExamRecord;
import lsgwr.exam.entity.User;
import lombok.Data;
@Data
public class ExamRecordVo {
//当前考试记录对应的考试
private Exam exam;
//当前考试对应的内容
private ExamRecord examRecord;
//参加考试的用户信息
private User user;
}

@ -1,100 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019/5/14 07:42
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class ExamVo {
// 考试id
@JsonProperty("id")
private String examId;
// 考试名称
@JsonProperty("name")
private String examName;
// 考试头像
@JsonProperty("avatar")
private String examAvatar;
// 考试描述
@JsonProperty("desc")
private String examDescription;
// 单选题列表
@JsonProperty("radios")
private List<ExamQuestionSelectVo> examQuestionSelectVoRadioList;
// 多选题列表
@JsonProperty("checks")
private List<ExamQuestionSelectVo> examQuestionSelectVoCheckList;
// 判断题列表
@JsonProperty("judges")
private List<ExamQuestionSelectVo> examQuestionSelectVoJudgeList;
// 考试总分数
@JsonProperty("score")
private Integer examScore;
// 单选题分数
@JsonProperty("radioScore")
private Integer examScoreRadio;
// 多选题分数
@JsonProperty("checkScore")
private Integer examScoreCheck;
// 判断题分数
@JsonProperty("judgeScore")
private Integer examScoreJudge;
/**
* id
*/
@JsonProperty("creator")
private String examCreator;
/**
*
*/
@JsonProperty("elapse")
private Integer examTimeLimit;
/**
*
*/
@JsonProperty("startDate")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examStartDate;
/**
*
*/
@JsonProperty("endDate")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examEndDate;
/**
*
*/
@JsonProperty("createTime")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
*
*/
@JsonProperty("updateTime")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

@ -1,73 +0,0 @@
package lsgwr.exam.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*
* @author liangshanguang
* @date 2019-05-22 08:11
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonData implements Serializable {
private static final long serialVersionUID = 1L;
//状态码 0 表示成功1表示处理中-1表示失败
private Integer code;
//数据
private Object data;
//描述
private String msg;
//成功,传入数据
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
//成功,传入数据
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
//失败,传入描述信息
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
//失败,传入描述信息,状态码
public static JsonData buildError(String msg, Integer code) {
return new JsonData(code, null, msg);
}
/**
* ,
*
* @param data
* @param msg
* @return
*/
public static JsonData buildSuccess(Object data, String msg) {
return new JsonData(0, data, msg);
}
//成功,传入数据,及状态码
public static JsonData buildSuccess(Object data, int code) {
return new JsonData(code, data, null);
}
}

@ -1,27 +0,0 @@
/***********************************************************
* @Description : Action
* @author : 广(Laing Shan Guang)
* @date : 2019-05-26 13:46
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class PageVo {
// 使用@JsonProperty注解将actionEntitySet字段映射到JSON中的actionEntitySet字段
@JsonProperty("actionEntitySet")
private List<ActionVo> actionVoList;
// 使用@JsonProperty注解将permissionId字段映射到JSON中的permissionId字段
@JsonProperty("permissionId")
private String pageName;
// 使用@JsonProperty注解将permissionName字段映射到JSON中的permissionName字段
@JsonProperty("permissionName")
private String pageDescription;
}

@ -1,47 +0,0 @@
/***********************************************************
* @Description : ,
* @author : 广(Laing Shan Guang)
* @date : 2019-06-02 13:26
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class QuestionCreateSimplifyVo {
//题目名称
@JsonProperty("name")
private String questionName;
@JsonProperty("desc")
private String questionDescription;
//问题的难度的id
@JsonProperty("level")
private Integer questionLevelId;
//问题的类型(单选、多选、判断等)
@JsonProperty("type")
private Integer questionTypeId;
//题目的类别表,从内容角度划分,比如数学、语文、英语等
@JsonProperty("category")
private Integer questionCategoryId;
//创建选项 里添加的内容
@JsonProperty("option")
private String option;
//问题的选项列表带上了是否是答案的true和false
@JsonProperty("options")
private List<QuestionOptionCreateVo> questionOptionCreateVoList;
}

@ -1,53 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-02 13:26
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class QuestionCreateVo {
//题目名称
@JsonProperty("name")
private String questionName;
@JsonProperty("desc")
private String questionDescription;
//题目的分数,默认值是5
@JsonProperty("score")
private Integer questionScore = 5;
//题目的创建者的id从token中解析得到
@JsonProperty("creator")
private String questionCreatorId;
//问题的难度的id
@JsonProperty("level")
private Integer questionLevelId;
//问题的类型(单选、多选、判断等)
@JsonProperty("type")
private Integer questionTypeId;
//题目的类别表,从内容角度划分,比如数学、语文、英语等
@JsonProperty("category")
private Integer questionCategoryId;
//问题的选项列表带上了是否是答案的true和false
@JsonProperty("options")
private List<QuestionOptionCreateVo> questionOptionCreateVoList;
}

@ -1,36 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-10-20 09:51
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import lsgwr.exam.entity.QuestionOption;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class QuestionDetailVo {
//问题的id
private String id;
//考试题目
private String name;
//考试描述
private String description;
//问题的类型
private String type;
//问题的选项
private List<QuestionOption> options;
//问题的答案,选项的id组成的数组
private List<String> answers = new ArrayList<>();
}

@ -1,24 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-02 20:23
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class QuestionOptionCreateVo {
//问题的内容
@JsonProperty("content")
private String questionOptionContent;
//当前的选项是否是问题大答案
@JsonProperty("answer")
private Boolean answer = false;
}

@ -1,29 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-01 09:45
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class QuestionOptionVo {
// 题目选项ID
@JsonProperty("id")
private String questionOptionId;
// 题目选项内容
@JsonProperty("content")
private String questionOptionContent;
// 是否为答案
@JsonProperty("answer")
private Boolean answer = false;
// 题目选项描述
@JsonProperty("description")
private String questionOptionDescription;
}

@ -1,37 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-28 22:09
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class QuestionPageVo {
//分页时每个分页的大小
private Integer pageSize;
//当前是在第几页注意要比前端传过来地小1
private Integer pageNo;
//一共有多少条符合条件的记录
private Long totalCount;
//一共有多少页
private Integer totalPage;
//当前页的详细数据
@JsonProperty("data")
private List<QuestionVo> questionVoList;
}

@ -1,30 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-06-03 07:35
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lsgwr.exam.entity.QuestionCategory;
import lsgwr.exam.entity.QuestionLevel;
import lsgwr.exam.entity.QuestionType;
import lombok.Data;
import java.util.List;
@Data
public class QuestionSelectionVo {
// 问题类型列表
@JsonProperty("types")
private List<QuestionType> questionTypeList;
// 问题类别列表
@JsonProperty("categories")
private List<QuestionCategory> questionCategoryList;
// 问题等级列表
@JsonProperty("levels")
private List<QuestionLevel> questionLevelList;
}

@ -1,80 +0,0 @@
/***********************************************************
* @Description :
* @author : 广(Laing Shan Guang)
* @date : 2019-05-28 08:17
* @email : liangshanguang2@gmail.com
***********************************************************/
package lsgwr.exam.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class QuestionVo {
// 使用@JsonProperty注解将属性映射到JSON对象的属性
@JsonProperty("id")
private String questionId;
// 使用@JsonProperty注解将属性映射到JSON对象的属性
@JsonProperty("name")
private String questionName;
// 使用@JsonProperty注解将属性映射到JSON对象的属性
@JsonProperty("score")
private Integer questionScore;
//根据questionCreatorId查询创建人
@JsonProperty("creator")
private String questionCreator;
//根据questionLevelId查询问题难度
@JsonProperty("level")
private String questionLevel;
//问题难度级别在数据库表question_level中的id
@JsonProperty("levelId")
private int questionLevelId;
//问题类型根据questionTypeId获取
@JsonProperty("type")
private String questionType;
//问题类型在数据库表question_type中的id
@JsonProperty("typeId")
private int questionTypeId;
//问题分类根据questionCategoryId获得
@JsonProperty("category")
private String questionCategory;
//问题分类在数据库表question_category中的id
@JsonProperty("categoryId")
private int questionCategoryId;
@JsonProperty("description")
private String questionDescription;
//问题选项列表从questionOptionIds获得,需要自己额外给isAnswer赋值
@JsonProperty("options")
private List<QuestionOptionVo> questionOptionVoList;
//更新时间设计表时设置了自动插入当前时间无需在Java代码中设置了。
//同时@DynamicUpdate注解可以时间当数据库数据变化时自动更新无需人工维护
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

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

Loading…
Cancel
Save