初始化项目文件

This commit is contained in:
2025-07-11 16:54:11 +08:00
parent 6bffd582a0
commit 39fedaac16
213 changed files with 16944 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/api_file/logs/
/api_iris/logs/
/api_iris/upload-note/
/api_iris/upload-video/
/api_iris/upload/
/api_iris/static/
/web_vue/node_modules/

View File

@ -0,0 +1,21 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="uwsgi" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N806" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

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

10
.idea/web_ylsa.iml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="TemplatesService">
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/web_vue/node_modules/videojs-font/templates" />
</list>
</option>
</component>
</module>

417
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,417 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="ALL" />
</component>
<component name="ChangeListManager">
<list default="true" id="d6a2de0a-a7ff-4119-8d61-61e927cbea3b" name="更改" comment="添加控制部署项目参数" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="DjangoConsoleOptions" custom-start-script="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)">
<option name="myCustomStartScript" value="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="GOROOT" url="file://$PROJECT_DIR$/../../../../../Program Files/Go" />
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GoLibraries">
<option name="indexEntireGoPath" value="true" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 1
}</component>
<component name="ProjectId" id="2nBHn2r8KaQa3zBkyc6KH6iOlOJ" />
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="1" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;ASKED_MARK_IGNORED_FILES_AS_EXCLUDED&quot;: &quot;true&quot;,
&quot;Django 服务器.web_ylsa.executor&quot;: &quot;Run&quot;,
&quot;Python.build (1).executor&quot;: &quot;Run&quot;,
&quot;Python.build.executor&quot;: &quot;Run&quot;,
&quot;Python.test-2.executor&quot;: &quot;Run&quot;,
&quot;Python.test-api (1).executor&quot;: &quot;Run&quot;,
&quot;Python.test-database.executor&quot;: &quot;Run&quot;,
&quot;Python.test.executor&quot;: &quot;Run&quot;,
&quot;Python.test1.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenDjangoStructureViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.go.formatter.settings.were.checked&quot;: &quot;true&quot;,
&quot;RunOnceActivity.go.migrated.go.modules.settings&quot;: &quot;true&quot;,
&quot;RunOnceActivity.go.modules.go.list.on.any.changes.was.set&quot;: &quot;true&quot;,
&quot;RunOnceActivity.pycharm.django.structure.promotion.once.per.project&quot;: &quot;true&quot;,
&quot;go.import.settings.migrated&quot;: &quot;true&quot;,
&quot;go.sdk.automatically.set&quot;: &quot;true&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/m1582/Documents/project/git/web_ylsa&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\m1582\Documents\project\web_ylsa" />
<recent name="C:\Users\m1582\Documents\project\web_ylsa\build_file\prd" />
<recent name="C:\Users\m1582\Documents\project\web_ylsa\build_file\dev" />
<recent name="C:\Users\m1582\Documents\project\web_ylsa\api_iris" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\m1582\Documents\project\web_ylsa\build_file\dev" />
</key>
</component>
<component name="RunManager" selected="Python.build">
<configuration name="build" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/build_file/prd" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/build_file/prd/build.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="test-api (1)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test-api.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="test-api" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="C:\Users\m1582\Documents\project\web_ylsa\test-api.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="test-database" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test-database.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="web_ylsa" type="Python.DjangoServer" factoryName="Django server">
<module name="web_ylsa" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DJANGO_SETTINGS_MODULE" value="api_django.settings" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="launchJavascriptDebuger" value="false" />
<option name="port" value="8000" />
<option name="host" value="localhost" />
<option name="additionalOptions" value="" />
<option name="browserUrl" value="" />
<option name="runTestServer" value="false" />
<option name="runNoReload" value="false" />
<option name="useCustomRunCommand" value="false" />
<option name="customRunCommand" value="" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.build" />
<item itemvalue="Python.test" />
<item itemvalue="Python.test-database" />
<item itemvalue="Python.test-api (1)" />
<item itemvalue="Python.test-api" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-1d06a55b98c1-0b3e54e931b4-JavaScript-PY-241.18034.82" />
<option value="bundled-python-sdk-975db3bf15a3-2767605e8bc2-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-241.18034.82" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="d6a2de0a-a7ff-4119-8d61-61e927cbea3b" name="更改" comment="" />
<created>1728439714627</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1728439714627</updated>
<workItem from="1728439715912" duration="3818000" />
<workItem from="1728869191254" duration="41432000" />
<workItem from="1729756714840" duration="89000" />
<workItem from="1729821221821" duration="11118000" />
<workItem from="1730080401247" duration="6048000" />
<workItem from="1730858313795" duration="1568000" />
<workItem from="1730859908065" duration="784000" />
<workItem from="1731916564305" duration="25000" />
<workItem from="1734592397916" duration="6000" />
<workItem from="1738911622202" duration="11193000" />
<workItem from="1739257254847" duration="2661000" />
<workItem from="1739845424316" duration="3592000" />
<workItem from="1739950524228" duration="2311000" />
<workItem from="1740129843205" duration="548000" />
<workItem from="1740553077718" duration="1546000" />
<workItem from="1742886523235" duration="51000" />
<workItem from="1743057323661" duration="1395000" />
<workItem from="1743143331607" duration="1321000" />
<workItem from="1744007639533" duration="723000" />
<workItem from="1744187367640" duration="2347000" />
<workItem from="1744247664043" duration="539000" />
<workItem from="1744252275625" duration="1096000" />
<workItem from="1744334448875" duration="11000" />
<workItem from="1744339989887" duration="700000" />
<workItem from="1744611873038" duration="413000" />
<workItem from="1744708847762" duration="2034000" />
<workItem from="1744851262269" duration="17000" />
<workItem from="1744875161555" duration="572000" />
<workItem from="1744965801259" duration="168000" />
<workItem from="1745197142032" duration="2000" />
<workItem from="1745197343015" duration="84000" />
<workItem from="1745203132271" duration="326000" />
<workItem from="1745986591451" duration="2763000" />
<workItem from="1746685782576" duration="14000" />
<workItem from="1747019888171" duration="830000" />
<workItem from="1749172452809" duration="6232000" />
<workItem from="1749605971551" duration="3131000" />
<workItem from="1749610841520" duration="5323000" />
<workItem from="1749634770374" duration="14000" />
<workItem from="1749635230351" duration="15471000" />
<workItem from="1750036455273" duration="3129000" />
<workItem from="1750040176503" duration="6372000" />
<workItem from="1750060142701" duration="67000" />
<workItem from="1750228813586" duration="2077000" />
<workItem from="1750643379036" duration="39000" />
<workItem from="1750646763737" duration="3468000" />
<workItem from="1751611731067" duration="2452000" />
<workItem from="1751849561709" duration="18000" />
<workItem from="1751868405398" duration="3188000" />
<workItem from="1751875050414" duration="3026000" />
<workItem from="1752223269978" duration="639000" />
</task>
<task id="LOCAL-00001" summary="修复部署问题">
<option name="closed" value="true" />
<created>1730080444691</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1730080444691</updated>
</task>
<task id="LOCAL-00002" summary="修复部署问题">
<option name="closed" value="true" />
<created>1730170240151</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1730170240151</updated>
</task>
<task id="LOCAL-00003" summary="修复部署问题">
<option name="closed" value="true" />
<created>1730859757009</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1730859757009</updated>
</task>
<task id="LOCAL-00004" summary="修复部署问题">
<option name="closed" value="true" />
<created>1739259478761</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1739259478761</updated>
</task>
<task id="LOCAL-00005" summary="修复部署问题">
<option name="closed" value="true" />
<created>1739259517144</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1739259517144</updated>
</task>
<task id="LOCAL-00006" summary="修复部署问题">
<option name="closed" value="true" />
<created>1739260593698</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1739260593698</updated>
</task>
<task id="LOCAL-00007" summary="添加控制部署项目参数">
<option name="closed" value="true" />
<created>1739848928421</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1739848928421</updated>
</task>
<task id="LOCAL-00008" summary="添加控制部署项目参数">
<option name="closed" value="true" />
<created>1740130391214</created>
<option name="number" value="00008" />
<option name="presentableId" value="LOCAL-00008" />
<option name="project" value="LOCAL" />
<updated>1740130391214</updated>
</task>
<option name="localTasksCounter" value="9" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnknownFeatures">
<option featureType="com.intellij.fileTypeFactory" implementationName="*.conf" />
<option featureType="dependencySupport" implementationName="javascript:npm:vite" />
<option featureType="dependencySupport" implementationName="python:kafka-python" />
<option featureType="dependencySupport" implementationName="javascript:npm:vue" />
</component>
<component name="Vcs.Log.History.Properties">
<option name="COLUMN_ID_ORDER">
<list>
<option value="Default.Root" />
<option value="Default.Author" />
<option value="Default.Date" />
<option value="Default.Subject" />
<option value="GitHub.CommitStatus" />
</list>
</option>
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="修复部署问题" />
<MESSAGE value="添加控制部署项目参数" />
<option name="LAST_COMMIT_MESSAGE" value="添加控制部署项目参数" />
</component>
<component name="VgoProject">
<integration-enabled>false</integration-enabled>
<settings-migrated>true</settings-migrated>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/web_ylsa$test_2.coverage" NAME="test-2 覆盖结果" MODIFIED="1729044074623" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/web_ylsa$build__1_.coverage" NAME="build (1) 覆盖结果" MODIFIED="1739848134595" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/build_file/dev" />
<SUITE FILE_PATH="coverage/web_ylsa$test_database.coverage" NAME="test-database 覆盖结果" MODIFIED="1749783531430" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/web_ylsa$test1.coverage" NAME="test1 覆盖结果" MODIFIED="1745988774356" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/web_ylsa$test.coverage" NAME="test 覆盖结果" MODIFIED="1751871879944" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/web_ylsa$test_api__1_.coverage" NAME="test-api (1) 覆盖结果" MODIFIED="1747020084599" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/web_ylsa$build.coverage" NAME="build 覆盖结果" MODIFIED="1751938876434" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/build_file/prd" />
</component>
</project>

15
api_file/Dockerfile Normal file
View File

@ -0,0 +1,15 @@
FROM golang:1.22.4
RUN mkdir -p /web \
mkdir -p /web/logs
ENV GOPATH=/web
ENV GOPROXY=https://goproxy.cn,direct
WORKDIR $GOPATH/api_file
COPY . $GOPATH/api_file
RUN go build .
ENTRYPOINT ["./main"]

View File

@ -0,0 +1,11 @@
database:
dsn: web:Song1875.@tcp(43.154.168.226:3306)/web_vue?charset=utf8mb4&parseTime=True&loc=Local
prd: false
logs:
log: logs
nginx: logs/nginx
sys:
jwt: False
User: admin

31
api_file/config/config.go Normal file
View File

@ -0,0 +1,31 @@
package config
import (
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"os"
)
// Config 公共参数
var Config settings
// InitConfig 配置初始化
func InitConfig(version string) error {
var file []byte
var err error
if version == "dev" {
file, err = os.ReadFile("./config/config.dev.yaml")
} else {
file, err = os.ReadFile("./config/config.prd.yaml")
}
if err != nil {
logrus.Errorln("Error reading config file:", err)
return err
}
err = yaml.Unmarshal(file, &Config)
if err != nil {
logrus.Errorln("Error parsing config file:", err)
return err
}
return nil
}

View File

@ -0,0 +1,11 @@
database:
dsn: web_prd:SongPrd1875.@tcp(43.154.168.226:3306)/web_prd?charset=utf8mb4&parseTime=True&loc=Local
prd: true
logs:
log: logs
nginx: logs/nginx
sys:
jwt: True
User:

21
api_file/config/type.d.go Normal file
View File

@ -0,0 +1,21 @@
package config
type settings struct {
Logs *logs `yaml:"logs"`
Database *database `yaml:"database"`
}
type logs struct {
Nginx string `yaml:"nginx"`
Log string `yaml:"log"`
}
type database struct {
Dsn string `yaml:"dsn"`
Prd bool `yaml:"prd"`
}
type sys struct {
Jwt string `yaml:"jwt"`
User string `yaml:"user"`
}

View File

@ -0,0 +1,48 @@
package database
import (
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"main/config"
"sync"
)
var instance *MysqlConnectionPool
var once sync.Once
var db *gorm.DB
var err error
// GetInstance 获取数据库连接池
func GetInstance() *MysqlConnectionPool {
once.Do(func() {
instance = &MysqlConnectionPool{}
})
return instance
}
// InitDataPool 数据库初始化连接
func (m *MysqlConnectionPool) InitDataPool() (isSuccess bool) {
dbConfig := config.Config.Database
if dbConfig.Prd {
db, err = gorm.Open(mysql.Open(dbConfig.Dsn), &gorm.Config{})
} else {
db, err = gorm.Open(mysql.Open(dbConfig.Dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
}
if err != nil {
logrus.Errorln("数据库配置失败:", err)
return false
}
return true
}
// GetMysqlDb 获取数据库连接
func (m *MysqlConnectionPool) GetMysqlDb() (dbCon *gorm.DB) {
return db
}
type MysqlConnectionPool struct {
}

65
api_file/go.mod Normal file
View File

@ -0,0 +1,65 @@
module main
go 1.22.4
require (
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/golang-jwt/jwt/v4 v4.5.1
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72
github.com/kataras/iris/v12 v12.2.11
github.com/shopspring/decimal v1.4.0
github.com/sirupsen/logrus v1.9.3
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.25.10
)
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
github.com/Joker/jade v1.1.3 // indirect
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/iris-contrib/schema v0.0.6 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kataras/blocks v0.0.8 // indirect
github.com/kataras/golog v0.1.11 // indirect
github.com/kataras/pio v0.0.13 // indirect
github.com/kataras/sitemap v0.0.6 // indirect
github.com/kataras/tunnel v0.0.4 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/mailgun/raymond/v2 v2.0.48 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
github.com/tdewolff/minify/v2 v2.20.19 // indirect
github.com/tdewolff/parse/v2 v2.7.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/yosssi/ace v0.0.5 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

207
api_file/go.sum Normal file
View File

@ -0,0 +1,207 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU=
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72 h1:wbkA/QXv1RZmuY2iLvsgmHeiGq4DNvv2Rhj5PQ2oHTI=
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72/go.mod h1:hIyBTK1zUxUaC4Hu8Ba9Z70r2S5ET4+ZKNescqjXld0=
github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk=
github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w=
github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo=
github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM=
github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ=
github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8=
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=

78
api_file/jwtSet/jwt.go Normal file
View File

@ -0,0 +1,78 @@
package jwtSet
//
//import (
// "github.com/iris-contrib/middleware/jwt"
// "github.com/sirupsen/logrus"
// "main/database"
// "main/model"
// "main/utils"
// "time"
//)
//
//var Jwt *jwt.Middleware
//var keys model.JwtKeys
//
//func GetJwtKeys() model.JwtKeys {
// db := database.GetInstance().GetMysqlDb()
// if utils.DataIsNil(keys) || keys.Date != time.Now().Format("2006-01-02") {
// keys = model.JwtKeys{}
// if err := db.Where("date = ? and token = ''", time.Now().Format("2006-01-02")).First(&keys).Error; err != nil {
// logrus.Errorln("sql执行失败", err)
// return model.JwtKeys{}
// }
// }
// if keys.Key == "" {
// keys.Date = time.Now().Format("2006-01-02")
// keys.Key = utils.NewKey(32)
// if err := db.Create(&keys).Error; err != nil {
// logrus.Errorln("sql执行失败", err)
// return model.JwtKeys{}
// }
// }
// if !keys.Updated && !utils.DataIsNil(Jwt) {
// UpdateJwt()
// }
// return keys
//}
////func Init() {
//// if utils.DataIsNil(keys) {
//// GetJwtKeys()
//// }
//// Jwt = jwt.New(jwt.Config{
//// ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
//// return []byte(keys.Key), nil
//// },
//// ErrorHandler: func(context iris.Context, err error) {
//// if err == nil {
//// return
//// }
//// context.StopExecution()
//// context.StatusCode(iris.StatusUnauthorized)
//// context.SetErr(err)
//// },
//// Extractor: jwt.FromAuthHeader,
//// SigningMethod: jwt.SigningMethodHS256,
//// })
//// db := database.GetInstance().GetMysqlDb()
//// keys.Updated = true
//// if err := db.Updates(&keys).Error; err != nil {
//// logrus.Errorln("sql执行失败", err)
//// return
//// }
////}
//
//func UpdateJwt() {
// if utils.DataIsNil(keys) {
// GetJwtKeys()
// }
// Jwt.Config.ValidationKeyGetter = func(token *jwt.Token) (interface{}, error) {
// return []byte(keys.Key), nil
// }
// db := database.GetInstance().GetMysqlDb()
// keys.Updated = true
// if err := db.Updates(&keys).Error; err != nil {
// logrus.Errorln("sql执行失败", err)
// return
// }
//}

81
api_file/main.go Normal file
View File

@ -0,0 +1,81 @@
package main
import (
"fmt"
nested "github.com/antonfisher/nested-logrus-formatter"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/accesslog"
"github.com/sirupsen/logrus"
"main/config"
"main/database"
"main/service"
"main/utils"
"os"
"path"
"time"
)
func main() {
logrus.SetFormatter(&nested.Formatter{HideKeys: true, TimestampFormat: time.RFC3339})
//配置文件初始化
err := config.InitConfig(utils.GetEnvDefault("version", "dev"))
if err != nil {
logrus.Errorln("配置文件初始化失败:", err)
return
}
logrus.Infoln("配置文件初始化完成")
//日志初始化
ac := makeAccessLog()
//应用初始化
app := iris.New()
//应用ac-log
app.UseRouter(ac.Handler)
//错误处理
app.OnAnyErrorCode(handler)
//数据库连接初始化
if !database.GetInstance().InitDataPool() {
return
}
logrus.Infoln("数据库已连接")
//初始化用户信息,系统配置信息,菜单列表
utils.UpdateUserInfo()
utils.UpdateSysSettings()
logrus.Infoln("数据库结构初始化完成")
//jwtSet.Init()
//logrus.Infoln("jwt认证初始化完成")
//接口组
app.PartyFunc("/api", service.Apis)
logrus.Infoln("接口组配置完成")
//应用启动
logrus.Infoln("应用启动")
err = app.Run(iris.Addr(":8081"))
if err != nil {
return
}
}
// 生成acLog实例
func makeAccessLog() *accesslog.AccessLog {
cPath, _ := os.Getwd()
ac := accesslog.File(path.Join(cPath, config.Config.Logs.Log, fmt.Sprintf("access-%s.log", time.Now().Format("2006-01-02"))))
ac.AddOutput(os.Stdout)
ac.IP = true
ac.Delim = ' '
ac.ResponseBody = false
return ac
}
// 接口错误处理
func handler(ctx iris.Context) {
if ctx.GetErr() != nil {
err := ctx.JSON(utils.FormatRes(ctx.GetStatusCode(), ctx.GetErr().Error(), nil))
if err != nil {
return
}
} else {
err := ctx.JSON(utils.FormatRes(ctx.GetStatusCode(), "", nil))
if err != nil {
return
}
}
}

View File

@ -0,0 +1,12 @@
package model
import "gorm.io/gorm"
type BackgammonRoom struct {
RoomId int `json:"room_id"`
Player string `json:"player"`
Winner string `json:"winner"`
Current string `json:"current"`
PawnStatus string `json:"pawn_status"`
gorm.Model
}

19
api_file/model/balance.go Normal file
View File

@ -0,0 +1,19 @@
package model
import "gorm.io/gorm"
type Balances struct {
Username string `json:"username"`
Card string `json:"card"`
Type bool `gorm:"default:false" json:"type"` //1支出型0收入型
Balance float64 `json:"balance"`
gorm.Model
}
type BalanceLogs struct {
Username string
Card string
Date string
Balance float64
gorm.Model
}

28
api_file/model/chess.go Normal file
View File

@ -0,0 +1,28 @@
package model
import (
"gorm.io/gorm"
"time"
)
type ChessStatus struct {
gorm.Model
Players string `json:"players"`
Current string `json:"current"`
IsEnd bool `json:"is_end"`
Status string `json:"status"`
Winner string `json:"winner"`
ChessId string `json:"chess_id"`
}
type ChessStatusLog struct {
gorm.Model
RoomId uint `json:"roomId"`
Current string `json:"current"`
Players string `json:"players"`
IsEnd bool `json:"is_end"`
Status string `json:"status"`
Winner string `json:"winner"`
ChessId string `json:"chess_id"`
Time time.Time `json:"time"`
}

View File

@ -0,0 +1,9 @@
package model
import "gorm.io/gorm"
type RunningCrontab struct {
Name string
CronId int
gorm.Model
}

20
api_file/model/keys.go Normal file
View File

@ -0,0 +1,20 @@
package model
import "gorm.io/gorm"
// DayKeys 每天对应key表
type DayKeys struct {
Date string
Key string
AesKey string
User string
gorm.Model
}
type JwtKeys struct {
Username string
Date string
Key string
Token string
Updated bool `gorm:"default:false"`
gorm.Model
}

31
api_file/model/logs.go Normal file
View File

@ -0,0 +1,31 @@
package model
import "gorm.io/gorm"
// Logs 日志表
type Logs struct {
Method string `json:"method,omitempty"`
Path string `json:"path,omitempty"`
Status string `json:"status,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
Time string `json:"time,omitempty"`
Location string `json:"location,omitempty"`
Ip string `json:"ip,omitempty"`
gorm.Model
}
type LogFileDealLog struct {
Date string
Success bool
gorm.Model
}
// SysLogs 系统容器日志表
type SysLogs struct {
Time string `json:"time,omitempty"`
ContainerName string `json:"container_name,omitempty"`
ContainerImage string `json:"container_image,omitempty"`
Message string `json:"message,omitempty"`
Offset int `json:"offset,omitempty"`
gorm.Model
}

14
api_file/model/menus.go Normal file
View File

@ -0,0 +1,14 @@
package model
import "gorm.io/gorm"
type Menus struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
UserType string `json:"user_type"`
WhiteList string `json:"white_list"`
gorm.Model
}

9
api_file/model/note.go Normal file
View File

@ -0,0 +1,9 @@
package model
import "gorm.io/gorm"
type UserNotes struct {
Username string `json:"username"`
Content string `json:"content"`
gorm.Model
}

18
api_file/model/sudoku.go Normal file
View File

@ -0,0 +1,18 @@
package model
import "gorm.io/gorm"
type Sudoku struct {
Sudoku string `json:"sudoku"`
Username string `json:"username"`
Result string `json:"result"`
gorm.Model
}
type SudokuStatus struct {
SudokuId uint `json:"sudoku_id"`
Username string `json:"username"`
Status string `json:"status"`
Complete bool `json:"complete"`
gorm.Model
}

View File

@ -0,0 +1,14 @@
package model
import (
"gorm.io/gorm"
"time"
)
type SysError struct {
Username string `json:"username"`
Time time.Time `json:"time"`
Function string `json:"function"`
ErrorInfo string `json:"error_info"`
gorm.Model
}

View File

@ -0,0 +1,17 @@
package model
import "gorm.io/gorm"
// SysIcons 系统图标库
type SysIcons struct {
Icon string `json:"icon"`
gorm.Model
}
type SysSettings struct {
Name string `json:"name"`
CnName string `json:"cn_name"`
Value string `json:"value"`
DType string `json:"d_type"`
gorm.Model
}

55
api_file/model/sysinfo.go Normal file
View File

@ -0,0 +1,55 @@
package model
import "gorm.io/gorm"
type SysInfo struct {
Date string `json:"date" gorm:"index:select_info"`
Datetime string `json:"datetime" gorm:"index:datetime_index"`
Username string `json:"username" gorm:"index:select_info"`
Hostname string `json:"hostname"`
Ip string `json:"ip" gorm:"index:select_info"`
SysVersion string `json:"sysVersion"`
PhysicalCount int `json:"physicalCount"`
LogicalCount int `json:"logicalCount"`
CpuPer float64 `json:"cpuPer"`
MemTotal string `json:"memTotal"`
MemUsed string `json:"memUsed"`
MemPer float64 `json:"memPer"`
DiskPoint string `json:"diskPoint"`
DiskTotal string `json:"diskTotal"`
DiskUsed string `json:"diskUsed"`
DiskPer string `json:"diskPer"`
NetSent int64 `json:"netSent"`
NetRec int64 `json:"netRec"`
SentSpeed string `json:"sentSpeed"`
RecSpeed string `json:"recSpeed"`
gorm.Model
}
type SysInfoOld struct {
Datetime string `json:"datetime" gorm:"index:datetime_index"`
Username string `json:"username"`
Hostname string `json:"hostname"`
Ip string `json:"ip"`
SysVersion string `json:"sysVersion"`
PhysicalCount int `json:"physicalCount"`
LogicalCount int `json:"logicalCount"`
CpuPer float64 `json:"cpuPer"`
MemTotal string `json:"memTotal"`
MemUsed string `json:"memUsed"`
MemPer float64 `json:"memPer"`
DiskPoint string `json:"diskPoint"`
DiskTotal string `json:"diskTotal"`
DiskUsed string `json:"diskUsed"`
DiskPer string `json:"diskPer"`
NetSent int64 `json:"netSent"`
NetRec int64 `json:"netRec"`
SentSpeed string `json:"sentSpeed"`
RecSpeed string `json:"recSpeed"`
}
type SysInfoUpdateLog struct {
Datetime string `json:"datetime"`
Update bool `json:"update"`
gorm.Model
}

38
api_file/model/user.go Normal file
View File

@ -0,0 +1,38 @@
package model
import "gorm.io/gorm"
// User 用户登录信息表
type User struct {
Username string
Password string
Date string
ConfirmCode string
gorm.Model
}
// Userinfo 用户信息表
type Userinfo struct {
Username string `json:"username"`
Avatar string `json:"avatar"`
Nickname string `json:"nickname"`
Mobile string `json:"mobile"`
Email string `json:"email"`
Location string `json:"location"`
Type string `json:"type"`
gorm.Model
}
// UserAction 用户行为表
type UserAction struct {
Username string
Action string
gorm.Model
}
type UserAutoLogin struct {
Username string
DeviceId string
Location string
gorm.Model
}

10
api_file/model/utils.go Normal file
View File

@ -0,0 +1,10 @@
package model
import "gorm.io/gorm"
// IpsLocation ip转地址表
type IpsLocation struct {
Ip string
Location string
gorm.Model
}

11
api_file/model/weather.go Normal file
View File

@ -0,0 +1,11 @@
package model
import "gorm.io/gorm"
// Weather 每日天气表
type Weather struct {
Date string
Location string
Weather string
gorm.Model
}

View File

@ -0,0 +1,319 @@
package api
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"mime/multipart"
"os"
"path"
"path/filepath"
"strings"
"time"
)
func getRootFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
userPath := fmt.Sprintf("./upload/%s", username.Username)
if !utils.FileIsExist(userPath) {
err := os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
var files filesRes
fileList, err := os.ReadDir(userPath)
if utils.ErrHandle(ctx, err) {
return
}
for _, file := range fileList {
if file.IsDir() {
files.Dirs = append(files.Dirs, file.Name())
} else {
var item fileItem
item.Name = file.Name()
f, err := os.Stat(path.Join(userPath, file.Name()))
if utils.ErrHandle(ctx, err) {
return
}
item.Size = f.Size()
item.Type = utils.GetFileType(f.Name())
files.Files = append(files.Files, item)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", files))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取指定目录下文件
func getFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New(userPath + ":目录不存在"))
return
}
var files filesRes
fileList, err := os.ReadDir(userPath)
if utils.ErrHandle(ctx, err) {
return
}
for _, file := range fileList {
if file.IsDir() {
files.Dirs = append(files.Dirs, file.Name())
} else {
var item fileItem
item.Name = file.Name()
f, err := os.Stat(path.Join(userPath, file.Name()))
if utils.ErrHandle(ctx, err) {
return
}
item.Size = f.Size()
item.Type = utils.GetFileType(f.Name())
files.Files = append(files.Files, item)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", files))
if utils.ErrHandle(ctx, err) {
return
}
}
// 删除文件或目录
func deleteFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("目录不存在"))
return
}
if info, _ := os.Stat(userPath); info.IsDir() {
err := os.RemoveAll(userPath)
if utils.ErrHandle(ctx, err) {
return
}
} else {
err := os.Remove(userPath)
if utils.ErrHandle(ctx, err) {
return
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 上传头像
func uploadAvatar(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
file, info, err := ctx.FormFile("file")
if utils.ErrHandle(ctx, err) {
return
}
defer func(file multipart.File) {
err = file.Close()
if utils.ErrHandle(ctx, err) {
return
}
}(file)
userPath := fmt.Sprintf("./static/%s", username.Username)
if !utils.FileIsExist(userPath) {
err = os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
fileType := strings.Split(info.Filename, ".")[len(strings.Split(info.Filename, "."))-1]
avatarName := fmt.Sprintf("./static/%s/avatar-%s.%s", username.Username, time.Now().Format("2006-01-02"), fileType)
_, err = ctx.SaveFormFile(info, avatarName)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", avatarName[1:]))
if utils.ErrHandle(ctx, err) {
return
}
}
func uploadDir(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("目录已存在"))
return
}
err := os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 上传文件
func uploadFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
file, info, err := ctx.FormFile("file")
if utils.ErrHandle(ctx, err) {
return
}
defer func(file multipart.File) {
err = file.Close()
if utils.ErrHandle(ctx, err) {
return
}
}(file)
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
err = os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
_, err = ctx.SaveFormFile(info, fmt.Sprintf("./upload/%s/%s/%s", username.Username, filePath, info.Filename))
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 文件下载转到nginx-upload目录
func downloadFile(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", userToken.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("文件不存在"))
return
}
if info, _ := os.Stat(userPath); info.IsDir() {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只可下载文件"))
return
}
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload/%s/%s", userToken.Username, filePath))
ctx.Recorder().Header().Add("X-Accel-Charset", "utf-8")
ctx.Recorder().Header().Add("Content-Disposition", "attachment")
ctx.Recorder().Header().Add("Content-Type", "application/octet-stream; charset=utf-8")
return
}
func getDownloadFileType(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
var res videoM3u8
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
username := userToken.Username
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username, filePath)
currentPath, _ := filepath.Split(filePath)
filename := strings.TrimSuffix(path.Base(userPath), path.Ext(userPath))
res.Video = utils.GetFileType(userPath) == "video"
res.M3u8 = utils.FileIsExist(fmt.Sprintf("./upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename))
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if err != nil {
return
}
return
}
func downloadVideo(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
username := userToken.Username
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username, filePath)
currentPath, _ := filepath.Split(filePath)
filename := strings.TrimSuffix(path.Base(userPath), path.Ext(userPath))
//fmt.Println(filePath, currentPath, filename)
if path.Ext(userPath) != ".ts" && !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("文件不存在"))
return
}
if info, err := os.Stat(userPath); err == nil && info.IsDir() {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只可下载文件"))
return
}
if utils.GetFileType(userPath) == "video" && utils.FileIsExist(fmt.Sprintf("./upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename)) {
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename))
} else if utils.GetFileType(userPath) == "video" {
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload/%s/%s", username, filePath))
} else {
tsPath := fmt.Sprintf("./upload-video/%s/%s%s/%s.ts", username, currentPath, filename[:len(filename)-6], filename)
ctx.Recorder().Header().Add("X-Accel-Redirect", tsPath[1:])
}
ctx.Recorder().Header().Add("X-Accel-Charset", "utf-8")
ctx.Recorder().Header().Add("Content-Disposition", "attachment")
ctx.Recorder().Header().Add("Content-Type", "application/octet-stream; charset=utf-8")
return
}

View File

@ -0,0 +1,17 @@
package api
import (
"github.com/kataras/iris/v12"
)
func File(party iris.Party) {
party.Get("/upload", getRootFile)
party.Get("/upload/{path:path}", getFile)
party.Post("/upload/{path:path}", uploadDir)
party.Post("/upload-file/{path:path}", uploadFile)
party.Delete("/upload/{path:path}", deleteFile)
party.Post("/static/avatar", uploadAvatar)
party.Get("/download/{path:path}", downloadFile)
party.Get("/download-video-check/{path:path}", getDownloadFileType)
party.Get("/download-video/{path:path}", downloadVideo)
}

View File

@ -0,0 +1,13 @@
package api
import (
"github.com/kataras/iris/v12"
"main/utils"
)
func Apis(ctx iris.Context) {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "allFileApis"))
if err != nil {
return
}
}

View File

@ -0,0 +1,172 @@
package api
import "time"
// user-----------------------------------------------------------------------------------------------
type result struct {
Date string
Password string
ConfirmCode string
UpdatedAt time.Time
Key string
AesKey string
}
// weather---------------------------------------------------------------------------------------------
type resWeather struct {
Status int `json:"status"`
Message string `json:"message"`
Data resData `json:"data"`
}
type resData struct {
Forecast24h resDate `json:"forecast_24h"`
}
type resDate struct {
D0 res24h `json:"1"`
D1 res24h `json:"2"`
}
type res24h struct {
Time string `json:"time"`
MaxDegree string `json:"max_degree"`
MinDegree string `json:"min_degree"`
DayWeather string `json:"day_weather"`
DayWindDirection string `json:"day_wind_direction"`
DayWindPower string `json:"day_wind_power"`
NightWeather string `json:"night_weather"`
NightWindPower string `json:"night_wind_power"`
NightWindDirection string `json:"night_wind_direction"`
}
type resLocation struct {
Data map[string]string `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
// backgammon-----------------------------------------------------------------------------------------------
type typeRoomStatus struct {
RoomId int `json:"room_id"`
Player string `json:"player"`
}
// file-----------------------------------------------------------------------------------------------------
type filesRes struct {
Dirs []string `json:"dirs"`
Files []fileItem `json:"files"`
}
type fileItem struct {
Name string `json:"name"`
Type string `json:"type"`
Size int64 `json:"size"`
}
type videoM3u8 struct {
Video bool `json:"video"`
M3u8 bool `json:"m3u8"`
}
// notes------------------------------------------------------------------------------------------------------
type noteParam struct {
ID uint `json:"id"`
Content string `json:"content"`
}
// sysInfo------------------------------------------------------------------------------------------------------
type resSysInfo struct {
Datetime string `json:"datetime"`
CpuPer float64 `json:"cpu_per"`
Mem resMem `json:"mem"`
Disk []resDisk `json:"disk"`
Net resNet `json:"net"`
}
type resMem struct {
MemTotal string `json:"mem_total"`
MemUsed string `json:"mem_used"`
MemPer float64 `json:"mem_per"`
}
type resDisk struct {
Point string `json:"point"`
Total string `json:"total"`
Used string `json:"used"`
Per float64 `json:"per"`
}
type resNet struct {
Sent string `json:"sent"`
Rec string `json:"rec"`
}
type resSystem struct {
Hostname string `json:"hostname"`
Ip string `json:"ip"`
}
type sysInfoIDs struct {
IDs []int `json:"ids"`
}
// yeb----------------------------------------------------------------------------------------------------------
type paramsBalance struct {
Card string `json:"card"`
Type bool `json:"type"`
Balance float64 `json:"balance"`
}
type paramSZBalance struct {
Card string `json:"card"`
Type bool `json:"type"` // 1-支出0-收入
Amount float64 `json:"amount"`
}
// 月余额
type dateLog struct {
Date string `json:"date"`
Duration string `json:"duration"`
Changes float64 `json:"changes"`
Balance float64 `json:"balance"`
Detail []cardLog `json:"detail"`
}
// 详情
type cardLog struct {
Card string `json:"card"`
Balance float64 `json:"balance"`
Changes float64 `json:"changes"`
}
// menus-----------------------------------------------------------------------------
type resMenu struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
Detail []subMenu `json:"detail"`
}
type subMenu struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
}
type sysIconsParam struct {
Icons string `json:"icons"`
}
// sudoku-----------------------------------------------------------------------------
type resSudokuListType struct {
New []sudokuListType `json:"new"`
Starting []sudokuListType `json:"starting"`
Complete []sudokuListType `json:"complete"`
}
type sudokuListType struct {
Sudoku string `json:"sudoku"`
SudokuId uint `json:"sudokuId"`
Username string `json:"username"`
Status string `json:"status"`
Complete bool `json:"complete"`
Id uint `json:"id"`
}
type addSudokuParam struct {
Sudoku string `json:"sudoku"`
Result string `json:"result"`
}

11
api_file/service/init.go Normal file
View File

@ -0,0 +1,11 @@
package service
import (
"github.com/kataras/iris/v12"
"main/service/api"
)
func Apis(p iris.Party) {
p.Get("/", api.Apis)
p.PartyFunc("/file", api.File)
}

View File

@ -0,0 +1,17 @@
package utils
import (
"github.com/sirupsen/logrus"
"main/database"
"main/model"
)
var SysSettings []model.SysSettings
func UpdateSysSettings() {
db := database.GetInstance().GetMysqlDb()
if err := db.Order("name").Find(&SysSettings).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
logrus.Infoln("更新系统配置列表")
}

24
api_file/utils/type.d.go Normal file
View File

@ -0,0 +1,24 @@
package utils
// ResponseBean result结构
type ResponseBean struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
type ResApiUtils struct {
Flag bool `json:"flag"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
}
// ResSudoku sudoku --------------------------------------------------------------------
type ResSudoku struct {
Flag bool `json:"flag"`
Data resSudokuData
}
type resSudokuData struct {
Check bool `json:"check"`
Result string `json:"result"`
}

73
api_file/utils/user.go Normal file
View File

@ -0,0 +1,73 @@
package utils
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"strings"
)
var UserList []model.Userinfo
// GetLoginUser 根据token获取用户,返回用户信息
func GetLoginUser(ctx iris.Context) model.Userinfo {
auth := ctx.GetHeader("Authorization")
fmt.Println(auth)
if auth == "" || !strings.Contains(auth, "Bearer") {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.SetErr(errors.New("未登录"))
logrus.Warningln("请求未携带token信息")
return model.Userinfo{}
}
var tokens []model.JwtKeys
db := database.GetInstance().GetMysqlDb()
fmt.Println(strings.Split(auth, " ")[1])
if err := db.Where("token = ?", strings.Split(auth, " ")[1]).Find(&tokens).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(tokens) == 0 {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.SetErr(errors.New("未登录"))
logrus.Warningln(auth, "token信息无效")
return model.Userinfo{}
} else {
return GetUserInfo(tokens[0].Username)
}
//foobar := auth.Claims.(jwt.MapClaims)
//for key, value := range foobar {
// if key == "username" {
// return GetUserInfo(value.(string))
// }
//}
//ctx.StatusCode(iris.StatusInternalServerError)
//ctx.SetErr(errors.New("系统错误,请联系管理员"))
//logrus.Errorln("token存在但获取用户信息失败")
//return model.Userinfo{}
}
// GetUserInfo 根据用户名获取用户信息,先更新本地数据
func GetUserInfo(username string) model.Userinfo {
if len(UserList) == 0 {
logrus.Warnln("暂存用户列表为空,刷新数据")
UpdateUserInfo()
}
for _, u := range UserList {
if u.Username == username {
return u
}
}
logrus.Warnln("未找到对应的用户信息")
return model.Userinfo{}
}
// UpdateUserInfo 更新当前用户信息
func UpdateUserInfo() {
db := database.GetInstance().GetMysqlDb()
if err := db.Find(&UserList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
logrus.Infoln("刷新暂存用户列表")
}

235
api_file/utils/utils.go Normal file
View File

@ -0,0 +1,235 @@
package utils
import (
"bufio"
"encoding/json"
"fmt"
"github.com/kataras/iris/v12"
"github.com/shopspring/decimal"
"github.com/sirupsen/logrus"
"io"
"main/database"
"main/model"
"math/rand"
"net/http"
"net/url"
"os"
"path"
"reflect"
"regexp"
"runtime"
"strings"
"time"
"unsafe"
)
// FormatRes 格式化result
func FormatRes(code int, msg string, data interface{}) ResponseBean {
return ResponseBean{
Code: code,
Msg: msg,
Data: data,
}
}
// GetEnvDefault 获取带默认值环境变量
func GetEnvDefault(name string, defaultVal string) string {
val, ok := os.LookupEnv(name)
if ok {
return val
} else {
return defaultVal
}
}
// FileRead 读取文件,返回行列表
func FileRead(file string, condition bool) ([]string, error) {
f, err := os.Open(file)
var res []string
if err != nil {
return []string{}, err
}
defer func(f *os.File) {
err = f.Close()
if err != nil {
return
}
}(f)
reader := bufio.NewReader(f)
for {
line, _, err := reader.ReadLine()
if err != nil {
break
}
if condition && len(line) > 1 {
res = append(res, string(line))
}
}
return res, nil
}
func SendEmail(receiver []string, subject string, content string, test bool) error {
var emailUrl string
if !test {
emailUrl = fmt.Sprintf("https://git-ylsa0.cn/api_django/send_email/?subject=%s&receivers=%s&content=%s", url.QueryEscape(subject), strings.Join(receiver, ";"), url.QueryEscape(content))
} else {
emailUrl = fmt.Sprintf("http://localhost:8000/api/send_email/?subject=%s&receivers=%s&content=%s", url.QueryEscape(subject), strings.Join(receiver, ";"), url.QueryEscape(content))
}
resp, err := http.Get(emailUrl)
fmt.Println(emailUrl)
if err != nil {
logrus.Errorln("连接send_email接口失败", err)
return err
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
}
}(resp.Body)
body, _ := io.ReadAll(resp.Body)
var r ResApiUtils
//解析json结构
err = json.Unmarshal(body, &r)
if err != nil {
logrus.Errorln("send_email接口结果json解析失败", err)
return err
}
return nil
}
// DataIsNil 判断数据是否为空
func DataIsNil(arg interface{}) bool {
if reflect.ValueOf(arg).Kind().String() == "ptr" || reflect.ValueOf(arg).Kind().String() == "slice" {
if reflect.ValueOf(arg).IsValid() {
return true
}
} else {
if reflect.ValueOf(arg).IsZero() {
return true
}
}
return false
}
// ErrHandle 错误处理
func ErrHandle(ctx iris.Context, err error) bool {
if err != nil {
pc, _, _, _ := runtime.Caller(1)
f := runtime.FuncForPC(pc).Name()
db := database.GetInstance().GetMysqlDb()
if err1 := db.Create(&model.SysError{
Username: GetLoginUser(ctx).Username,
Time: time.Now(),
Function: f,
ErrorInfo: err.Error(),
}); err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(err)
return true
}
return false
}
// NewKey 取n位随机数
func NewKey(n int) string {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()-+*/~"
var src = rand.NewSource(time.Now().UnixNano())
const (
// 6 bits to represent a letter index
letterIdBits = 6
// All 1-bits as many as letterIdBits
letterIdMask = 1<<letterIdBits - 1
letterIdMax = 63 / letterIdBits
)
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax letters!
for i, cache, remain := n-1, src.Int63(), letterIdMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdMax
}
if idx := int(cache & letterIdMask); idx < len(letters) {
b[i] = letters[idx]
i--
}
cache >>= letterIdBits
remain--
}
return *(*string)(unsafe.Pointer(&b))
}
// CheckListItem 判断item是否在list内
func CheckListItem[T comparable](data []T, item T) bool {
for _, value := range data {
if value == item {
return true
}
}
return false
}
// FileIsExist 判断路径是否存在
func FileIsExist(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
// Round float取小数
func Round(num float64, n int32) float64 {
res, _ := decimal.NewFromFloat(num).Round(n).Float64()
return res
}
// GetFileType 获取文件类型
func GetFileType(f string) string {
fileSuffix := path.Ext(f)
fileSuffix = strings.ToLower(fileSuffix)
patternFileSuffix := fmt.Sprintf("^%s,|,%s,|,%s$|%s", fileSuffix, fileSuffix, fileSuffix, fileSuffix)
regFileSuffix := regexp.MustCompile(patternFileSuffix)
for _, v := range SysSettings {
if strings.HasPrefix(v.Name, "fileType:") && regFileSuffix.MatchString(v.Value) {
return strings.Split(v.Name, "fileType:")[1]
}
}
//switch fileSuffix {
//case ".png", ".jpg", ".jpeg", ".bmp", ".gif":
// return "image"
//case ".mp4", ".m2v", ".mkv", ".rmvb", ".avi", ".flv", ".mov", ".m4v", ".wmv", ".f4v":
// return "video"
//case ".mp3", ".wav", ".flac":
// return "audio"
//case ".zip", ".rar", ".7z":
// return "zip"
//}
return "doc"
}
// IntAbs 数字取绝对值
func IntAbs(i int) int {
if i < 0 {
return -i
} else {
return i
}
}
// Reverse 字符串反转
func Reverse(s string) string {
a := []rune(s)
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
return string(a)
}
func GetRequestIp(ctx iris.Context) string {
realIp := ctx.Request().Header.Get("X-Real-IP")
if realIp != "" {
return realIp
}
ip := ctx.RemoteAddr()
return ip
}

15
api_iris/Dockerfile Normal file
View File

@ -0,0 +1,15 @@
FROM golang:1.22.4
RUN mkdir -p /web \
&& mkdir /web/logs
ENV GOPATH=/web
ENV GOPROXY=https://goproxy.cn,direct
WORKDIR $GOPATH/api_iris
COPY . $GOPATH/api_iris
RUN go build .
ENTRYPOINT ["./main"]

View File

@ -0,0 +1,15 @@
database:
dsn: web:Song1875.@tcp(43.154.168.226:3306)/web_vue?charset=utf8mb4&parseTime=True&loc=Local
prd: false
logs:
log: logs
nginx: logs/nginx
sys:
jwt: False
User: admin
email:
username: 15822909392@163.com
password: RXWDMRGRNTZBNAML

31
api_iris/config/config.go Normal file
View File

@ -0,0 +1,31 @@
package config
import (
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"os"
)
// Config 公共参数
var Config settings
// InitConfig 配置初始化
func InitConfig(version string) error {
var file []byte
var err error
if version == "dev" {
file, err = os.ReadFile("./config/config.dev.yaml")
} else {
file, err = os.ReadFile("./config/config.prd.yaml")
}
if err != nil {
logrus.Errorln("Error reading config file:", err)
return err
}
err = yaml.Unmarshal(file, &Config)
if err != nil {
logrus.Errorln("Error parsing config file:", err)
return err
}
return nil
}

View File

@ -0,0 +1,15 @@
database:
dsn: web_prd:SongPrd1875.@tcp(43.154.168.226:3306)/web_prd?charset=utf8mb4&parseTime=True&loc=Local
prd: true
logs:
log: logs
nginx: logs/nginx
sys:
jwt: True
User:
email:
username: 15822909392@163.com
password: RXWDMRGRNTZBNAML

22
api_iris/config/type.d.go Normal file
View File

@ -0,0 +1,22 @@
package config
type settings struct {
Logs *logs `yaml:"logs"`
Database *database `yaml:"database"`
Email *email `yaml:"email"`
}
type logs struct {
Nginx string `yaml:"nginx"`
Log string `yaml:"log"`
}
type database struct {
Dsn string `yaml:"dsn"`
Prd bool `yaml:"prd"`
}
type email struct {
Username string `yaml:"username"`
Password string `yaml:"password"`
}

40
api_iris/crontab/init.go Normal file
View File

@ -0,0 +1,40 @@
package crontab
import (
"github.com/robfig/cron/v3"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
)
var MyCron *cron.Cron
func InitAllCron() {
MyCron = cron.New(cron.WithSeconds())
MyCron.Start()
db := database.GetInstance().GetMysqlDb()
var runningCron []model.RunningCrontab
if err := db.Where("deleted_at is null").Delete(&runningCron).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
}
func UpdateCronDb(id int, name string, status bool) {
db := database.GetInstance().GetMysqlDb()
var runningCron model.RunningCrontab
if status {
if err := db.Create(&model.RunningCrontab{
Name: name,
CronId: id,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
} else {
if err := db.Delete(&runningCron, "cron_id = ?", id).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
}
}

View File

@ -0,0 +1,70 @@
package crontab
import (
"fmt"
"github.com/sirupsen/logrus"
"main/config"
"main/database"
"main/model"
"main/service/admin"
"main/utils"
"os"
"path"
"strings"
"time"
)
// CornSaveNginxLog 定时任务处理nginx日志
func CornSaveNginxLog() {
cPath, _ := os.Getwd()
logPath := path.Join(cPath, config.Config.Logs.Nginx)
fileList, _ := os.ReadDir(logPath)
db := database.GetInstance().GetMysqlDb()
var logDealList []model.LogFileDealLog
var resLogList []model.Logs
if err := db.Find(&logDealList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
for _, file := range fileList {
if strings.Contains(file.Name(), "access-") {
date := strings.Split(strings.Split(file.Name(), "access-")[1], ".")[0]
if getDateDealBool(date, logDealList) || date == time.Now().Format("2006-01-02") {
continue
}
logrus.Infoln(date, "nginx日志开始处理")
if err := db.Where("time like ?", fmt.Sprintf("%s%%", date)).Delete(&resLogList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
logList, _ := utils.FileRead(path.Join(logPath, file.Name()), true)
for _, v := range logList {
c := make(chan model.Logs)
go admin.FormatLog(v, date, c)
resLogItem := <-c
if err := db.Create(&resLogItem).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
}
if err := db.Create(&model.LogFileDealLog{
Date: date,
Success: true,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
logrus.Infoln(date, "nginx日志处理完成")
}
}
}
// 获取当前日期是否已处理
func getDateDealBool(date string, dealLog []model.LogFileDealLog) bool {
for _, v := range dealLog {
if v.Date == date && v.Success {
return true
}
}
return false
}

View File

@ -0,0 +1,5 @@
package crontab
type sysLogDateType struct {
Datetime string `json:"datetime"`
}

View File

@ -0,0 +1,85 @@
package database
import (
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"main/config"
"main/model"
"sync"
)
var instance *MysqlConnectionPool
var once sync.Once
var db *gorm.DB
var err error
// GetInstance 获取数据库连接池
func GetInstance() *MysqlConnectionPool {
once.Do(func() {
instance = &MysqlConnectionPool{}
})
return instance
}
// InitDataPool 数据库初始化连接
func (m *MysqlConnectionPool) InitDataPool() (isSuccess bool) {
dbConfig := config.Config.Database
if dbConfig.Prd {
db, err = gorm.Open(mysql.Open(dbConfig.Dsn), &gorm.Config{})
} else {
db, err = gorm.Open(mysql.Open(dbConfig.Dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
}
if err != nil {
logrus.Errorln("数据库配置失败:", err)
return false
}
return true
}
// GetMysqlDb 获取数据库连接
func (m *MysqlConnectionPool) GetMysqlDb() (dbCon *gorm.DB) {
return db
}
// UpdateDbStruct 数据库数据结构更新
func UpdateDbStruct() error {
err = db.AutoMigrate(
&model.Logs{},
&model.Weather{},
&model.DayKeys{},
&model.JwtKeys{},
&model.IpsLocation{},
&model.User{},
&model.Userinfo{},
&model.UserAction{},
&model.UserAutoLogin{},
&model.LogFileDealLog{},
&model.RunningCrontab{},
&model.Balances{},
&model.BalanceLogs{},
&model.UserNotes{},
&model.BackgammonRoom{},
&model.SysInfo{},
&model.SysInfoUpdateLog{},
&model.ChessStatus{},
&model.ChessStatusLog{},
&model.Menus{},
&model.SysIcons{},
&model.SysSettings{},
&model.SysError{},
&model.Sudoku{},
&model.SudokuStatus{},
&model.SysLogs{},
)
if err != nil {
logrus.Errorln("数据库自动迁移失败:", err)
}
return err
}
type MysqlConnectionPool struct {
}

77
api_iris/go.mod Normal file
View File

@ -0,0 +1,77 @@
module main
go 1.22.4
require (
github.com/golang-jwt/jwt/v4 v4.5.1
github.com/gorilla/websocket v1.5.3
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72
github.com/jakehl/goid v1.1.0
github.com/kataras/iris/v12 v12.2.11
github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede
github.com/robfig/cron/v3 v3.0.1
github.com/shopspring/decimal v1.4.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.25.10
)
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
github.com/Joker/jade v1.1.3 // indirect
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/antonfisher/nested-logrus-formatter v1.3.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.3.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/iris-contrib/schema v0.0.6 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kataras/blocks v0.0.8 // indirect
github.com/kataras/golog v0.1.11 // indirect
github.com/kataras/pio v0.0.13 // indirect
github.com/kataras/sitemap v0.0.6 // indirect
github.com/kataras/tunnel v0.0.4 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/mailgun/raymond/v2 v2.0.48 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mediocregopher/radix/v3 v3.8.1 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nats-io/nats.go v1.34.1 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tdewolff/minify/v2 v2.20.19 // indirect
github.com/tdewolff/parse/v2 v2.7.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/yosssi/ace v0.0.5 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

234
api_iris/go.sum Normal file
View File

@ -0,0 +1,234 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q=
github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU=
github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72 h1:wbkA/QXv1RZmuY2iLvsgmHeiGq4DNvv2Rhj5PQ2oHTI=
github.com/iris-contrib/middleware/jwt v0.0.0-20240502084239-34f27409ce72/go.mod h1:hIyBTK1zUxUaC4Hu8Ba9Z70r2S5ET4+ZKNescqjXld0=
github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
github.com/jakehl/goid v1.1.0 h1:c08GO8z16wWJtfQhyiD8BQRFkpf1oDxaPmA+uYAG+50=
github.com/jakehl/goid v1.1.0/go.mod h1:V6bQh+tr2Oay5WHL0jmTTJWrABYIO+cs4/P6e1prV1o=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk=
github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w=
github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g=
github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE=
github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M=
github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4=
github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo=
github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM=
github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ=
github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8=
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=

78
api_iris/jwtSet/jwt.go Normal file
View File

@ -0,0 +1,78 @@
package jwtSet
import (
"github.com/iris-contrib/middleware/jwt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"time"
)
var Jwt *jwt.Middleware
var keys model.JwtKeys
func GetJwtKeys() model.JwtKeys {
db := database.GetInstance().GetMysqlDb()
if utils.DataIsNil(keys) || keys.Date != time.Now().Format("2006-01-02") {
keys = model.JwtKeys{}
if err := db.Where("date = ? and token = ''", time.Now().Format("2006-01-02")).First(&keys).Error; err != nil {
logrus.Errorln("sql执行失败", err)
//return model.JwtKeys{}
}
}
if keys.Key == "" {
keys.Date = time.Now().Format("2006-01-02")
keys.Key = utils.NewKey(32)
if err := db.Create(&keys).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return model.JwtKeys{}
}
}
if !keys.Updated && !utils.DataIsNil(Jwt) {
UpdateJwt()
}
return keys
}
func Init() {
if utils.DataIsNil(keys) {
GetJwtKeys()
}
Jwt = jwt.New(jwt.Config{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return []byte(keys.Key), nil
},
ErrorHandler: func(context iris.Context, err error) {
if err == nil {
return
}
context.StopExecution()
context.StatusCode(iris.StatusUnauthorized)
context.SetErr(err)
},
Extractor: jwt.FromAuthHeader,
SigningMethod: jwt.SigningMethodHS256,
})
db := database.GetInstance().GetMysqlDb()
keys.Updated = true
if err := db.Updates(&keys).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
}
func UpdateJwt() {
if utils.DataIsNil(keys) {
GetJwtKeys()
}
Jwt.Config.ValidationKeyGetter = func(token *jwt.Token) (interface{}, error) {
return []byte(keys.Key), nil
}
db := database.GetInstance().GetMysqlDb()
keys.Updated = true
if err := db.Updates(&keys).Error; err != nil {
logrus.Errorln("sql执行失败", err)
return
}
}

119
api_iris/main.go Normal file
View File

@ -0,0 +1,119 @@
package main
import (
"fmt"
nested "github.com/antonfisher/nested-logrus-formatter"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/accesslog"
"github.com/kataras/iris/v12/websocket"
"github.com/sirupsen/logrus"
"main/config"
"main/crontab"
"main/database"
"main/jwtSet"
"main/service"
"main/service/admin"
"main/service/ws"
"main/utils"
"os"
"path"
"time"
)
func main() {
logrus.SetFormatter(&nested.Formatter{HideKeys: true, TimestampFormat: time.RFC3339})
//配置文件初始化
err := config.InitConfig(utils.GetEnvDefault("version", "dev"))
if err != nil {
logrus.Errorln("配置文件初始化失败:", err)
return
}
logrus.Infoln("配置文件初始化完成")
//日志初始化
ac := makeAccessLog()
//应用初始化
app := iris.New()
//应用ac-log
app.UseRouter(ac.Handler)
//错误处理
app.OnAnyErrorCode(handler)
//数据库连接初始化
if !database.GetInstance().InitDataPool() {
return
}
logrus.Infoln("数据库连接初始化完成")
if e := database.UpdateDbStruct(); e != nil {
logrus.Errorln("数据库初始化失败:", e)
return
}
//初始化用户信息,系统配置信息,菜单列表,本地IP地址信息
utils.UpdateUserInfo()
utils.UpdateSysSettings()
utils.UpdateMenuList()
admin.UpdateLocalIpList()
logrus.Infoln("数据库结构初始化完成")
jwtSet.Init()
logrus.Infoln("jwt认证初始化完成")
crontab.InitAllCron()
id, err := crontab.MyCron.AddFunc("0 0 0 * * *", func() {
utils.UpdateUserInfo()
jwtSet.GetJwtKeys()
})
if err != nil {
logrus.Errorln("cron任务添加失败", err)
return
}
crontab.UpdateCronDb(int(id), "每天初始化jwt密钥", true)
if utils.GetEnvDefault("version", "dev") == "prd" {
//id, err = crontab.MyCron.AddFunc("0 10 * * * *", func() {
// crontab.UpdateSysInfo("")
//})
//crontab.UpdateCronDb(int(id), "每小时10分同步历史系统信息记录", true)
id, err = crontab.MyCron.AddFunc("0 30 0 * * *", func() {
crontab.CornSaveNginxLog()
})
crontab.UpdateCronDb(int(id), "每天00:30同步nginx日志", true)
}
logrus.Infoln("定时任务初始化完成")
//接口组
app.PartyFunc("/api", service.Apis)
app.PartyFunc("/admin", service.Admin)
app.PartyFunc("/test", service.Test)
logrus.Infoln("接口组配置完成")
//启动websocket
wss := ws.SetupWebsocket()
app.Get("/ws", websocket.Handler(wss))
logrus.Infoln("websocket配置完成")
//应用启动
logrus.Infoln("应用启动")
err = app.Run(iris.Addr(":8080"))
if err != nil {
return
}
}
// 生成acLog实例
func makeAccessLog() *accesslog.AccessLog {
cPath, _ := os.Getwd()
ac := accesslog.File(path.Join(cPath, config.Config.Logs.Log, fmt.Sprintf("access-%s.log", time.Now().Format("2006-01-02"))))
ac.AddOutput(os.Stdout)
ac.IP = true
ac.Delim = ' '
ac.ResponseBody = false
return ac
}
// 接口错误处理
func handler(ctx iris.Context) {
if ctx.GetErr() != nil {
err := ctx.JSON(utils.FormatRes(ctx.GetStatusCode(), ctx.GetErr().Error(), nil))
if err != nil {
return
}
} else {
err := ctx.JSON(utils.FormatRes(ctx.GetStatusCode(), "", nil))
if err != nil {
return
}
}
}

View File

@ -0,0 +1,12 @@
package model
import "gorm.io/gorm"
type BackgammonRoom struct {
RoomId int `json:"room_id"`
Player string `json:"player"`
Winner string `json:"winner"`
Current string `json:"current"`
PawnStatus string `json:"pawn_status"`
gorm.Model
}

19
api_iris/model/balance.go Normal file
View File

@ -0,0 +1,19 @@
package model
import "gorm.io/gorm"
type Balances struct {
Username string `json:"username"`
Card string `json:"card"`
Type bool `gorm:"default:false" json:"type"` //1支出型0收入型
Balance float64 `json:"balance"`
gorm.Model
}
type BalanceLogs struct {
Username string
Card string
Date string
Balance float64
gorm.Model
}

28
api_iris/model/chess.go Normal file
View File

@ -0,0 +1,28 @@
package model
import (
"gorm.io/gorm"
"time"
)
type ChessStatus struct {
gorm.Model
Players string `json:"players"`
Current string `json:"current"`
IsEnd bool `json:"is_end"`
Status string `json:"status"`
Winner string `json:"winner"`
ChessId string `json:"chess_id"`
}
type ChessStatusLog struct {
gorm.Model
RoomId uint `json:"roomId"`
Current string `json:"current"`
Players string `json:"players"`
IsEnd bool `json:"is_end"`
Status string `json:"status"`
Winner string `json:"winner"`
ChessId string `json:"chess_id"`
Time time.Time `json:"time"`
}

View File

@ -0,0 +1,9 @@
package model
import "gorm.io/gorm"
type RunningCrontab struct {
Name string
CronId int
gorm.Model
}

20
api_iris/model/keys.go Normal file
View File

@ -0,0 +1,20 @@
package model
import "gorm.io/gorm"
// DayKeys 每天对应key表
type DayKeys struct {
Date string
Key string
AesKey string
User string
gorm.Model
}
type JwtKeys struct {
Username string
Date string
Key string
Token string
Updated bool `gorm:"default:false"`
gorm.Model
}

31
api_iris/model/logs.go Normal file
View File

@ -0,0 +1,31 @@
package model
import "gorm.io/gorm"
// Logs 日志表
type Logs struct {
Method string `json:"method,omitempty"`
Path string `json:"path,omitempty"`
Status string `json:"status,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
Time string `json:"time,omitempty"`
Location string `json:"location,omitempty"`
Ip string `json:"ip,omitempty"`
gorm.Model
}
type LogFileDealLog struct {
Date string
Success bool
gorm.Model
}
// SysLogs 系统容器日志表
type SysLogs struct {
Time string `json:"time,omitempty"`
ContainerName string `json:"container_name,omitempty"`
ContainerImage string `json:"container_image,omitempty"`
Message string `json:"message,omitempty"`
Offset int `json:"offset,omitempty"`
gorm.Model
}

14
api_iris/model/menus.go Normal file
View File

@ -0,0 +1,14 @@
package model
import "gorm.io/gorm"
type Menus struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
UserType string `json:"user_type"`
WhiteList string `json:"white_list"`
gorm.Model
}

9
api_iris/model/note.go Normal file
View File

@ -0,0 +1,9 @@
package model
import "gorm.io/gorm"
type UserNotes struct {
Username string `json:"username"`
Content string `json:"content"`
gorm.Model
}

18
api_iris/model/sudoku.go Normal file
View File

@ -0,0 +1,18 @@
package model
import "gorm.io/gorm"
type Sudoku struct {
Sudoku string `json:"sudoku"`
Username string `json:"username"`
Result string `json:"result"`
gorm.Model
}
type SudokuStatus struct {
SudokuId uint `json:"sudoku_id"`
Username string `json:"username"`
Status string `json:"status"`
Complete bool `json:"complete"`
gorm.Model
}

View File

@ -0,0 +1,14 @@
package model
import (
"gorm.io/gorm"
"time"
)
type SysError struct {
Username string `json:"username"`
Time time.Time `json:"time"`
Function string `json:"function"`
ErrorInfo string `json:"error_info"`
gorm.Model
}

View File

@ -0,0 +1,17 @@
package model
import "gorm.io/gorm"
// SysIcons 系统图标库
type SysIcons struct {
Icon string `json:"icon"`
gorm.Model
}
type SysSettings struct {
Name string `json:"name"`
CnName string `json:"cn_name"`
Value string `json:"value"`
DType string `json:"d_type"`
gorm.Model
}

55
api_iris/model/sysinfo.go Normal file
View File

@ -0,0 +1,55 @@
package model
import "gorm.io/gorm"
type SysInfo struct {
Date string `json:"date" gorm:"index:select_info"`
Datetime string `json:"datetime" gorm:"index:datetime_index"`
Username string `json:"username" gorm:"index:select_info"`
Hostname string `json:"hostname"`
Ip string `json:"ip" gorm:"index:select_info"`
SysVersion string `json:"sysVersion"`
PhysicalCount int `json:"physicalCount"`
LogicalCount int `json:"logicalCount"`
CpuPer float64 `json:"cpuPer"`
MemTotal string `json:"memTotal"`
MemUsed string `json:"memUsed"`
MemPer float64 `json:"memPer"`
DiskPoint string `json:"diskPoint"`
DiskTotal string `json:"diskTotal"`
DiskUsed string `json:"diskUsed"`
DiskPer string `json:"diskPer"`
NetSent int64 `json:"netSent"`
NetRec int64 `json:"netRec"`
SentSpeed string `json:"sentSpeed"`
RecSpeed string `json:"recSpeed"`
gorm.Model
}
type SysInfoOld struct {
Datetime string `json:"datetime" gorm:"index:datetime_index"`
Username string `json:"username"`
Hostname string `json:"hostname"`
Ip string `json:"ip"`
SysVersion string `json:"sysVersion"`
PhysicalCount int `json:"physicalCount"`
LogicalCount int `json:"logicalCount"`
CpuPer float64 `json:"cpuPer"`
MemTotal string `json:"memTotal"`
MemUsed string `json:"memUsed"`
MemPer float64 `json:"memPer"`
DiskPoint string `json:"diskPoint"`
DiskTotal string `json:"diskTotal"`
DiskUsed string `json:"diskUsed"`
DiskPer string `json:"diskPer"`
NetSent int64 `json:"netSent"`
NetRec int64 `json:"netRec"`
SentSpeed string `json:"sentSpeed"`
RecSpeed string `json:"recSpeed"`
}
type SysInfoUpdateLog struct {
Datetime string `json:"datetime"`
Update bool `json:"update"`
gorm.Model
}

38
api_iris/model/user.go Normal file
View File

@ -0,0 +1,38 @@
package model
import "gorm.io/gorm"
// User 用户登录信息表
type User struct {
Username string
Password string
Date string
ConfirmCode string
gorm.Model
}
// Userinfo 用户信息表
type Userinfo struct {
Username string `json:"username"`
Avatar string `json:"avatar"`
Nickname string `json:"nickname"`
Mobile string `json:"mobile"`
Email string `json:"email"`
Location string `json:"location"`
Type string `json:"type"`
gorm.Model
}
// UserAction 用户行为表
type UserAction struct {
Username string
Action string
gorm.Model
}
type UserAutoLogin struct {
Username string
DeviceId string
Location string
gorm.Model
}

10
api_iris/model/utils.go Normal file
View File

@ -0,0 +1,10 @@
package model
import "gorm.io/gorm"
// IpsLocation ip转地址表
type IpsLocation struct {
Ip string
Location string
gorm.Model
}

11
api_iris/model/weather.go Normal file
View File

@ -0,0 +1,11 @@
package model
import "gorm.io/gorm"
// Weather 每日天气表
type Weather struct {
Date string
Location string
Weather string
gorm.Model
}

View File

@ -0,0 +1,25 @@
package admin
import (
"errors"
"github.com/kataras/iris/v12"
"main/utils"
)
func Admin(ctx iris.Context) {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "adminPage"))
if err != nil {
return
}
}
// CheckAdmin 检查admin权限
func checkAdmin(ctx iris.Context) {
user := utils.GetLoginUser(ctx)
if user.Type != "admin" {
ctx.StatusCode(iris.StatusForbidden)
ctx.SetErr(errors.New("权限不足"))
return
}
ctx.Next()
}

View File

@ -0,0 +1,199 @@
package admin
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
"main/config"
"main/database"
"main/model"
"main/utils"
"os"
"path"
"strconv"
"strings"
"time"
)
var ipLocationList []model.IpsLocation
func getLogStats(ctx iris.Context) {
var logStats []resLogStats
db := database.GetInstance().GetMysqlDb()
if err := db.Model(&model.Logs{}).Select("left(time, 10) name", "count(1) value").Order("left(time,10)").Group("left(time,10)").Scan(&logStats).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", logStats))
if utils.ErrHandle(ctx, err) {
return
}
}
func getLogDetail(ctx iris.Context) {
var logs []model.Logs
date := ctx.URLParam("date")
db := database.GetInstance().GetMysqlDb()
if err := db.Where("left(time,10) = ?", date).Find(&logs).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", logs))
if utils.ErrHandle(ctx, err) {
return
}
}
func getSysLogs(ctx iris.Context) {
var logs []model.SysLogs
var resLogs []model.SysLogs
startTime := ctx.URLParam("start_time")
endTime := ctx.URLParam("end_time")
containerName := ctx.URLParam("container_name")
message := ctx.URLParam("message")
db := database.GetInstance().GetMysqlDb()
//生成子查询
query := db.Model(&model.SysLogs{})
if startTime == "" {
startTime = time.Date(2000, 0, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02 15:04:05")
}
if endTime == "" {
endTime = time.Now().Format("2006-01-02 15:04:05")
}
query.Where("time >= ? and time <= ?", startTime, endTime)
if containerName != "" {
query.Where("container_name = ?", containerName)
}
//查询限制1000条日志
if err := query.Order("time desc").Limit(1000).Find(&logs).Error; err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("系统错误,请联系管理员"))
logrus.Errorln("查询容器日志sql失败", err, "查询参数:", startTime, endTime, containerName)
return
}
//过滤包含message内容
if message != "" {
for _, log := range logs {
if strings.Contains(log.Message, message) {
resLogs = append(resLogs, log)
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, strconv.Itoa(len(resLogs)), resLogs))
if err != nil {
return
}
} else {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, strconv.Itoa(len(logs)), logs))
if err != nil {
return
}
}
}
// 获取日志容器名称列表
func getSysLogsContainerList(ctx iris.Context) {
var list []string
db := database.GetInstance().GetMysqlDb()
if err := db.Model(&model.SysLogs{}).Distinct("container_name").Find(&list).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", list))
if err != nil {
return
}
}
// 手动保存日志
func saveLogs(ctx iris.Context) {
cPath, _ := os.Getwd()
logPath := path.Join(path.Join(cPath, config.Config.Logs.Nginx))
fileList, err := os.ReadDir(logPath)
if utils.ErrHandle(ctx, err) {
return
}
var resLogList []model.Logs
var logDealList []model.LogFileDealLog
db := database.GetInstance().GetMysqlDb()
if err1 := db.Find(&logDealList).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
for _, file := range fileList {
if strings.Contains(file.Name(), "access-") {
date := strings.Split(strings.Split(file.Name(), "access-")[1], ".")[0]
if checkDate(date, logDealList) {
continue
}
if err1 := db.Where("time like ?", fmt.Sprintf("%s%%", date)).Delete(&resLogList).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
logList, err := utils.FileRead(path.Join(logPath, file.Name()), true)
if utils.ErrHandle(ctx, err) {
return
}
for _, v := range logList {
c := make(chan model.Logs)
go FormatLog(v, date, c)
resLogItem := <-c
if err1 := db.Create(&resLogItem).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
resLogList = append(resLogList, resLogItem)
}
if err1 := db.Create(&model.LogFileDealLog{
Date: date,
Success: true,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", resLogList))
if utils.ErrHandle(ctx, err) {
return
}
}
// 判断日期是否已处理
func checkDate(date string, list []model.LogFileDealLog) bool {
for _, v := range list {
if v.Date == date && v.Success {
return true
}
}
return false
}
// 格式化日志内时间格式
func formatTime(date string, s string) string {
l := strings.Split(s, ":")
return fmt.Sprintf("%s %s:%s:%s", date, l[1], l[2], l[3])
}
// 从本地ipLocationList记录中获取IP对应地址
func getLocalIpAddr(ip string) string {
for _, v := range ipLocationList {
if v.Ip == ip {
return v.Location
}
}
return ""
}
// 从接口中获取IP对应地址
func getIpAddr(ip string) (string, error) {
db := database.GetInstance().GetMysqlDb()
location, err := utils.GetIpLocation(ip)
if err != nil {
return "", err
}
ipItem := model.IpsLocation{
Ip: ip,
Location: location,
Model: gorm.Model{},
}
if err1 := db.Create(&ipItem).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
UpdateLocalIpList()
return location, nil
}

View File

@ -0,0 +1,85 @@
package admin
import (
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/jwtSet"
"main/model"
"main/utils"
"strings"
)
func Logs(party iris.Party) {
party.Post("/", saveLogs)
party.Get("/", jwtSet.Jwt.Serve, checkAdmin, getLogStats)
party.Get("/detail", jwtSet.Jwt.Serve, checkAdmin, getLogDetail)
party.Get("/sys", jwtSet.Jwt.Serve, checkAdmin, getSysLogs)
party.Get("/log-container-list", jwtSet.Jwt.Serve, checkAdmin, getSysLogsContainerList)
}
// FormatLog 对日志内容切分,格式化数据
func FormatLog(logItem string, date string, c chan model.Logs) {
var resLogItem model.Logs
resLogItem.Ip = strings.Split(logItem, " ")[0]
resLogItem.Location = GetIpLocation(resLogItem.Ip)
//resLogItem.Location = getLocalIpAddr(resLogItem.Ip)
//if resLogItem.Location == "" {
// resLogItem.Location, _ = getIpAddr(resLogItem.Ip)
//}
resLogItem.Time = formatTime(date, strings.Split(strings.Split(logItem, "[")[1], "]")[0])
if strings.Split(logItem, "\"")[1] != "" {
if strings.Contains(strings.Split(logItem, "\"")[1], " /") {
resLogItem.Method = strings.Split(strings.Split(logItem, "\"")[1], " ")[0]
resLogItem.Path = strings.Split(strings.Split(logItem, "\"")[1], " ")[1]
} else {
resLogItem.Method = ""
resLogItem.Path = strings.Split(logItem, "\"")[1]
}
resLogItem.Status = strings.Split(strings.Split(logItem, "\" ")[1], " ")[0]
}
resLogItem.UserAgent = strings.Split(logItem, "\"")[5]
c <- resLogItem
}
// GetIpLocation 获取IP对应的地址
func GetIpLocation(ip string) string {
if len(ipLocationList) == 0 {
UpdateLocalIpList()
}
location := getLocalIpAddr(ip)
if location == "" {
location, _ = getIpAddr(ip)
}
return location
}
func UpdateLocalIpList() {
var nullDataList []nullData
db := database.GetInstance().GetMysqlDb()
if err := db.Model(&model.Logs{}).
Distinct("logs.ip", "ips_locations.location").
Where("ips_locations.location is null").
Joins("left join ips_locations on logs.ip=ips_locations.ip").
Scan(&nullDataList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(nullDataList) != 0 {
for _, data := range nullDataList {
location, err := utils.GetIpLocation(data.IP)
if err != nil {
logrus.Errorln(data.IP, "IP地址获取失败", err)
}
if err = db.Create(&model.IpsLocation{
Ip: data.IP,
Location: location,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
}
if err := db.Distinct("ip, location").Find(&ipLocationList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
logrus.Infoln("更新本地IP地址列表")
}

View File

@ -0,0 +1,103 @@
package admin
import (
"errors"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
)
func getMenu(ctx iris.Context) {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", utils.MenuList))
if utils.ErrHandle(ctx, err) {
return
}
}
func addMenu(ctx iris.Context) {
var param model.Menus
err := ctx.ReadJSON(&param)
if utils.ErrHandle(ctx, err) || utils.DataIsNil(param) {
return
}
if (len(param.MenuId) != 3 && len(param.MenuId) != 5) || param.MenuId[0:3] == "000" {
utils.ErrHandle(ctx, errors.New("菜单ID格式错误"))
return
}
if checkMenuExist(param) {
utils.ErrHandle(ctx, errors.New("菜单ID已存在"))
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Create(&param).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
utils.UpdateMenuList()
}
func updateMenu(ctx iris.Context) {
var param model.Menus
err := ctx.ReadJSON(&param)
if utils.ErrHandle(ctx, err) || utils.DataIsNil(param) {
return
}
if (len(param.MenuId) != 3 && len(param.MenuId) != 5) || param.MenuId[0:3] == "000" {
utils.ErrHandle(ctx, errors.New("菜单ID格式错误"))
return
}
if !checkMenuIDExist(param) || checkMenuExist(param) {
utils.ErrHandle(ctx, errors.New("菜单ID已存在"))
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Save(&param).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
utils.UpdateMenuList()
}
func deleteMenu(ctx iris.Context) {
menuId := ctx.URLParam("menu_id")
db := database.GetInstance().GetMysqlDb()
utils.UpdateMenuList()
for _, menu := range utils.MenuList {
if menu.MenuId == menuId || menu.MenuId[0:3] == menuId {
if err := db.Delete(&menu).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
utils.UpdateMenuList()
}
func checkMenuExist(menu model.Menus) bool {
for _, m := range utils.MenuList {
if menu.MenuId == m.MenuId && menu.ID != m.ID {
return true
}
}
return false
}
func checkMenuIDExist(menu model.Menus) bool {
for _, m := range utils.MenuList {
if menu.ID == m.ID {
return true
}
}
return false
}

View File

@ -0,0 +1,13 @@
package admin
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func Menus(party iris.Party) {
party.Get("/", jwtSet.Jwt.Serve, checkAdmin, getMenu)
party.Post("/", jwtSet.Jwt.Serve, checkAdmin, addMenu)
party.Put("/", jwtSet.Jwt.Serve, checkAdmin, updateMenu)
party.Delete("/", jwtSet.Jwt.Serve, checkAdmin, deleteMenu)
}

View File

@ -0,0 +1,106 @@
package admin
import (
"errors"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"strings"
)
func getSysSettings(ctx iris.Context) {
var res []resSysSettings
var resSysSettingsData []model.SysSettings
var currentList []string
name := ctx.Params().GetString("name")
for _, sysSetting := range utils.SysSettings {
if sysSetting.DType == "option" {
sysSetting.Name = strings.Split(sysSetting.Name, ":")[0]
}
if (name != "" && sysSetting.Name != name) || utils.CheckListItem(currentList, sysSetting.Name) {
continue
} else {
resSysSettingsData = nil
for _, v := range utils.SysSettings {
if strings.Split(v.Name, ":")[0] == sysSetting.Name {
resSysSettingsData = append(resSysSettingsData, v)
}
}
currentList = append(currentList, sysSetting.Name)
res = append(res, resSysSettings{Name: sysSetting.Name, Data: resSysSettingsData})
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}
func addSysSettings(ctx iris.Context) {
var params model.SysSettings
err := ctx.ReadJSON(&params)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if !checkExist(params) {
if err1 := db.Create(&params).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
utils.UpdateSysSettings()
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func delSettings(ctx iris.Context) {
var params model.SysSettings
err := ctx.ReadJSON(&params)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Delete(&params).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
utils.UpdateSysSettings()
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func updateSettings(ctx iris.Context) {
var params model.SysSettings
err := ctx.ReadJSON(&params)
if utils.ErrHandle(ctx, err) {
return
}
if !checkExist(params) {
if utils.ErrHandle(ctx, errors.New("配置信息不存在")) {
return
}
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Save(&params).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
utils.UpdateSysSettings()
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func checkExist(setting model.SysSettings) bool {
for _, sysSetting := range utils.SysSettings {
if setting.Name == sysSetting.Name && setting.Value == sysSetting.Value {
return true
}
}
return false
}

View File

@ -0,0 +1,13 @@
package admin
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func SysSettings(party iris.Party) {
party.Get("/", jwtSet.Jwt.Serve, checkAdmin, getSysSettings)
party.Post("/", jwtSet.Jwt.Serve, checkAdmin, addSysSettings)
party.Delete("/", jwtSet.Jwt.Serve, checkAdmin, delSettings)
party.Put("/", jwtSet.Jwt.Serve, checkAdmin, updateSettings)
}

View File

@ -0,0 +1,27 @@
package admin
import "main/model"
// logs-----------------------------------------------------------------------------
type resIpLocation struct {
Flag bool `json:"flag"`
Data resIpLocationData `json:"data"`
}
type resIpLocationData struct {
Ip string `json:"ip"`
Location string `json:"location"`
}
type nullData struct {
IP string `json:"ip"`
Location string `json:"location"`
}
type resLogStats struct {
Name string `json:"name"`
Value int `json:"value"`
}
// sysSettings------------------------------------------------------------------------
type resSysSettings struct {
Name string `json:"name"`
Data []model.SysSettings `json:"data"`
}

View File

@ -0,0 +1,66 @@
package admin
import (
"errors"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
)
func getUserList(ctx iris.Context) {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", utils.UserList))
if utils.ErrHandle(ctx, err) {
return
}
}
func updateUserInfo(ctx iris.Context) {
var userinfo model.Userinfo
err := ctx.ReadJSON(&userinfo)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Save(&userinfo).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
utils.UpdateUserInfo()
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func deleteUser(ctx iris.Context) {
loginUser := utils.GetLoginUser(ctx)
username := ctx.URLParam("username")
if username == loginUser.Username {
logrus.Errorln(loginUser.Username, "无法删除本人")
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("不可删除本人用户"))
return
}
db := database.GetInstance().GetMysqlDb()
var user []model.User
if err := db.Where("username = ?", username).Find(&user).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(user) == 0 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("用户不存在"))
return
}
if err := db.Where("username = ?", username).Delete(&model.User{}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Where("username = ?", username).Delete(&model.Userinfo{}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
utils.UpdateUserInfo()
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}

View File

@ -0,0 +1,12 @@
package admin
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func User(party iris.Party) {
party.Get("/", jwtSet.Jwt.Serve, checkAdmin, getUserList)
party.Put("/", jwtSet.Jwt.Serve, checkAdmin, updateUserInfo)
party.Delete("/", jwtSet.Jwt.Serve, checkAdmin, deleteUser)
}

View File

@ -0,0 +1,313 @@
package api
import (
"errors"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"strconv"
"strings"
)
// 初始化新棋盘
var cols = 15
func getRooms(ctx iris.Context) {
db := database.GetInstance().GetMysqlDb()
var rooms []typeRoomStatus
if err := db.Model(&model.BackgammonRoom{}).Distinct("room_id").Order("room_id").Scan(&rooms).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for k, v := range rooms {
roomStatus, err := getRoomStatus(v.RoomId)
if utils.ErrHandle(ctx, err) {
return
}
rooms[k].Player = roomStatus.Player
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", rooms))
if utils.ErrHandle(ctx, err) {
return
}
}
// 删除房间
func delRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id, err := strconv.Atoi(ctx.Params().Get("id"))
if utils.ErrHandle(ctx, err) {
return
}
roomStatus, err := getRoomStatus(id)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if roomStatus.Player == username.Username {
if err1 := db.Where("room_id = ?", id).Delete(&model.BackgammonRoom{}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
} else if strings.Split(roomStatus.Player, ",")[0] == username.Username {
if err1 := db.Create(&model.BackgammonRoom{
RoomId: roomStatus.RoomId,
Player: strings.Split(roomStatus.Player, ",")[1],
Winner: "",
Current: strings.Split(roomStatus.Player, ",")[1],
PawnStatus: initPawns(),
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
} else if strings.Split(roomStatus.Player, ",")[1] == username.Username {
if err1 := db.Create(&model.BackgammonRoom{
RoomId: roomStatus.RoomId,
Player: strings.Split(roomStatus.Player, ",")[0],
Winner: "",
Current: strings.Split(roomStatus.Player, ",")[0],
PawnStatus: initPawns(),
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func initPawns() string {
var newPawns string
for i := 0; i < cols; i++ {
tmp := "0" + strings.Repeat(",0", cols-1)
if i == 0 {
newPawns = tmp
continue
}
newPawns += ";" + tmp
}
return newPawns
}
// 新建房间
func addRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var currentStatus model.BackgammonRoom
db := database.GetInstance().GetMysqlDb()
if err := db.Order("room_id desc").First(&currentStatus).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
newPawns := initPawns()
if err := db.Create(&model.BackgammonRoom{
RoomId: currentStatus.RoomId + 1,
Player: username.Username,
Current: username.Username,
Winner: "",
PawnStatus: newPawns,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", currentStatus.RoomId+1))
if utils.ErrHandle(ctx, err) {
return
}
}
func joinRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id, err := strconv.Atoi(ctx.Params().Get("id"))
if utils.ErrHandle(ctx, err) {
return
}
roomStatus, err := getRoomStatus(id)
if utils.ErrHandle(ctx, err) {
return
}
if utils.CheckListItem(strings.Split(roomStatus.Player, ","), username.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("无法重复加入房间"))
return
}
if !utils.CheckListItem(strings.Split(roomStatus.Player, ","), username.Username) && len(strings.Split(roomStatus.Player, ",")) > 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人数已满"))
return
}
roomStatus.Player = roomStatus.Player + "," + username.Username
db := database.GetInstance().GetMysqlDb()
if err1 := db.Model(&model.BackgammonRoom{}).Where("id = ?", roomStatus.ID).Updates(&roomStatus).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func getRoomStatus(roomId int) (model.BackgammonRoom, error) {
var status model.BackgammonRoom
db := database.GetInstance().GetMysqlDb()
if err := db.Where("room_id = ?", roomId).Order("id desc").First(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(status) {
return model.BackgammonRoom{}, errors.New("房间号不存在")
}
return status, nil
}
// 获取房间棋盘状态
func getStatus(ctx iris.Context) {
id, err := strconv.Atoi(ctx.Params().Get("id"))
if utils.ErrHandle(ctx, err) {
return
}
roomStatus, err := getRoomStatus(id)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", roomStatus))
if utils.ErrHandle(ctx, err) {
return
}
}
// 新增棋子
func addPawn(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id, err := strconv.Atoi(ctx.Params().Get("id"))
if utils.ErrHandle(ctx, err) {
return
}
roomStatus, err := getRoomStatus(id)
if utils.ErrHandle(ctx, err) {
return
}
var tmpT string
if roomStatus.Winner != "" {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("对局已结束"))
return
}
if len(strings.Split(roomStatus.Player, ",")) != 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前房间,玩家人数不足"))
return
}
if roomStatus.Current != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("现在不是你的回合"))
return
}
if strings.Split(roomStatus.Player, ",")[0] == username.Username {
tmpT = "1"
} else if strings.Split(roomStatus.Player, ",")[1] == username.Username {
tmpT = "-1"
} else {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("非玩家,无法进行游戏"))
return
}
place := strings.Split(ctx.URLParam("place"), ",")
var newPawn []int
for _, i := range place {
tmp, _ := strconv.Atoi(i)
newPawn = append(newPawn, tmp)
}
var pawnStatus [][]string
for _, i := range strings.Split(roomStatus.PawnStatus, ";") {
var tmp []string
for _, j := range strings.Split(i, ",") {
tmp = append(tmp, j)
}
pawnStatus = append(pawnStatus, tmp)
}
if pawnStatus[newPawn[0]][newPawn[1]] != "0" {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("该位置已有棋子"))
return
}
winner := getWinner(pawnStatus, tmpT, [2]int{newPawn[0], newPawn[1]})
if winner {
roomStatus.Winner = username.Username
}
pawnStatus[newPawn[0]][newPawn[1]] = tmpT
var tmp []string
for _, i := range pawnStatus {
tmp = append(tmp, strings.Join(i, ","))
}
roomStatus.PawnStatus = strings.Join(tmp, ";")
roomStatus.Current = strings.Replace(strings.Replace(roomStatus.Player, username.Username, "", 1), ",", "", 1)
db := database.GetInstance().GetMysqlDb()
if err1 := db.Create(&model.BackgammonRoom{
RoomId: roomStatus.RoomId,
Player: roomStatus.Player,
Winner: roomStatus.Winner,
Current: roomStatus.Current,
PawnStatus: roomStatus.PawnStatus,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", roomStatus))
if utils.ErrHandle(ctx, err) {
return
}
}
// 判断当前是否存在winner
func getWinner(pawns [][]string, t string, pawn [2]int) bool {
pawnAround := [8][2]int{{pawn[0] - 1, pawn[1] - 1}, {pawn[0], pawn[1] - 1}, {pawn[0] + 1, pawn[1] - 1}, {pawn[0] - 1, pawn[1]},
{pawn[0] + 1, pawn[1]}, {pawn[0] - 1, pawn[1] + 1}, {pawn[0], pawn[1] + 1}, {pawn[0] + 1, pawn[1] + 1}}
around := [8]int{0, 0, 0, 0, 0, 0, 0, 0}
for i, p := range pawnAround {
if p[0] >= 0 && p[1] >= 0 && p[0] < cols && p[1] < cols && pawns[p[0]][p[1]] == t {
current := [2]int{p[0], p[1]}
for j := 0; j < 3; j++ {
switch i {
case 0:
current[0]--
current[1]--
case 1:
current[1]--
case 2:
current[0]++
current[1]--
case 3:
current[0]--
case 4:
current[0]++
case 5:
current[0]--
current[1]++
case 6:
current[1]++
case 7:
current[0]++
current[1]++
}
//fmt.Println(current)
if current[0] < 0 || current[0] > cols-1 || current[1] < 0 || current[1] > cols-1 || pawns[current[0]][current[1]] != t {
around[i] = j + 1
break
}
around[i] = j + 2
}
}
}
if around[0]+around[7] >= 4 || around[1]+around[6] >= 4 || around[2]+around[5] >= 4 || around[3]+around[4] >= 4 {
return true
}
return false
}

View File

@ -0,0 +1,15 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func Backgammon(party iris.Party) {
party.Get("/", getRooms)
party.Post("/", jwtSet.Jwt.Serve, addRoom)
party.Get("/{id:int}", getStatus)
party.Put("/{id:int}", jwtSet.Jwt.Serve, joinRoom)
party.Delete("/{id:int}", jwtSet.Jwt.Serve, delRoom)
party.Post("/{id:int}", jwtSet.Jwt.Serve, addPawn)
}

View File

@ -0,0 +1,614 @@
package api
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"io"
"main/database"
"main/model"
"main/utils"
"math/rand"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
)
var initChessPawns = model.ChessStatus{
Current: "",
IsEnd: false,
Status: "0,1,2,3,4,5,6,7,8;-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,9,-1,-1,-1,-1,-1,10,-1;11,-1,12,-1,13,-1,14,-1,15;-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,-1,-1,-1,-1,-1,-1,-1,-1;31,-1,30,-1,29,-1,28,-1,27;-1,26,-1,-1,-1,-1,-1,25,-1;-1,-1,-1,-1,-1,-1,-1,-1,-1;24,23,22,21,20,19,18,17,16",
Winner: "",
ChessId: "",
}
func addAiChessPlayer(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if status.Players != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房主方可添加机器人"))
return
}
status.Players += ",ai--" + id
status.Status = initChessPawns.Status
status.Current = username.Username
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.ChessId = initChessPawns.ChessId
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
func updateChessAiStep(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if players := strings.Split(status.Players, ","); players[0] != username.Username || players[1] != "ai--"+id {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人员配置错误"))
return
}
if status.Current != "ai--"+id {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前非ai回合"))
return
}
stepList := strings.Split(getAiChessStep(chessPawnStatusToFen(chessPawnStrToSlice(status.Status)), "queryall", "b"), "|")
var tmpNum int
if strings.Index(stepList[0], "score:??") != -1 {
rand.NewSource(time.Now().Unix())
tmpNum = rand.Intn(len(stepList))
} else {
tmpNum = 0
}
stepTmp := strings.Split(stepList[tmpNum], ",")[0]
//fmt.Println(stepTmp, chessPawnStatusToFen(chessPawnStrToSlice(status.Status)))
if strings.Index(stepTmp, "move:") == -1 {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("机器人无合适步骤,对局结束"))
return
}
step := strings.Split(stepTmp, "move:")[1]
tmp := "abcdefghi0123456789"
statusList := chessPawnStrToSlice(status.Status)
start0 := 8 - strings.IndexByte(tmp, step[0])
end0 := 8 - strings.IndexByte(tmp, step[2])
start1 := strings.IndexByte(tmp, step[1]) - 9
end1 := strings.IndexByte(tmp, step[3]) - 9
statusList[end1][end0] = statusList[start1][start0]
statusList[start1][start0] = "-1"
status.Status = chessPawnSliceToStr(statusList)
status.ChessId = statusList[end1][end0]
status.Current = username.Username
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(200, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
func testChess(ctx iris.Context) {
var res [][]string
db := database.GetInstance().GetMysqlDb()
var status []model.ChessStatus
if err := db.Find(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, s := range status {
stepTmp := getAiChessStep(chessPawnStatusToFen(chessPawnStrToSlice(s.Status)), "queryall", "b")
//fmt.Println(s.Status, chessPawnStatusToFen(chessPawnStrToSlice(s.Status)))
step := strings.Split(stepTmp, "move:")[1]
tmp := "abcdefghi0123456789"
//statusList := chessPawnStrToSlice(status.Status)
start0 := strings.IndexByte(tmp, step[0])
end0 := strings.IndexByte(tmp, step[2])
start1 := strings.IndexByte(tmp, step[1]) - 9
end1 := strings.IndexByte(tmp, step[3]) - 9
statusTmp := chessPawnStrToSlice(s.Status)
start := statusTmp[start1][start0]
end := statusTmp[end1][end0]
res = append(res, []string{start, end})
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}
func resetRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if username.Username == "" {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if strings.Split(status.Players, ",")[0] != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房主方可重置房间"))
return
}
db := database.GetInstance().GetMysqlDb()
status.Status = initChessPawns.Status
status.Current = username.Username
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.ChessId = initChessPawns.ChessId
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 新建房间
func newChessRoom(ctx iris.Context) {
creator := utils.GetLoginUser(ctx)
if creator.Username == "" {
return
}
db := database.GetInstance().GetMysqlDb()
status := model.ChessStatus{
Players: creator.Username,
Current: creator.Username,
IsEnd: initChessPawns.IsEnd,
Status: initChessPawns.Status,
Winner: initChessPawns.Winner,
ChessId: initChessPawns.ChessId,
}
if err := db.Create(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status.ID))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取所有房间
func getChessRooms(ctx iris.Context) {
db := database.GetInstance().GetMysqlDb()
var rooms []model.ChessStatus
if err := db.Find(&rooms).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", rooms))
if utils.ErrHandle(ctx, err) {
return
}
}
// 加入房间
func joinChessRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if len(strings.Split(status.Players, ",")) >= 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人数已满"))
return
}
if utils.CheckListItem(strings.Split(status.Players, ","), username.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("不可重复加入房间"))
return
}
status.Players += fmt.Sprintf(",%s", username.Username)
db := database.GetInstance().GetMysqlDb()
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.ChessStatusLog{
RoomId: status.ID,
Players: status.Players,
Current: status.Current,
IsEnd: status.IsEnd,
Status: status.Status,
Winner: status.Winner,
ChessId: status.ChessId,
Time: status.CreatedAt,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 离开房间
func leaveChessRoom(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if !utils.CheckListItem(strings.Split(status.Players, ","), username.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未加入该房间"))
return
}
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Players = v
}
}
db := database.GetInstance().GetMysqlDb()
if status.Players == username.Username || status.Players == "ai--"+id {
if err := db.Delete(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
} else {
status.Current = status.Players
status.ChessId = initChessPawns.ChessId
status.IsEnd = initChessPawns.IsEnd
status.Winner = initChessPawns.Winner
status.Status = initChessPawns.Status
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取房间状态接口
func getChessRoom(ctx iris.Context) {
id := ctx.Params().Get("id")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 更新棋盘状态
func updateChessStatus(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
id := ctx.Params().Get("id")
pawn := ctx.URLParam("pawn")
des := ctx.URLParam("des")
status := getChessRoomStatus(id)
if utils.DataIsNil(status) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间号不存在"))
return
}
if len(strings.Split(status.Players, ",")) < 2 {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("房间人数不足"))
return
}
pawnNum, _ := strconv.Atoi(pawn)
if (strings.Split(status.Players, ",")[0] == username.Username && pawnNum > 15) || (strings.Split(status.Players, ",")[1] == username.Username && pawnNum < 16) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只能移动自己的棋子"))
return
}
if status.Current != username.Username {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前不是你的回合"))
return
}
if checkChessStep(pawn, status.Status, des) {
tmpStatus := chessPawnStrToSlice(status.Status)
locTmp := getPawnLoc(status.Status, pawn)
toTmp0, _ := strconv.Atoi(strings.Split(des, ",")[0])
toTmp1, _ := strconv.Atoi(strings.Split(des, ",")[1])
tmpStatus[locTmp[0]][locTmp[1]] = "-1"
tmpStatus[toTmp0][toTmp1] = pawn
status.Status = chessPawnSliceToStr(tmpStatus)
status.ChessId = pawn
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Current = v
}
}
if checkWinner(status.Status) == 1 {
status.Winner = username.Username
status.IsEnd = true
status.Current = ""
}
} else {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("当前无法移到该位置"))
return
}
db := database.GetInstance().GetMysqlDb()
if checkWinner(status.Status) == 2 {
for _, v := range strings.Split(status.Players, ",") {
if v != username.Username {
status.Winner = v
status.IsEnd = true
}
}
}
if err := db.Save(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.ChessStatusLog{
RoomId: status.ID,
Current: status.Current,
Players: status.Players,
IsEnd: status.IsEnd,
Status: status.Status,
Winner: status.Winner,
ChessId: status.ChessId,
Time: status.CreatedAt,
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", status))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取房间状态方法
func getChessRoomStatus(id string) model.ChessStatus {
db := database.GetInstance().GetMysqlDb()
var status model.ChessStatus
if err := db.Where("id = ?", id).First(&status).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
return status
}
func checkWinner(status string) int {
if utils.DataIsNil(getPawnLoc(status, "4")) || utils.DataIsNil(getPawnLoc(status, "20")) {
return 1
}
if checkNullPath(chessPawnStrToSlice(status), getPawnLoc(status, "4"), getPawnLoc(status, "20")) {
return 2
}
return 0
}
// 获取棋子位置
func getPawnLoc(statusStr string, pawn string) [2]int {
var res [2]int
status := chessPawnStrToSlice(statusStr)
for row, i := range status {
for col, j := range i {
if j == pawn {
res[0] = row
res[1] = col
}
}
}
return res
}
// 判断棋子是否可移动
func checkChessStep(pawn string, statusStr string, to string) bool {
locList := getPawnLoc(statusStr, pawn)
status := chessPawnStrToSlice(statusStr)
locTmp0 := locList[0]
locTmp1 := locList[1]
toTmp := strings.Split(to, ",")
toTmp0, _ := strconv.Atoi(toTmp[0])
toTmp1, _ := strconv.Atoi(toTmp[1])
//目标位置超出棋盘
if toTmp0 < 0 || toTmp1 < 0 || toTmp0 > 10 || toTmp1 > 8 {
return false
}
pawnNum, _ := strconv.Atoi(pawn)
toPawnNum, _ := strconv.Atoi(status[toTmp0][toTmp1])
if (pawnNum < 16 && toPawnNum < 16 && toPawnNum >= 0) || (pawnNum > 15 && toPawnNum > 15) {
return false
}
switch pawn {
case "0", "8", "16", "24": //车:同行列,路径为空
if (toTmp0 == locTmp0 && toTmp1 != locTmp1) || (toTmp1 == locTmp1 && toTmp0 != locTmp0) && checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) {
return true
}
case "1", "7", "17", "23": //马:日字,前后左右无子
if (utils.IntAbs(toTmp0-locTmp0) == 1 && utils.IntAbs(toTmp1-locTmp1) == 2 && status[locTmp0][(locTmp1+toTmp1)/2] == "-1") || (utils.IntAbs(toTmp0-locTmp0) == 2 && utils.IntAbs(toTmp1-locTmp1) == 1 && status[(locTmp0+toTmp0)/2][locTmp1] == "-1") {
return true
}
case "2", "6", "18", "22": //象:田字,不过河,中间格子为空
if utils.IntAbs(toTmp0-locTmp0) == 2 && utils.IntAbs(toTmp1-locTmp1) == 2 && ((locTmp0 < 5 && toTmp0 < 5) || (locTmp0 > 4 && toTmp0 > 4)) && status[(locTmp0+toTmp0)/2][(locTmp1+toTmp1)/2] == "-1" {
return true
}
case "3", "5", "19", "21": //士:斜着走,不超出方格
if toTmp1 < 3 || toTmp1 > 5 || (locTmp0 < 5 && toTmp0 > 2) || (locTmp0 > 4 && toTmp0 < 7) {
return false
}
if utils.IntAbs(toTmp0-locTmp0) == 1 && utils.IntAbs(toTmp1-locTmp1) == 1 {
return true
}
case "4", "20": //将:走一步,不超出方格
if toTmp1 < 3 || toTmp1 > 5 || (locTmp0 < 5 && toTmp0 > 2) || (locTmp0 > 4 && toTmp0 < 7) {
return false
}
if utils.IntAbs(toTmp0-locTmp0)+utils.IntAbs(toTmp1-locTmp1) == 1 {
return true
}
case "9", "10", "25", "26": //炮:同行列,路径不为空,目标位置不为空
if ((toTmp0 == locTmp0 && toTmp1 != locTmp1) || (toTmp1 == locTmp1 && toTmp0 != locTmp0)) && ((!checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) && status[toTmp0][toTmp1] != "-1") || (checkNullPath(status, [2]int{locTmp0, locTmp1}, [2]int{toTmp0, toTmp1}) && status[toTmp0][toTmp1] == "-1")) {
return true
}
case "11", "12", "13", "14", "15": //兵:走一步,过河后可横移
if (toTmp0 < 5 && toTmp1 == locTmp1 && toTmp0-locTmp0 == 1) || (toTmp0 > 4 && utils.IntAbs(toTmp0-locTmp0+toTmp1-locTmp1) == 1) {
return true
}
case "27", "28", "29", "30", "31": //兵:走一步,过河后可横移
if (toTmp0 > 4 && toTmp1 == locTmp1 && toTmp0-locTmp0 == -1) || (toTmp0 < 5 && utils.IntAbs(toTmp0-locTmp0+toTmp1-locTmp1) == 1) {
return true
}
default:
return false
}
return false
}
// 棋盘状态字符串转数组
func chessPawnStrToSlice(status string) [][]string {
var res [][]string
for _, i := range strings.Split(status, ";") {
var colList []string
for _, j := range strings.Split(i, ",") {
colList = append(colList, j)
}
res = append(res, colList)
}
return res
}
// 棋盘状态数组转字符串
func chessPawnSliceToStr(status [][]string) string {
var resList []string
for _, i := range status {
resList = append(resList, strings.Join(i, ","))
}
res := strings.Join(resList, ";")
return res
}
func chessPawnStatusToFen(status [][]string) string {
var res []string
for _, i := range status {
resTmp := ""
count := 0
for col, j := range i {
if j == "-1" && col == len(i)-1 {
resTmp += strconv.Itoa(count + 1)
} else if j == "-1" {
count += 1
} else {
if count != 0 {
resTmp += strconv.Itoa(count)
count = 0
}
switch j {
case "0", "8":
resTmp += "R"
case "1", "7":
resTmp += "N"
case "2", "6":
resTmp += "B"
case "3", "5":
resTmp += "A"
case "4":
resTmp += "K"
case "9", "10":
resTmp += "C"
case "11", "12", "13", "14", "15":
resTmp += "P"
case "16", "24":
resTmp += "r"
case "17", "23":
resTmp += "n"
case "18", "22":
resTmp += "b"
case "19", "21":
resTmp += "a"
case "20":
resTmp += "k"
case "25", "26":
resTmp += "c"
case "27", "28", "29", "30", "31":
resTmp += "p"
}
}
}
res = append(res, resTmp)
}
return utils.Reverse(strings.Join(res, "/"))
}
// 判断路径是否为空
func checkNullPath(status [][]string, start [2]int, end [2]int) bool {
if start[0] == end[0] {
path := []int{start[1], end[1]}
sort.Ints(path)
for i := path[0] + 1; i < path[1]; i++ {
if status[start[0]][i] != "-1" {
return false
}
}
return true
}
if start[1] == end[1] {
path := []int{start[0], end[0]}
sort.Ints(path)
for i := path[0] + 1; i < path[1]; i++ {
if status[i][start[1]] != "-1" {
return false
}
}
return true
}
return false
}
func getAiChessStep(fenStatus string, t string, p string) string {
urlPath, err := url.Parse("http://www.chessdb.cn/chessdb.php")
params := url.Values{}
params.Set("action", t)
params.Set("board", fmt.Sprintf("%s %s", fenStatus, p))
params.Set("showall", "1")
urlPath.RawQuery = params.Encode()
res, err := http.Get(urlPath.String())
if err != nil {
return err.Error()
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
}
}(res.Body)
body, _ := io.ReadAll(res.Body)
return string(body)
}

View File

@ -0,0 +1,19 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func Chess(party iris.Party) {
party.Post("/", jwtSet.Jwt.Serve, newChessRoom)
party.Get("/", getChessRooms)
party.Get("/{id:int}", getChessRoom)
party.Post("/{id:int}", jwtSet.Jwt.Serve, joinChessRoom)
party.Delete("/{id:int}", jwtSet.Jwt.Serve, leaveChessRoom)
party.Put("/{id:int}", jwtSet.Jwt.Serve, updateChessStatus)
party.Get("/{id:int}/reset", jwtSet.Jwt.Serve, resetRoom)
party.Post("/{id:int}/ai", jwtSet.Jwt.Serve, addAiChessPlayer)
party.Put("/{id:int}/ai", jwtSet.Jwt.Serve, updateChessAiStep)
party.Get("/test", testChess)
}

View File

@ -0,0 +1,319 @@
package api
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"mime/multipart"
"os"
"path"
"path/filepath"
"strings"
"time"
)
func getRootFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
userPath := fmt.Sprintf("./upload/%s", username.Username)
if !utils.FileIsExist(userPath) {
err := os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
var files filesRes
fileList, err := os.ReadDir(userPath)
if utils.ErrHandle(ctx, err) {
return
}
for _, file := range fileList {
if file.IsDir() {
files.Dirs = append(files.Dirs, file.Name())
} else {
var item fileItem
item.Name = file.Name()
f, err := os.Stat(path.Join(userPath, file.Name()))
if utils.ErrHandle(ctx, err) {
return
}
item.Size = f.Size()
item.Type = utils.GetFileType(f.Name())
files.Files = append(files.Files, item)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", files))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取指定目录下文件
func getFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New(userPath + ":目录不存在"))
return
}
var files filesRes
fileList, err := os.ReadDir(userPath)
if utils.ErrHandle(ctx, err) {
return
}
for _, file := range fileList {
if file.IsDir() {
files.Dirs = append(files.Dirs, file.Name())
} else {
var item fileItem
item.Name = file.Name()
f, err := os.Stat(path.Join(userPath, file.Name()))
if utils.ErrHandle(ctx, err) {
return
}
item.Size = f.Size()
item.Type = utils.GetFileType(f.Name())
files.Files = append(files.Files, item)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", files))
if utils.ErrHandle(ctx, err) {
return
}
}
// 删除文件或目录
func deleteFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("目录不存在"))
return
}
if info, _ := os.Stat(userPath); info.IsDir() {
err := os.RemoveAll(userPath)
if utils.ErrHandle(ctx, err) {
return
}
} else {
err := os.Remove(userPath)
if utils.ErrHandle(ctx, err) {
return
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 上传头像
func uploadAvatar(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
file, info, err := ctx.FormFile("file")
if utils.ErrHandle(ctx, err) {
return
}
defer func(file multipart.File) {
err = file.Close()
if utils.ErrHandle(ctx, err) {
return
}
}(file)
userPath := fmt.Sprintf("./static/%s", username.Username)
if !utils.FileIsExist(userPath) {
err = os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
fileType := strings.Split(info.Filename, ".")[len(strings.Split(info.Filename, "."))-1]
avatarName := fmt.Sprintf("./static/%s/avatar-%s.%s", username.Username, time.Now().Format("2006-01-02"), fileType)
_, err = ctx.SaveFormFile(info, avatarName)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", avatarName[1:]))
if utils.ErrHandle(ctx, err) {
return
}
}
func uploadDir(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("目录已存在"))
return
}
err := os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 上传文件
func uploadFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
filePath := ctx.Params().Get("path")
file, info, err := ctx.FormFile("file")
if utils.ErrHandle(ctx, err) {
return
}
defer func(file multipart.File) {
err = file.Close()
if utils.ErrHandle(ctx, err) {
return
}
}(file)
userPath := fmt.Sprintf("./upload/%s/%s", username.Username, filePath)
if !utils.FileIsExist(userPath) {
err = os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
_, err = ctx.SaveFormFile(info, fmt.Sprintf("./upload/%s/%s/%s", username.Username, filePath, info.Filename))
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 文件下载转到nginx-upload目录
func downloadFile(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", userToken.Username, filePath)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("文件不存在"))
return
}
if info, _ := os.Stat(userPath); info.IsDir() {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只可下载文件"))
return
}
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload/%s/%s", userToken.Username, filePath))
ctx.Recorder().Header().Add("X-Accel-Charset", "utf-8")
ctx.Recorder().Header().Add("Content-Disposition", "attachment")
ctx.Recorder().Header().Add("Content-Type", "application/octet-stream; charset=utf-8")
return
}
func getDownloadFileType(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
var res videoM3u8
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
username := userToken.Username
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username, filePath)
currentPath, _ := filepath.Split(filePath)
filename := strings.TrimSuffix(path.Base(userPath), path.Ext(userPath))
res.Video = utils.GetFileType(userPath) == "video"
res.M3u8 = utils.FileIsExist(fmt.Sprintf("./upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename))
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if err != nil {
return
}
return
}
func downloadVideo(ctx iris.Context) {
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
username := userToken.Username
filePath := ctx.Params().Get("path")
userPath := fmt.Sprintf("./upload/%s/%s", username, filePath)
currentPath, _ := filepath.Split(filePath)
filename := strings.TrimSuffix(path.Base(userPath), path.Ext(userPath))
//fmt.Println(filePath, currentPath, filename)
if path.Ext(userPath) != ".ts" && !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("文件不存在"))
return
}
if info, err := os.Stat(userPath); err == nil && info.IsDir() {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只可下载文件"))
return
}
if utils.GetFileType(userPath) == "video" && utils.FileIsExist(fmt.Sprintf("./upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename)) {
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload-video/%s/%s%s/%s.m3u8", username, currentPath, filename, filename))
} else if utils.GetFileType(userPath) == "video" {
ctx.Recorder().Header().Add("X-Accel-Redirect", fmt.Sprintf("/upload/%s/%s", username, filePath))
} else {
tsPath := fmt.Sprintf("./upload-video/%s/%s%s/%s.ts", username, currentPath, filename[:len(filename)-6], filename)
ctx.Recorder().Header().Add("X-Accel-Redirect", tsPath[1:])
}
ctx.Recorder().Header().Add("X-Accel-Charset", "utf-8")
ctx.Recorder().Header().Add("Content-Disposition", "attachment")
ctx.Recorder().Header().Add("Content-Type", "application/octet-stream; charset=utf-8")
return
}

View File

@ -0,0 +1,18 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func File(party iris.Party) {
party.Get("/upload", jwtSet.Jwt.Serve, getRootFile)
party.Get("/upload/{path:path}", jwtSet.Jwt.Serve, getFile)
party.Post("/upload/{path:path}", jwtSet.Jwt.Serve, uploadDir)
party.Post("/upload-file/{path:path}", jwtSet.Jwt.Serve, uploadFile)
party.Delete("/upload/{path:path}", jwtSet.Jwt.Serve, deleteFile)
party.Post("/static/avatar", jwtSet.Jwt.Serve, uploadAvatar)
party.Get("/download/{path:path}", downloadFile)
party.Get("/download-video-check/{path:path}", getDownloadFileType)
party.Get("/download-video/{path:path}", downloadVideo)
}

View File

@ -0,0 +1,13 @@
package api
import (
"github.com/kataras/iris/v12"
"main/utils"
)
func Apis(ctx iris.Context) {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "allApis"))
if err != nil {
return
}
}

View File

@ -0,0 +1,55 @@
package api
import (
"fmt"
"github.com/kataras/iris/v12"
"main/utils"
"regexp"
)
func getMenu(ctx iris.Context) {
var resTmp []subMenu
var res []resMenu
user := utils.GetLoginUser(ctx)
if utils.DataIsNil(user) {
return
}
if len(utils.MenuList) == 0 {
utils.UpdateMenuList()
}
resTmp = append(resTmp, subMenu{MenuId: "000", Name: "首页", Icon: "bi-emoji-wink", Path: "/", RouteOnly: false})
for _, menu := range utils.MenuList {
patternWhiteList := fmt.Sprintf("^%s,|,%s,|,%s$|%s", user.Username, user.Username, user.Username, user.Username)
regWhiteList := regexp.MustCompile(patternWhiteList)
patternUserType := fmt.Sprintf("^%s,|,%s,|,%s$|%s", user.Type, user.Type, user.Type, user.Type)
regUserType := regexp.MustCompile(patternUserType)
if match := regWhiteList.MatchString(menu.WhiteList); match || regUserType.MatchString(menu.UserType) {
resTmp = append(resTmp, subMenu{
MenuId: menu.MenuId,
Name: menu.Name,
Icon: menu.Icon,
Path: menu.Path,
RouteOnly: menu.RouteOnly,
})
}
}
for _, menu := range resTmp {
if menu.RouteOnly {
res = append(res, resMenu{MenuId: menu.MenuId, Name: menu.Name, Icon: menu.Icon, Path: menu.Path, RouteOnly: menu.RouteOnly})
continue
}
if len(menu.MenuId) == 3 {
var tmp []subMenu
for _, sub := range resTmp {
if len(sub.MenuId) == 5 && sub.MenuId[0:3] == menu.MenuId && !sub.RouteOnly {
tmp = append(tmp, sub)
}
}
res = append(res, resMenu{MenuId: menu.MenuId, Name: menu.Name, Icon: menu.Icon, Path: menu.Path, Detail: tmp})
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}

View File

@ -0,0 +1,10 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func Menus(party iris.Party) {
party.Get("/", jwtSet.Jwt.Serve, getMenu)
}

View File

@ -0,0 +1,210 @@
package api
import (
"errors"
"fmt"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"mime/multipart"
"os"
"time"
)
func getNotesList(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var notes []model.UserNotes
var res []noteParam
db := database.GetInstance().GetMysqlDb()
if err := db.Where("username = ?", username.Username).Select("id", "content").Find(&notes).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, item := range notes {
if len(item.Content) > 100 {
item.Content = item.Content[:30] + "\n......"
}
res = append(res, noteParam{
ID: item.ID,
Content: item.Content,
})
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}
func addNote(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var note noteParam
err := ctx.ReadJSON(&note)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Create(&model.UserNotes{
Username: username.Username,
Content: note.Content,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
var newNote model.UserNotes
if err1 := db.Where("username = ?", username.Username).Order("id desc").First(&newNote).Error; err1 != nil {
logrus.Errorln("sql执行失败", err)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", newNote.ID))
if utils.ErrHandle(ctx, err) {
return
}
}
func getNote(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
db := database.GetInstance().GetMysqlDb()
var note model.UserNotes
if err := db.Where("username = ? and id = ?", username.Username, ctx.Params().Get("id")).Find(&note).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(note) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("not found"))
return
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", note))
if utils.ErrHandle(ctx, err) {
return
}
}
func deleteNote(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var note model.UserNotes
db := database.GetInstance().GetMysqlDb()
if err := db.Where("username = ? and id = ?", username.Username, ctx.Params().Get("id")).Find(&note).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(note) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("not found"))
return
}
if err := db.Delete(&note).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func updateNote(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var note model.UserNotes
db := database.GetInstance().GetMysqlDb()
if err := db.Where("username = ? and id = ?", username.Username, ctx.Params().Get("id")).Find(&note).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(note) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("not found"))
return
}
var newNote noteParam
err := ctx.ReadJSON(&newNote)
if utils.ErrHandle(ctx, err) {
return
}
if err1 := db.Model(&note).Updates(model.UserNotes{
Content: newNote.Content,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func uploadNoteFile(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
noteId := ctx.Params().Get("id")
userPath := fmt.Sprintf("./upload-note/%s/%s", username.Username, noteId)
if !utils.FileIsExist(userPath) {
err := os.MkdirAll(userPath, 0755)
if utils.ErrHandle(ctx, err) {
return
}
}
file, info, err := ctx.FormFile("file")
if utils.ErrHandle(ctx, err) {
return
}
defer func(file multipart.File) {
err = file.Close()
if utils.ErrHandle(ctx, err) {
return
}
}(file)
filePath := fmt.Sprintf("%s/%s", userPath, info.Filename)
_, err = ctx.SaveFormFile(info, filePath)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", fmt.Sprintf("/api/notes/%s/file/%s", noteId, info.Filename)))
if utils.ErrHandle(ctx, err) {
return
}
}
func getNoteFile(ctx iris.Context) {
noteId := ctx.Params().Get("id")
authToken := ctx.GetCookie("token")
activeTime := time.Now().Add(-2 * time.Hour)
var userToken model.JwtKeys
db := database.GetInstance().GetMysqlDb()
if err := db.Where("token = ? and created_at >= ?", authToken, activeTime).First(&userToken).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(userToken.Username) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("未登录"))
return
}
filename := ctx.Params().Get("filename")
userPath := fmt.Sprintf("./upload-note/%s/%s/%s", userToken.Username, noteId, filename)
if !utils.FileIsExist(userPath) {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("文件不存在"))
return
}
if info, _ := os.Stat(userPath); info.IsDir() {
ctx.StatusCode(iris.StatusBadRequest)
ctx.SetErr(errors.New("只可下载文件"))
return
}
ctx.Recorder().Header().Add("X-Accel-Redirect", userPath[1:])
ctx.Recorder().Header().Add("X-Accel-Charset", "utf-8")
ctx.Recorder().Header().Add("Content-Disposition", "attachment")
ctx.Recorder().Header().Add("Content-Type", "application/octet-stream; charset=utf-8")
return
}

View File

@ -0,0 +1,16 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func Notes(party iris.Party) {
party.Get("/", jwtSet.Jwt.Serve, getNotesList)
party.Post("/", jwtSet.Jwt.Serve, addNote)
party.Get("/{id:int}", jwtSet.Jwt.Serve, getNote)
party.Put("/{id:int}", jwtSet.Jwt.Serve, updateNote)
party.Delete("/{id:int}", jwtSet.Jwt.Serve, deleteNote)
party.Post("/{id:int}/file", jwtSet.Jwt.Serve, uploadNoteFile)
party.Get("/{id:int}/file/{filename:string}", getNoteFile)
}

View File

@ -0,0 +1,88 @@
package api
import (
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/utils"
"strconv"
"strings"
"time"
)
// 获取节假日信息
func getHolidays(ctx iris.Context) {
yearParam := ctx.URLParam("year")
if yearParam == "" {
yearParam = strconv.Itoa(time.Now().Year())
}
logrus.Infoln("假期查询年份:", yearParam)
year, err := strconv.Atoi(yearParam)
var res []utils.ResHolidays
if utils.ErrHandle(ctx, err) {
return
}
if utils.ErrHandle(ctx, err) {
return
}
startDate := time.Date(year, 1, 1, 0, 0, 0, 0, time.Local)
for startDate.Year() == year {
isHoliday, name := utils.CheckHoliday(startDate.Format("2006-01-02"))
if startDate.Weekday() == time.Saturday || startDate.Weekday() == time.Sunday {
res = append(res, utils.ResHolidays{
Date: startDate.Format("2006-01-02"),
HolidayNameCn: "周末",
})
} else if isHoliday {
res = append(res, utils.ResHolidays{
Date: startDate.Format("2006-01-02"),
HolidayNameCn: name,
})
}
startDate = startDate.AddDate(0, 0, 1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if err != nil {
return
}
}
// 获取IP归属地
func getIpLocation(ctx iris.Context) {
var ip string
if ctx.URLParam("ip") != "" {
ip = ctx.URLParam("ip")
} else {
ip = utils.GetRequestIp(ctx)
}
ipLocation, err := utils.GetIpLocation(ip)
if utils.ErrHandle(ctx, err) {
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", ipLocationData{
Ip: ip,
Location: ipLocation,
}))
if err != nil {
return
}
}
// 邮件发送
func sendEmail(ctx iris.Context) {
receiver := strings.Split(ctx.URLParam("receiver"), ";")
subject := ctx.URLParam("subject")
content := ctx.URLParam("content")
err := utils.SendEmail(receiver, subject, content)
if utils.ErrHandle(ctx, err) {
logrus.Errorln(err)
return
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "发送成功"))
if err != nil {
return
}
}
func getSudokuCheck(ctx iris.Context) {
}

View File

@ -0,0 +1,10 @@
package api
import "github.com/kataras/iris/v12"
func PublicApis(party iris.Party) {
party.Get("/holidays", getHolidays)
party.Get("/send_email", sendEmail)
party.Get("/get_ip_location", getIpLocation)
party.Get("/get_sudoku_check", getSudokuCheck)
}

View File

@ -0,0 +1,170 @@
package api
import (
"errors"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"strings"
)
func getSudokuList(ctx iris.Context) {
var resSudokuList resSudokuListType
var startingSudokuList []sudokuListType
var newSudokuList []model.Sudoku
db := database.GetInstance().GetMysqlDb()
if err := db.Where("id not in (?)", db.Table("sudoku_statuses").Distinct("sudoku_id").Where("username = ? and deleted_at is null", "admin")).Find(&newSudokuList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, v := range newSudokuList {
resSudokuList.New = append(resSudokuList.New, sudokuListType{Sudoku: v.Sudoku, SudokuId: v.ID, Complete: false})
}
queryId := db.Table("sudoku_statuses").Select("max(id)").Where("username = ? and deleted_at is null", "admin").Group("sudoku_id")
if queryId.Error != nil {
logrus.Errorln("sql执行失败", queryId.Error)
}
queryStatus := db.Table("sudoku_statuses").Where("id in (?)", queryId)
if queryStatus.Error != nil {
logrus.Errorln("sql执行失败", queryStatus.Error)
}
if err := db.Model(&model.Sudoku{}).Select("sudokus.sudoku, q.*").Joins("left join (?) q on sudokus.id = q.sudoku_id", queryStatus).Scan(&startingSudokuList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, v := range startingSudokuList {
if v.Complete {
resSudokuList.Complete = append(resSudokuList.Complete, v)
} else {
resSudokuList.Starting = append(resSudokuList.Starting, v)
}
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", resSudokuList))
if utils.ErrHandle(ctx, err) {
return
}
}
func addSudokuGame(ctx iris.Context) {
var sudokuParam addSudokuParam
var dbCheck model.Sudoku
var sudokuResult [9][9]string
err := ctx.ReadJSON(&sudokuParam)
if utils.ErrHandle(ctx, err) {
return
}
if sudokuParam.Result != "" {
sudokuResult, err = sudokuStringToList(sudokuParam.Result)
if utils.ErrHandle(ctx, err) {
return
}
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Where("sudoku = ?", sudokuParam.Sudoku).First(&dbCheck).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if !utils.DataIsNil(dbCheck) {
utils.ErrHandle(ctx, errors.New("棋盘已存在"))
return
}
err, r := utils.CheckSudoku(sudokuParam.Sudoku)
if utils.ErrHandle(ctx, err) {
return
}
if r.Data.Check || checkSudokuCompleted(sudokuResult) {
if r.Data.Check {
if err1 := db.Create(&model.Sudoku{Sudoku: sudokuParam.Sudoku, Username: "admin", Result: r.Data.Result}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
} else {
if err1 := db.Create(&model.Sudoku{Sudoku: sudokuParam.Sudoku, Username: "admin", Result: sudokuParam.Result}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
} else {
utils.ErrHandle(ctx, errors.New("检测题目无法完成,请上传解题结果"))
return
}
}
func sudokuStringToList(sudoku string) ([9][9]string, error) {
var res [9][9]string
sudokuRows := strings.Split(sudoku, ";")
if len(sudokuRows) != 9 {
return res, errors.New("棋盘格式错误")
}
for r, row := range sudokuRows {
sudokuCols := strings.Split(row, ",")
if len(sudokuCols) != 9 {
return res, errors.New("棋盘格式错误")
}
for c, col := range sudokuCols {
if len(col) > 1 || strings.Index("123456789", col) == -1 {
return res, errors.New("棋盘格式错误")
}
res[r][c] = col
}
}
return res, nil
}
func sudokuListToString(sudoku [9][9]string) string {
var res string
for r, _ := range sudoku {
var tmp string
for c, _ := range sudoku[r] {
if tmp == "" {
tmp = sudoku[r][c]
} else {
tmp += "," + sudoku[r][c]
}
}
if res == "" {
res = tmp
} else {
res += ";" + tmp
}
}
return res
}
// 检查题目是否已完成
func checkSudokuCompleted(sudoku [9][9]string) bool {
for r, _ := range sudoku {
for c, _ := range sudoku[r] {
if sudoku[r][c] == "" || !checkNum(r, c, sudoku) {
return false
}
}
}
return true
}
// 检查题目当前位置是否符合要求
func checkNum(r int, c int, sudoku [9][9]string) bool {
if sudoku[r][c] == "" {
return true
}
for i, n := range sudoku[r] {
if n == sudoku[r][c] && i != c {
return false
}
}
for i, _ := range sudoku {
if sudoku[i][c] == sudoku[r][c] && i != r {
return false
}
}
for row := (r % 3) * 3; row < (r%3)*3+2; row++ {
for col := (c % 3) * 3; col < (c%3)*3+2; col++ {
if sudoku[row][col] == sudoku[r][c] && row != r && col != c {
return false
}
}
}
return true
}

View File

@ -0,0 +1,10 @@
package api
import (
"github.com/kataras/iris/v12"
)
func Sudoku(party iris.Party) {
party.Get("/", getSudokuList)
party.Post("/", addSudokuGame)
}

View File

@ -0,0 +1,59 @@
package api
import (
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"strings"
)
func getSysIcons(ctx iris.Context) {
var icons []model.SysIcons
db := database.GetInstance().GetMysqlDb()
if err := db.Find(&icons).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", icons))
if utils.ErrHandle(ctx, err) {
return
}
}
func addSysIcons(ctx iris.Context) {
var params sysIconsParam
var icons []model.SysIcons
var sysIcons []model.SysIcons
err := ctx.ReadJSON(&params)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if err1 := db.Find(&sysIcons).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
for _, iconStr := range strings.Split(params.Icons, ",") {
icon := strings.Join([]string{"bi", iconStr}, "-")
if !checkIconExist(icon, sysIcons) {
icons = append(icons, model.SysIcons{Icon: icon})
sysIcons = append(sysIcons, model.SysIcons{Icon: icon})
}
}
if err1 := db.Create(&icons).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
func checkIconExist(icon string, sysIcons []model.SysIcons) bool {
for _, sysIcon := range sysIcons {
if sysIcon.Icon == icon {
return true
}
}
return false
}

View File

@ -0,0 +1,8 @@
package api
import "github.com/kataras/iris/v12"
func SysSettings(party iris.Party) {
party.Get("/icon", getSysIcons)
party.Post("/icon", addSysIcons)
}

View File

@ -0,0 +1,96 @@
package api
import (
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"main/utils"
"strconv"
"strings"
)
func getSystem(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
date := ctx.URLParam("date")
//username := "admin"
db := database.GetInstance().GetMysqlDb()
var systemList []resSystem
var ids []int
if err := db.Model(&model.SysInfo{}).Select("max(id)").Where("date = ? and username = ?", date, username.Username).Group("ip").Scan(&ids).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Model(&model.SysInfo{}).Where("id in (?)", ids).Find(&systemList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", systemList))
if utils.ErrHandle(ctx, err) {
return
}
}
// 获取当前系统信息
func getSysInfo(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
//username := "admin"
date := ctx.URLParam("date")
ip := ctx.URLParam("ip")
db := database.GetInstance().GetMysqlDb()
var sysInfoList []model.SysInfo
var res []resSysInfo
if err := db.Where("username = ? and date = ? and ip = ?", username.Username, date, ip).Find(&sysInfoList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
for _, sysInfo := range sysInfoList {
var diskList []resDisk
diskLists := strings.Split(sysInfo.DiskPoint, ",")
for i, disk := range diskLists {
if strings.Contains(disk, "docker") {
continue
}
diskPer, err := strconv.ParseFloat(strings.Split(sysInfo.DiskPer, ",")[i], 64)
if utils.ErrHandle(ctx, err) {
return
}
diskList = append(diskList, resDisk{
Point: disk,
Total: strings.Split(sysInfo.DiskTotal, ",")[i],
Used: strings.Split(sysInfo.DiskUsed, ",")[i],
Per: utils.Round(diskPer, 2),
})
}
res = append(res, resSysInfo{
Datetime: sysInfo.Datetime,
CpuPer: utils.Round(sysInfo.CpuPer, 2),
Mem: resMem{
MemPer: utils.Round(sysInfo.MemPer, 2),
MemUsed: sysInfo.MemUsed,
MemTotal: sysInfo.MemTotal,
},
Disk: diskList,
Net: resNet{
Sent: sysInfo.SentSpeed,
Rec: sysInfo.RecSpeed,
},
})
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", res))
if utils.ErrHandle(ctx, err) {
return
}
}
//func updateSysInfo(ctx iris.Context) {
// date := ctx.URLParam("date")
// crontab.UpdateSysInfo(date)
// err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", fmt.Sprintf("%s 日期数据同步完成", date)))
// if utils.ErrHandle(ctx, err) {
// return
// }
//}

View File

@ -0,0 +1,12 @@
package api
import (
"github.com/kataras/iris/v12"
"main/jwtSet"
)
func SysInfo(party iris.Party) {
party.Get("/server", jwtSet.Jwt.Serve, getSystem)
party.Get("/", jwtSet.Jwt.Serve, getSysInfo)
//party.Get("/update", updateSysInfo)
}

View File

@ -0,0 +1,178 @@
package api
import "time"
// user-----------------------------------------------------------------------------------------------
type result struct {
Date string
Password string
ConfirmCode string
UpdatedAt time.Time
Key string
AesKey string
}
// weather---------------------------------------------------------------------------------------------
type resWeather struct {
Status int `json:"status"`
Message string `json:"message"`
Data resData `json:"data"`
}
type resData struct {
Forecast24h resDate `json:"forecast_24h"`
}
type resDate struct {
D0 res24h `json:"1"`
D1 res24h `json:"2"`
}
type res24h struct {
Time string `json:"time"`
MaxDegree string `json:"max_degree"`
MinDegree string `json:"min_degree"`
DayWeather string `json:"day_weather"`
DayWindDirection string `json:"day_wind_direction"`
DayWindPower string `json:"day_wind_power"`
NightWeather string `json:"night_weather"`
NightWindPower string `json:"night_wind_power"`
NightWindDirection string `json:"night_wind_direction"`
}
type resLocation struct {
Data map[string]string `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
// backgammon-----------------------------------------------------------------------------------------------
type typeRoomStatus struct {
RoomId int `json:"room_id"`
Player string `json:"player"`
}
// file-----------------------------------------------------------------------------------------------------
type filesRes struct {
Dirs []string `json:"dirs"`
Files []fileItem `json:"files"`
}
type fileItem struct {
Name string `json:"name"`
Type string `json:"type"`
Size int64 `json:"size"`
}
type videoM3u8 struct {
Video bool `json:"video"`
M3u8 bool `json:"m3u8"`
}
// notes------------------------------------------------------------------------------------------------------
type noteParam struct {
ID uint `json:"id"`
Content string `json:"content"`
}
// sysInfo------------------------------------------------------------------------------------------------------
type resSysInfo struct {
Datetime string `json:"datetime"`
CpuPer float64 `json:"cpu_per"`
Mem resMem `json:"mem"`
Disk []resDisk `json:"disk"`
Net resNet `json:"net"`
}
type resMem struct {
MemTotal string `json:"mem_total"`
MemUsed string `json:"mem_used"`
MemPer float64 `json:"mem_per"`
}
type resDisk struct {
Point string `json:"point"`
Total string `json:"total"`
Used string `json:"used"`
Per float64 `json:"per"`
}
type resNet struct {
Sent string `json:"sent"`
Rec string `json:"rec"`
}
type resSystem struct {
Hostname string `json:"hostname"`
Ip string `json:"ip"`
}
type sysInfoIDs struct {
IDs []int `json:"ids"`
}
// yeb----------------------------------------------------------------------------------------------------------
type paramsBalance struct {
Card string `json:"card"`
Type bool `json:"type"`
Balance float64 `json:"balance"`
}
type paramSZBalance struct {
Card string `json:"card"`
Type bool `json:"type"` // 1-支出0-收入
Amount float64 `json:"amount"`
}
// 月余额
type dateLog struct {
Date string `json:"date"`
Duration string `json:"duration"`
Changes float64 `json:"changes"`
Balance float64 `json:"balance"`
Detail []cardLog `json:"detail"`
}
// 详情
type cardLog struct {
Card string `json:"card"`
Balance float64 `json:"balance"`
Changes float64 `json:"changes"`
}
// menus-----------------------------------------------------------------------------
type resMenu struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
Detail []subMenu `json:"detail"`
}
type subMenu struct {
MenuId string `json:"menu_id"`
Name string `json:"name"`
Icon string `json:"icon"`
Path string `json:"path"`
RouteOnly bool `json:"route_only"`
}
type sysIconsParam struct {
Icons string `json:"icons"`
}
// sudoku-----------------------------------------------------------------------------
type resSudokuListType struct {
New []sudokuListType `json:"new"`
Starting []sudokuListType `json:"starting"`
Complete []sudokuListType `json:"complete"`
}
type sudokuListType struct {
Sudoku string `json:"sudoku"`
SudokuId uint `json:"sudokuId"`
Username string `json:"username"`
Status string `json:"status"`
Complete bool `json:"complete"`
Id uint `json:"id"`
}
type addSudokuParam struct {
Sudoku string `json:"sudoku"`
Result string `json:"result"`
}
// public ------------------------------------------------------------------------------
type ipLocationData struct {
Ip string `json:"ip"`
Location string `json:"location"`
}

View File

@ -0,0 +1,365 @@
package api
import (
"errors"
"fmt"
"github.com/golang-jwt/jwt/v4"
"github.com/jakehl/goid"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/jwtSet"
"main/model"
"main/service/admin"
"main/utils"
"math/rand"
"strconv"
"strings"
"time"
)
// 返回加密后用户信息
func userinfo(ctx iris.Context) {
user := utils.GetLoginUser(ctx)
if utils.DataIsNil(user) {
return
}
if user.Email != "" {
user.Email = fmt.Sprintf("%s****%s", user.Email[0:2], user.Email[len(user.Email)-7:])
}
if user.Mobile != "" {
user.Mobile = fmt.Sprintf("%s****%s", user.Mobile[0:2], user.Mobile[len(user.Mobile)-4:])
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", user))
if utils.ErrHandle(ctx, err) {
return
}
}
// 更新用户信息
func updateUserinfo(ctx iris.Context) {
username := utils.GetLoginUser(ctx)
if utils.DataIsNil(username) {
return
}
var params model.Userinfo
err := ctx.ReadJSON(&params)
if utils.ErrHandle(ctx, err) {
return
}
db := database.GetInstance().GetMysqlDb()
if strings.Contains(params.Email, "*") {
params.Email = ""
}
if strings.Contains(params.Mobile, "*") {
params.Mobile = ""
}
if err1 := db.Model(&model.Userinfo{}).Where("username = ?", username.Username).Updates(params).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
for i, u := range utils.UserList {
if u.Username == username.Username {
utils.UserList[i] = params
}
}
utils.UpdateUserInfo()
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 用户登录
func login(ctx iris.Context) (string, error) {
username := ctx.URLParam("username")
password := ctx.URLParam("password")
confirmCode := ctx.URLParam("confirmCode")
auto := ctx.URLParam("auto")
var res result
db := database.GetInstance().GetMysqlDb()
if err := db.
Model(&model.User{}).
Select("users.password, users.confirm_code, users.updated_at, day_keys.key, day_keys.aes_key").
Joins("left join day_keys on day_keys.user = users.username and day_keys.date = users.date").
Where("users.username = ?", username).
Order("users.date desc").
Scan(&res).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if utils.DataIsNil(res) {
return "", errors.New("用户不存在")
}
rsaDePass, err := utils.RsaDecrypt(password, res.Key)
if err != nil {
return "", err
}
if confirmCode == "" {
aesDePass, err := utils.DecryptByAes(res.Password, []byte(res.AesKey))
if err != nil {
return "", err
}
//fmt.Println(string(aesDePass), rsaDePass)
if string(aesDePass) != rsaDePass {
return "", errors.New("用户信息错误")
}
} else if res.ConfirmCode != confirmCode {
return "", errors.New("验证码错误")
} else if res.ConfirmCode != "" && time.Now().After(res.UpdatedAt.Add(time.Minute*5)) {
return "", errors.New("验证码已过期")
}
priKeys, _ := utils.GetPrivateKeys(username, time.Now().Format("2006-01-02"))
newPwd, _ := utils.EncryptByAes([]byte(rsaDePass), []byte(priKeys.AesKey))
if err1 := db.
Model(&model.User{}).
Where("username = ?", username).
Updates(map[string]interface{}{
"password": newPwd,
"date": time.Now().Format("2006-01-02"),
"confirm_code": "",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
rand1 := rand.New(rand.NewSource(time.Now().UnixNano()))
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": username,
"iat": time.Now().Unix(),
"jti": strconv.Itoa(rand1.Int()),
"exp": time.Now().Add(2 * time.Hour).Unix(),
})
jwtKey := jwtSet.GetJwtKeys().Key
tokenString, err := token.SignedString([]byte(jwtKey))
if err != nil {
return "", err
}
ctx.SetCookieKV("is_login", "1", iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
ctx.SetCookieKV("token", tokenString, iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
ctx.SetCookieKV("loginTime", strconv.FormatInt(time.Now().UnixMilli(), 10), iris.CookieHTTPOnly(false))
if err1 := db.Create(&model.UserAction{
Username: username,
Action: "用户登录",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if err1 := db.Create(&model.JwtKeys{
Username: username,
Date: time.Now().Format("2006-01-02"),
Key: jwtKey,
Token: tokenString,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if auto == "true" {
deviceId := goid.NewV4UUID()
location := admin.GetIpLocation(utils.GetRequestIp(ctx))
ctx.SetCookieKV("deviceId", deviceId.String(), iris.CookieHTTPOnly(false))
if err1 := db.Create(&model.UserAutoLogin{
Username: username,
DeviceId: deviceId.String(),
Location: location,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
}
return tokenString, nil
}
// 用户注册
func register(ctx iris.Context) (string, error) {
username := ctx.URLParam("username")
password := ctx.URLParam("password")
priKeys, err := utils.GetPrivateKeys(username, time.Now().Format("2006-01-02"))
if err != nil {
return "", err
}
dePass, err := utils.RsaDecrypt(password, priKeys.Key)
if err != nil {
return "", err
}
enPass, err := utils.EncryptByAes([]byte(dePass), []byte(priKeys.AesKey))
if err != nil {
return "", err
}
db := database.GetInstance().GetMysqlDb()
var user []model.User
if err1 := db.Where("username = ?", username).Find(&user).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if len(user) > 0 {
err = errors.New("user exists")
return "", err
}
if err1 := db.Create(&model.User{
Username: username,
Password: enPass,
Date: time.Now().Format("2006-01-02"),
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if len(utils.UserList) == 0 {
if err1 := db.Create(&model.Userinfo{
Username: username,
Type: "admin",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
} else {
if err1 := db.Create(&model.Userinfo{
Username: username,
Type: "user",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
}
utils.UpdateUserInfo()
rand1 := rand.New(rand.NewSource(time.Now().UnixNano()))
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": username,
"iat": time.Now().Unix(),
"jti": strconv.Itoa(rand1.Int()),
"exp": time.Now().Add(2 * time.Hour).Unix(),
})
jwtKey := jwtSet.GetJwtKeys().Key
tokenString, err := token.SignedString([]byte(jwtKey))
if err != nil {
return "", err
}
ctx.SetCookieKV("is_login", "1", iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
ctx.SetCookieKV("token", tokenString, iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
ctx.SetCookieKV("loginTime", strconv.FormatInt(time.Now().UnixMilli(), 10), iris.CookieHTTPOnly(false))
if err1 := db.Create(&model.UserAction{
Username: username,
Action: "用户注册并登录",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if err1 := db.Create(&model.JwtKeys{
Username: username,
Date: time.Now().Format("2006-01-02"),
Key: jwtKey,
Token: tokenString,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
return tokenString, nil
}
// 退出登录
func logout(ctx iris.Context) {
db := database.GetInstance().GetMysqlDb()
username := utils.GetLoginUser(ctx)
auth := ctx.Values().Get("jwt")
deviceId := ctx.GetCookie("deviceId")
if auth == nil {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.SetErr(errors.New("未登录"))
return
}
if err := db.Where("token = ?", auth.(*jwt.Token).Raw).Delete(&model.JwtKeys{}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
ctx.RemoveCookie("is_login")
ctx.RemoveCookie("token")
if deviceId != "" {
ctx.RemoveCookie("deviceId")
if err := db.Where("device_id = ? and username = ?", deviceId, username).Delete(&model.UserAutoLogin{}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
if err := db.Create(&model.UserAction{
Username: username.Username,
Action: "用户注销登录",
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
if utils.ErrHandle(ctx, err) {
return
}
}
// 重置密码
func resetPwd(ctx iris.Context) {
username := ctx.URLParam("username")
//var user model.Userinfo
db := database.GetInstance().GetMysqlDb()
user := utils.GetUserInfo(username)
if utils.DataIsNil(user) {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("用户不存在"))
return
}
confirmCode := utils.NewKey(8)
if err := db.Model(&model.User{}).Where("username = ?", username).Updates(model.User{ConfirmCode: confirmCode}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
err := utils.SendEmail([]string{user.Email}, "密码重置", fmt.Sprintf("验证码为:%s\n您正在进行密码重置验证码5分钟内有效如非本人操作请忽略本邮件", confirmCode))
if utils.ErrHandle(ctx, err) {
return
}
if err1 := db.Create(&model.UserAction{
Username: username,
Action: "获取重置密码验证码",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", fmt.Sprintf("%s****%s", user.Email[0:2], user.Email[7:])))
if utils.ErrHandle(ctx, err) {
return
}
}
func autoLogin(ctx iris.Context) {
var user []model.UserAutoLogin
location := admin.GetIpLocation(utils.GetRequestIp(ctx))
deviceId := ctx.GetCookie("deviceId")
if deviceId == "" || location == "" {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "自动登录未设置", false))
if utils.ErrHandle(ctx, err) {
return
}
return
}
db := database.GetInstance().GetMysqlDb()
if err := db.Where("device_id = ? and location = ?", deviceId, location).Find(&user).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(user) == 0 {
err := ctx.JSON(utils.FormatRes(iris.StatusOK, "自动登录未设置", false))
if utils.ErrHandle(ctx, err) {
return
}
return
}
rand1 := rand.New(rand.NewSource(time.Now().UnixNano()))
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": user[0].Username,
"iat": time.Now().Unix(),
"jti": strconv.Itoa(rand1.Int()),
"exp": time.Now().Add(2 * time.Hour).Unix(),
})
jwtKey := jwtSet.GetJwtKeys().Key
tokenString, err := token.SignedString([]byte(jwtKey))
if utils.ErrHandle(ctx, err) {
return
}
ctx.SetCookieKV("is_login", "1", iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
ctx.SetCookieKV("token", tokenString, iris.CookieHTTPOnly(false), iris.CookieExpires(2*time.Hour))
if err1 := db.Create(&model.UserAction{
Username: user[0].Username,
Action: "用户自动登录",
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
if err1 := db.Create(&model.JwtKeys{
Username: user[0].Username,
Date: time.Now().Format("2006-01-02"),
Key: jwtKey,
Token: tokenString,
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", tokenString))
if utils.ErrHandle(ctx, err) {
return
}
}

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