Compare commits

...

No commits in common. "82bb1f1d68b76955149e2d1b83d4e2683a39b208" and "6c901e25544046ae024b8578c0159aed1a54e897" have entirely different histories.

118 changed files with 9674 additions and 5512 deletions

View File

@ -1,7 +0,0 @@
{
"plugins": [
["@babel/plugin-syntax-dynamic-import"
]
]
}

2
.env
View File

@ -1,2 +0,0 @@
NODE_ENV = 'production'
VUE_APP_BASE_URL = '/dist/admin/index.html#'

View File

@ -1,2 +0,0 @@
NODE_ENV = 'production'
VUE_APP_BASE_URL = './'

View File

@ -1,26 +0,0 @@
/*
* @Author: your name
* @Date: 2021-11-06 16:47:51
* @LastEditTime: 2021-11-06 16:52:07
* @LastEditors: your name
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \background-front\.eslintrc.js
*/
module.exports = {
"env": {
"browser": true
},
"extends": [
"eslint:recommended",
"plugin:vue/essential"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"vue"
],
"rules": {
}
};

41
.gitignore vendored
View File

@ -1,23 +1,20 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
glide.yaml
api_user.exe
user.exe
background.exe
backgroun.exe
user.yaml
pem/client-key.pem
pem/client-cert.pem
pem/ca.pem
id_rsa
package-lock.json
background
image/
deploy.bat
docbackground.exe
__debug_bin
11.json
test/pem/ca.pem
test/pem/client-cert.pem
test/pem/client-key.pem
id_rsa_117

13
.idea/background.iml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true">
<buildTags>
<option name="cgo" value="NO" />
</buildTags>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/background.iml" filepath="$PROJECT_DIR$/.idea/background.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

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

176
.idea/workspace.xml Normal file
View File

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="7cf7b6b3-0082-44ef-bb0f-bfcc57e19eb1" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/fork.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<<<<<<< HEAD
=======
<change beforePath="$PROJECT_DIR$/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/main.go" afterDir="false" />
>>>>>>> aeb0b55a434d20bb6af252ba0528414a00fe60d8
</list>
<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="DatabaseView">
<option name="SHOW_INTERMEDIATE" value="true" />
<option name="GROUP_DATA_SOURCES" value="true" />
<option name="GROUP_SCHEMA" value="true" />
<option name="GROUP_CONTENTS" value="false" />
<option name="SORT_POSITIONED" value="false" />
<option name="SHOW_EMPTY_GROUPS" value="false" />
<option name="AUTO_SCROLL_FROM_SOURCE" value="false" />
<option name="HIDDEN_KINDS">
<set />
</option>
<expand />
<select />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Go File" />
</list>
</option>
</component>
<<<<<<< HEAD
<component name="GOROOT" path="C:\Go" />
=======
<component name="GOROOT" path="$PROJECT_DIR$/../../../../Program Files/go" />
>>>>>>> aeb0b55a434d20bb6af252ba0528414a00fe60d8
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectId" id="1OeBjD7R4KFQzfWAqpMf9jlmzxr" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="DefaultGoTemplateProperty" value="Go File" />
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="configurable.Global.GOPATH.is.expanded" value="true" />
<property name="configurable.Module.GOPATH.is.expanded" value="false" />
<property name="configurable.Project.GOPATH.is.expanded" value="true" />
<property name="go.import.settings.migrated" value="true" />
<property name="go.sdk.automatically.set" value="true" />
<<<<<<< HEAD
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="restartRequiresConfirmation" value="false" />
<property name="settings.editor.selected.configurable" value="vcs.Git" />
=======
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../gobase" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="settings.editor.selected.configurable" value="go.sdk" />
>>>>>>> aeb0b55a434d20bb6af252ba0528414a00fe60d8
</component>
<component name="RunManager" selected="Go Build.background">
<configuration name="background" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="background" />
<working_directory value="$PROJECT_DIR$/" />
<envs>
<env name="GOOS" value="windows" />
<env name="GOARCH" value="amd64" />
</envs>
<kind value="FILE" />
<filePath value="$PROJECT_DIR$/main.go" />
<output_directory value="$PROJECT_DIR$/" />
<method v="2" />
</configuration>
<configuration name="fork2" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true">
<module name="background" />
<working_directory value="$PROJECT_DIR$/" />
<parameters value="background.exe" />
<kind value="FILE" />
<filePath value="$PROJECT_DIR$/fork.go" />
<package value="background" />
<directory value="$PROJECT_DIR$/" />
<output_directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Go Build.background" />
<item itemvalue="Go Build.fork2" />
</list>
<recent_temporary>
<list>
<item itemvalue="Go Build.fork2" />
</list>
</recent_temporary>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="2" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="WindowStateProjectService">
<state x="767" y="429" key="#Go_Modules" timestamp="1595431702688">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state x="767" y="429" key="#Go_Modules/0.40.2048.1112@0.40.2048.1112" timestamp="1595431702688" />
<state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1595778748175">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.40.2048.1112@0.40.2048.1112" timestamp="1595778748175" />
<state x="805" y="351" key="FileChooserDialogImpl" timestamp="1595857317209">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state x="805" y="351" key="FileChooserDialogImpl/0.40.2048.1112@0.40.2048.1112" timestamp="1595857317209" />
<state width="2005" height="305" key="GridCell.Tab.0.bottom" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="305" key="GridCell.Tab.0.bottom/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.center" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="305" key="GridCell.Tab.0.center/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.left" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="305" key="GridCell.Tab.0.left/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.right" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="305" key="GridCell.Tab.0.right/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="376" key="GridCell.Tab.1.bottom" timestamp="1595433941254">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="376" key="GridCell.Tab.1.bottom/0.40.2048.1112@0.40.2048.1112" timestamp="1595433941254" />
<state width="2005" height="376" key="GridCell.Tab.1.center" timestamp="1595433941254">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="376" key="GridCell.Tab.1.center/0.40.2048.1112@0.40.2048.1112" timestamp="1595433941254" />
<state width="2005" height="376" key="GridCell.Tab.1.left" timestamp="1595433941254">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="376" key="GridCell.Tab.1.left/0.40.2048.1112@0.40.2048.1112" timestamp="1595433941254" />
<state width="2005" height="376" key="GridCell.Tab.1.right" timestamp="1595433941254">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state width="2005" height="376" key="GridCell.Tab.1.right/0.40.2048.1112@0.40.2048.1112" timestamp="1595433941254" />
<state x="526" y="240" key="SettingsEditor" timestamp="1595432383541">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state x="526" y="240" key="SettingsEditor/0.40.2048.1112@0.40.2048.1112" timestamp="1595432383541" />
<state x="687" y="283" width="672" height="678" key="search.everywhere.popup" timestamp="1595757093391">
<screen x="0" y="40" width="2048" height="1112" />
</state>
<state x="687" y="283" width="672" height="678" key="search.everywhere.popup/0.40.2048.1112@0.40.2048.1112" timestamp="1595757093391" />
</component>
</project>

18
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceRoot}/main.go",
"env": {},
"args": [],
"cwd":"${workspaceRoot}/",
}
]
}

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
"C_Cpp.intelliSenseEngineFallback": "enabled"
}

49
11.yaml Normal file
View File

@ -0,0 +1,49 @@
listen_api: 4596
runmode: debug
max_conn: 121
logs:
dir: /var/log/user
file: user.log
level: 1
savefile: false
redis1:
addr: 49.235.25.67:16379
password: ~
db: 1
mysql:
addr: 49.235.25.67
user: caiyu
password: 12345678
db: background
max_open: 100
MaxIdle: 99
elasticsearch:
address: http://hyrtc.net:9200
mysql1:
addr: 49.235.25.67
user: caiyu
password: 12345678
db: background
max_open: 100
MaxIdle: 99
mongo:
addr: 49.235.25.67
port: 27017
user: root
password: root
db: test
max_open: 100
MaxIdle: 99
ws_server_conf:
type: gateway
id: 1
ipadress: :9850
zkserver:
- "49.235.25.67
ca_cert: ""
client_cert: ""
client_key: ""
test_arr:
- 1
- 23

121
README.md
View File

@ -1,40 +1,95 @@
### 程序员的个人博客后台前端界面
本博客系统设计目标针程序员群体,提供了传统的文章管理,新增了个人时间管理,计划管理管理等功能,此外代码,数据库设计全部开源。
# background
基于golang gin 博客系统后台http接口,提供了简易可用的博客系统后台api服务设计文档全面。</br>
</br>前台展示界面git地址: https://gitee.com/290198252/api </br>
前台展示界面git地址: https://gitee.com/290198252/api
</br>后台管理后端接口的git地址: https://gitee.com/290198252/background </br>
</br>后台管理前端界面的git地址: https://gitee.com/290198252/background-front</br>
#### 介绍
开源的后台管理前后端
后端采用go+gin+ redis
前端采用vue+iview框架
#### 如何使用
本后台接口提供了完备的文档,可以搭配上面提供的前台,后台前端系统,同时也可以在此基础上搭建自己的前台系统。</br>
数据表位于[background.sql](https://gitee.com/290198252/background/blob/master/background.sql)</br>
## 设计目标
大部分团队协同软件侧重于团队人员的管理功能,本项目既提供了传统博客方面的接口,同时提供了丰富的个人管理的功能。</br>
现有功能:</br>
- 简单鉴权:
账号密码登录
- 文章(公有文章)管理>:
1. 文章分3级管理。
2. 提供图片上传下载接口富文本能力。
- 备忘管(私有文章)管理:
- 个人管理相关功能:
1. 每日时间管理,生成周报表,月报表的能力。
2. 代办事项管理。
3. 个人状态,每日睡眠周期记录,每日进食记录,生成月/周报表。
后台管理后端接口的git地址: https://gitee.com/290198252/background
- 相关辅助接口
图像上传等返回下载图像的url,为文章提供富文本能力。
## 传统博客板块
### 文章管理
基于mysql实现功能</br>
1. 文章创建
2. 文章更新
3. 文章删除
4. 文章查询
5. 文章所属二级分组管理
文章结构表:</br>
|字段名称|字段类型|字段说明|是否主键|
|-|-|-|-|
|id|int(11)||true|
|title|varchar(255)||false|
|type|int(11)||false|
|content|longblob||false|
|author|varchar(255)||false|
|create_time|datetime(0)||false|
|update_time|datetime(0)||false|
|delete_time|datetime(0)||false|
|version|float(255,||false|
|is_public|int(1)||false|
|deleted|int(1)||false|
|origin_url|varchar(255)||false|
文章一级分组结构表:</br>
|字段名称|字段类型|字段说明|是否主键|
|-|-|-|-|
|id|int(11)||true|
|type_name|varchar(255)||false|
|group|int(11)||false|
## 个人管理板块
传统的teambition等项目管理工具的问题在于将自己的定位赋予了项目管理者的角色,可以给自己分配任务,也可以给他人分配任务,这样设计的目的大部分是为了企业项目管理角色服务,而不是为了普通程序员服务,本后台服务设计的思路是基于每天固定工作时间的管理,以时间为管理单位而不是以项目的具体事项为管理单位,更贴近普通人的管理思维,毕竟普通人只需要管理好自己,也就是计划和时间。
- 代办计划的管理。
- 每天工作时间管理。
- 周/月统计
后台管理前端界面的git地址: https://gitee.com/290198252/background-front
### 睡眠记录管理
这里参照了R90科学睡眠方法建议使用者使用智能手环记录自己的
### 计划管理
计划即是未做的事项。
### 时间管理
前台采样php 语言编写后台接口采用golang编程后台界面采用 js + vue框架编程。
存储方面使用的是 mysql + redis + elasticsearch。
本系统经过简单修改,可以修改为公司文档管理系统和人员任务管理系统。
### 怎么使用
部署npm run alpha
单机测试: npm run serve
### 实现功能
注意单机测试情况下和服务器的跨域请求
现有功能:
#### 简单用户认证
#### 用户管理
![image.png](https://www.testingcloud.club/sapi/api/image_download/f1d2f2c5-814c-11eb-8238-525400dc6cec.png)
#### 文章管理
![image.png](https://www.testingcloud.club/sapi/api/image_download/a5f73ebf-814c-11eb-8238-525400dc6cec.png)
#### 文章修改
![image.png](https://www.testingcloud.club/sapi/api/image_download/a5f73ebf-814c-11eb-8238-525400dc6cec.png)
#### 每日时间管理
![image.png](https://www.testingcloud.club/sapi/api/image_download/66ebb116-744c-11eb-80c3-525400dc6cec.png)
#### 待办事项管理
![image.png](https://www.testingcloud.club/sapi/api/image_download/fa818b24-80eb-11eb-93e9-525400dc6cec.png)
#### 完成计划管理/统计
#### 时间周月统计
![image.png](https://www.testingcloud.club/sapi/api/image_download/7cdfd098-7c99-11eb-93e9-525400dc6cec.png)
- 天时间线管理。
- 每日计划时间统计。
- 计划的实施时间。
时间消耗表格字段说明: </br>
|字段名称|字段类型|字段说明|是否主键|
|-|-|-|-|
|id|int(11)||true|
|start_time|datetime(0)||false|
|end_time|datetime(0)||false|
|date|date||false|
|content|varchar(255)||false|
|type|int(11)||false|

View File

@ -1,80 +0,0 @@
/*
* @Author: your name
* @Date: 2019-05-23 22:39:12
* @LastEditTime: 2021-08-08 22:59:30
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \background-front\Vue.config.js
*/
// vue.config.js
const CompressionPlugin = require("compression-webpack-plugin")
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
// 修改的配置
// 部署应用时的基本 URL。默认情况下
//如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。
//则设置 baseUrl 为 /my-app/
publicPath:process.env.NODE_ENV === 'production'
? './'
: '/',
devServer: {
host:"127.0.0.1",
port:8080,
useLocalIp: true,
//proxy: 'http://127.0.0.1:8080',
},
configureWebpack: config => {
console.log("process.env.NODE_ENV: ",process.env.NODE_ENV )
if (process.env.NODE_ENV === 'production') {
// 代码压缩
config.plugins.push( new UglifyJsPlugin({
uglifyOptions: { //生产环境自动删除
compress: {
drop_debugger: true,
drop_console: true,
pure_funcs: ['console.log']
}
},
sourceMap: false,
parallel: true }
)
)
}
}
,
chainWebpack: config => {
// GraphQL Loader
config.module
.rule('graphql')
.test(/\.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end();
config.output.filename('[name].bu.js');
config.output.chunkFilename ('[name].module.js');
config.optimization.splitChunks({
chunks: 'all'
});
config.entry('main').add('babel-polyfill')
// 开启图片压缩
config.module.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({ bypassOnDebug: true })
// 开启js、css压缩
if (process.env.NODE_ENV === 'production') {
config.plugin('compressionPlugin')
.use(new CompressionPlugin({
test:/\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false // 不删除源文件
}))
}
},
transpileDependencies: [
'biyi-admin', // 指定对第三方依赖包进行babel-polyfill处理
]
// 为开发环境修改配置...
}

View File

@ -1,13 +0,0 @@
module.exports = {
presets: ["@vue/app"],
plugins: [
[
"import",
{
libraryName: "element-ui",
libraryDirectory: "src/components"
},
"transform-runtime"
]
]
};

346
background.sql Normal file
View File

@ -0,0 +1,346 @@
/*
SQLyog v12.2.6 (64 bit)
MySQL - 5.7.23-0ubuntu0.16.04.1-log : Database - background
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`background` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;
USE `background`;
/*Table structure for table `book` */
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`author` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`tag` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`content` blob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `bugs` */
DROP TABLE IF EXISTS `bugs`;
CREATE TABLE `bugs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` int(11) DEFAULT NULL,
`type_char` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`platform` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`solution` blob,
`desc` blob,
`associate` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `doc` */
DROP TABLE IF EXISTS `doc`;
CREATE TABLE `doc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`content` longblob,
`author` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`delete_time` datetime DEFAULT NULL,
`version` int(11) DEFAULT '0',
`is_public` int(1) unsigned zerofill DEFAULT '0',
`deleted` int(1) DEFAULT '0',
`origin_url` varchar(255) DEFAULT NULL,
`es_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8;
/*Table structure for table `doc_comment` */
DROP TABLE IF EXISTS `doc_comment`;
CREATE TABLE `doc_comment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`doc_id` int(11) DEFAULT NULL,
`child_id` int(11) DEFAULT NULL,
`content` varchar(512) COLLATE utf8_unicode_ci NOT NULL,
`time` datetime DEFAULT NULL,
`author` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `doc_copy2` */
DROP TABLE IF EXISTS `doc_copy2`;
CREATE TABLE `doc_copy2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`content` longblob,
`author` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`delete_time` datetime DEFAULT NULL,
`is_public` int(1) unsigned zerofill DEFAULT '0',
`deleted` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=351 DEFAULT CHARSET=utf8;
/*Table structure for table `doc_group` */
DROP TABLE IF EXISTS `doc_group`;
CREATE TABLE `doc_group` (
`int` int(11) DEFAULT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '文章分组'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `doc_group_type` */
DROP TABLE IF EXISTS `doc_group_type`;
CREATE TABLE `doc_group_type` (
`int` int(11) NOT NULL AUTO_INCREMENT,
`type_id` int(11) DEFAULT NULL,
`group_id` int(11) DEFAULT NULL,
PRIMARY KEY (`int`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `doc_template` */
DROP TABLE IF EXISTS `doc_template`;
CREATE TABLE `doc_template` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` blob COMMENT '内容',
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '模板名字',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `doc_type` */
DROP TABLE IF EXISTS `doc_type`;
CREATE TABLE `doc_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`group` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC;
/*Table structure for table `files` */
DROP TABLE IF EXISTS `files`;
CREATE TABLE `files` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`filename` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`size` int(11) DEFAULT NULL,
`types` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `greate_word` */
DROP TABLE IF EXISTS `greate_word`;
CREATE TABLE `greate_word` (
`id` int(14) NOT NULL,
`content` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `group` */
DROP TABLE IF EXISTS `group`;
CREATE TABLE `group` (
`group_id` int(11) NOT NULL,
`group_creator` int(11) DEFAULT NULL,
`group_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '权限组名字',
`group_type` int(11) DEFAULT NULL COMMENT '权限组具体权限',
PRIMARY KEY (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `memo` */
DROP TABLE IF EXISTS `memo`;
CREATE TABLE `memo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`content` blob COMMENT '内容',
`delete` int(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `permission` */
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '权限名字',
`level` int(11) DEFAULT NULL COMMENT '权限级别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `plan` */
DROP TABLE IF EXISTS `plan`;
CREATE TABLE `plan` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start_time` datetime DEFAULT NULL,
`end_time` datetime DEFAULT NULL,
`date` date DEFAULT NULL,
`content` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`type` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `plan_type` */
DROP TABLE IF EXISTS `plan_type`;
CREATE TABLE `plan_type` (
`id` int(11) NOT NULL,
`type_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `project` */
DROP TABLE IF EXISTS `project`;
CREATE TABLE `project` (
`id` int(13) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`content` longblob,
`contact_info` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `read_history` */
DROP TABLE IF EXISTS `read_history`;
CREATE TABLE `read_history` (
`id` int(11) NOT NULL,
`read_book` int(11) DEFAULT NULL COMMENT '阅读的书籍id',
`read_learn` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '学习到的知识',
`read_page` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '页数',
`read_time` datetime DEFAULT NULL COMMENT '阅读时间',
`read_pos` int(11) DEFAULT NULL COMMENT '阅读位置',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `role` */
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名字',
`creator_id` int(11) DEFAULT NULL COMMENT '创建者',
`creator_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '创建者名字',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `role_permission` */
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) DEFAULT NULL COMMENT ' 角色id',
`permision_id` int(11) DEFAULT NULL COMMENT '权限id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `sys_position` */
DROP TABLE IF EXISTS `sys_position`;
CREATE TABLE `sys_position` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`area_name` varchar(255) DEFAULT NULL COMMENT '地区名称',
`area_code` int(11) DEFAULT NULL COMMENT '地区编码',
`city_code` varchar(11) DEFAULT NULL COMMENT '城市编码',
`level` tinyint(1) DEFAULT NULL COMMENT '地区等级',
`area_index` varchar(255) DEFAULT NULL COMMENT '地区索引',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3537 DEFAULT CHARSET=utf8mb4;
/*Table structure for table `undo` */
DROP TABLE IF EXISTS `undo`;
CREATE TABLE `undo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(512) DEFAULT NULL,
`spend_time` int(11) DEFAULT NULL,
`level` int(11) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`parent` int(11) DEFAULT NULL,
`done` int(11) DEFAULT NULL,
`done_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
/*Table structure for table `user_permissions` */
DROP TABLE IF EXISTS `user_permissions`;
CREATE TABLE `user_permissions` (
`id` int(11) NOT NULL,
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`permission_id` int(11) DEFAULT NULL COMMENT '允许的操作id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `users` */
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(16) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_pwd` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`update_date` datetime DEFAULT NULL,
`display_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`email_address` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`tel` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`avatar` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Table structure for table `xmjobcnt` */
DROP TABLE IF EXISTS `xmjobcnt`;
CREATE TABLE `xmjobcnt` (
`timestamp` timestamp(6) NULL DEFAULT NULL,
`jobcnt` int(14) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

27
c@192.168.0.101 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxfs9xpGkF/tF7eCrkTI73CDA1VW/iIAR6/fOEPKlDsDcRKMR
uwb3rVaWrbTTG9doCjiAI7xtwuP0N9oka4N8nYbywACoWNTzQn4+V302yKIA/jiU
sSe1dNofNxlY1QSz/lu/D+zeJ3qHdelicRJsQUSh150ug5gJadF3zYfhotix7K3i
sLhpm+HQ5mbRk5b4AypXMqEB6M2cb1iTZYtKBmDMh6ZzOdiWg6ohjlmKwq7oeJWQ
6oXDmT3jChbUMhAmQ4AEi8f9555lw6nk0MzZXhMH+9mt1XwU6klt8+Rwz4f2t9Ob
ST/8U+oWMrCB1jO14J/s+c3ymMqsIbSccVtNdwIDAQABAoIBADYM1Vy0vjvd2cWL
pMtLD5SVTI/xjQzTChGF4bg2xmE0ve3vJxQMXunvzcs2prvfHwRLUJBxDPY8DZyB
7Zd8mjTXdsZ8Z3l5CcCJfrOb96zmraa6A74pvRxdwE/ml53wXsN+gLb0T+IvTXQf
d0SvZuaauiSHQP+kLk25Zh+yjSNL0qHJxFRSnAPjAXGLpgkTAFCC4KegliDdhpRb
c9taytlwet3KyB7d6MzqY5+UuMNLHkWqZsb1lOEjSRjdRyYuMd41srbw+Of6+5iK
RA1C6hwshhSgiTV9qNVcO5xykGsdk+JNsp5pUoaygUkxn47gMoPBk8ZwpwtzKbWQ
7r9NbsECgYEA6j4JyhbVaS97HaWLIYJlhe4Gxi6jfBo4ZhbzzK800/8iB2iHGWa+
8qxhQes8mkoGj9XtDVwwlgM6xKnhEysfDSZXpO6pPdxy1f3wnrukGx7jNgVcL8F2
c1K6Zda8HiRqe8Fb6PGqvxRZAwfZmkuG+N5phFR3rSRSEvVxdH5p118CgYEA2F73
y+/sCh4Bx9ld1wgxXlgrY/7DsWWuWF8eNKwrcrScgxmpbM1ZDuHTth2VzxrMYVLP
QPmyAtoPGv85eVKkEBC+mFJhFaZFb8lNfzUNZSYyImo70h+ZXyjMiuFC7G1yirQO
NFCooKkWmRheehs/O6oS0SbY9/YDbWE4vDwGuOkCgYAf9A6JzsuV6bA1vxtXmt4W
gv3RkxMiHsGKy56+UTg3oxoVQKENSgLKP9GUmG5P7cEvZdNMe0L1c8NUiIf3gW5e
8NgL27KiiavwnQ9x187vFCuSdvC4Yv+xg5uBwOUwh28vKpVLFYxhPHlX/H4mmh7z
XAOw1YTtzYKUq36qkYQGqQKBgQCpUIdwGusGb7zM+peoMU0QmsY5lZ7lLsBjfutQ
JHpLZHIlVOtzrK1ILAdTt4sHad0NO5PbMInQGXtAkQAUpEqmF7RN1gkKu/YSJ+Bw
7r7wrBcHP0JYh0mpYW/OLcAE6xB64bNL1OJf9nEslBk6TCALPGdFK7UVNHoyGaYg
BojsIQKBgAWqp6p8VF1Hp7pIswCnWN5YrmRlwIEANBLNgdk53UpXlIjZracoRqTe
LSINSpTgBgEe5FHPqa9Yxu0rS7ievLlGfVNscXtUaW1YiisU0y7iUjvxiW0u8afX
elQGUJgoAa9MPQFNJ3cNVqzSLfbhCRANc0zzqf5d2lNPPWgfg6R+
-----END RSA PRIVATE KEY-----

13
camelcase/swagger.json Normal file
View File

@ -0,0 +1,13 @@
{
"swagger": "2.0",
"info": {
"description": "{{.Description}}",
"title": "大厅功能api",
"contact": {},
"license": {},
"version": "1.0"
},
"host": "localhost:8080",
"basePath": "/api/v1",
"paths": {}
}

10
camelcase/swagger.yaml Normal file
View File

@ -0,0 +1,10 @@
basePath: /api/v1
host: localhost:8080
info:
contact: {}
description: '{{.Description}}'
license: {}
title: 大厅功能api
version: "1.0"
paths: {}
swagger: "2.0"

153
config/config.go Normal file
View File

@ -0,0 +1,153 @@
package config
import (
"log"
"os"
"runtime"
wsConf "tcptemplate/config"
"gopkg.in/yaml.v2"
)
var ostype = runtime.GOOS
var conf ConfAPI
type ConfAPI struct {
ListenSvr int `yaml:"listen_svr"` // 服务监听端口
ListenApi int `yaml:"listen_api"` // 服务监听端口
RunMode string `yaml:"runmode"` // 服务运行模式
MaxConn int `yaml:"max_conn"`
Logs LogConfig `yaml:"logs"` // 日志
Redis1 EntityRedis `yaml:"redis1"`
Mysql MysqlConfig `yaml:"mysql"` // 认证配置
ElasticSerach ElasticSearch `yaml:"elasticsearch"`
Mysql1 MysqlConfig `yaml:"mysql1"` // 认证配置
MongoConf MongoConfig `yaml:"mongo"`
WsServerConf wsConf.Config `yaml:"ws_server_conf"`
CaCert string `yaml:"ca_cert"`
ClientCert string `yaml:"client_cert"`
ClientKey string `yaml:"client_key"'`
init bool
}
type ElasticSearch struct{
Address string `yaml:"address"`
User string `yaml:"user"`
Password string `yaml:"password"`
}
type EntityRedis struct {
Addr string `yaml:"addr"`
Pwd string `yaml:"password"`
DB int `yaml:"db"`
PoolSize int `yaml:"poolsize"`
}
type RedisConfig struct {
Addr string `yaml:"addr"`
Pwd string `yaml:"password"`
DB int64 `yaml:"db"`
}
type LogConfig struct {
Dir string `yaml:"dir"`
File string `yaml:"file"`
Level int `yaml:"level"`
SaveFile bool `yaml:"savefile"`
}
type MysqlConfig struct {
Addr string `yaml:"addr"`
UserName string `yaml:"user"`
Password string `yaml:"password"`
Db string `yaml:"db"`
MaxOpen int `yaml:"max_open"`
MaxIdle int `yaml:"max_idle"`
}
// mongodb://myuser:mypass@localhost:40001
type MongoConfig struct {
Addr string `yaml:"addr"`
Port int64 `yaml:"port"`
UserName string `yaml:"user"`
Password string `yaml:"password"`
Db string `yaml:"db"`
MaxOpen int `yaml:"max_open"`
MaxIdle int `yaml:"max_idle"`
}
var gConf ConfAPI
func ApiConfig() ConfAPI{
return gConf
}
func Init(path string) error {
file, e := os.Open(path)
if nil != e {
log.Println(e.Error())
return e
}
stat, _ := file.Stat()
filec := make([]byte, stat.Size())
log.Print(filec)
file.Read(filec)
e = yaml.Unmarshal(filec, &gConf)
if nil != e {
log.Println(e.Error())
}
gConf.init = true
log.Print(gConf)
return nil
}
func GetPort() int {
if gConf.init {
return gConf.ListenApi
} else {
return 8001
}
}
func GetMysqlConfig() *MysqlConfig {
if gConf.init {
return &gConf.Mysql
} else {
return nil
}
}
func GetMysqlBlogConfig() *MysqlConfig {
if gConf.init {
return &gConf.Mysql1
} else {
return nil
}
}
func GETCaCert() string{
return gConf.CaCert
}
func GetMongoDBConfig() *MongoConfig{
if gConf.init{
return &gConf.MongoConf
} else {
return nil
}
}
func GetRedis1() *EntityRedis {
if gConf.init {
return &gConf.Redis1
} else {
return nil
}
}
func GetLogConfig() *LogConfig {
if gConf.init {
return &gConf.Logs
} else {
return nil
}
}
func GetElkConfig() *ElasticSearch{
if gConf.init{
return &gConf.ElasticSerach
}else {
return nil
}
}

59
config/redisConf.go Normal file
View File

@ -0,0 +1,59 @@
/*
* @Author: your name
* @Date: 2019-04-07 11:19:50
* @LastEditTime: 2021-07-17 22:23:23
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \background\config\redisConf.go
*/
package config
import (
"background/logs"
"fmt"
"github.com/pkg/errors"
"gopkg.in/redis.v4"
)
var (
gRedis1 *redis.Client
)
func initRedis(addr string, pwd string, db int, coon int) (*redis.Client, error) {
red := redis.NewClient(&redis.Options{
Addr: addr,
Password: pwd,
DB: db,
PoolSize: coon,
})
_, err := red.Ping().Result()
if nil != err {
red.Close()
return nil, errors.New(fmt.Sprintf("fail to ping redis,addr :%s , pwd :%s ,DB :%d", addr, pwd, db))
}
return red, nil
}
func InitRedis() error {
redisConf := GetRedis1()
if nil == redisConf {
return errors.New("Error Config Redis")
} else {
var e error
gRedis1, e = initRedis(GetRedis1().Addr, GetRedis1().Pwd, GetRedis1().DB, GetRedis1().PoolSize)
if nil != e {
logs.Error(e.Error())
return e
}
}
return nil
}
func RedisOne() *redis.Client {
return gRedis1
}

21
const/const.go Normal file
View File

@ -0,0 +1,21 @@
package _const
var RespCode map[int]string
const (
RESP_ERR_COMON = 101
RESP_ERR_OK = 0
)
func init() {
RespCode[RESP_ERR_OK] = "OK"
RespCode[RESP_ERR_COMON] = "Err"
}
func M(key int) string {
v, ok := RespCode[key]
if ok {
return v
} else {
return ""
}
}

1210
controller/blog.go Normal file

File diff suppressed because it is too large Load Diff

7
controller/data.go Normal file
View File

@ -0,0 +1,7 @@
package controller
type RespBase struct {
Msg string
Status int
Data interface{}
}

421
controller/file.go Normal file
View File

@ -0,0 +1,421 @@
package controller
import (
"background/db"
"background/model"
"background/utils"
"fmt"
"image"
"image/color"
"image/jpeg"
"io/ioutil"
"log"
"math"
"net/http"
"os"
"strconv"
"strings"
"github.com/disintegration/imaging"
"github.com/gin-gonic/gin"
json "github.com/json-iterator/go"
"github.com/nfnt/resize"
uuid "github.com/satori/go.uuid"
// "github.com/nfnt/resize"
// "image/jpeg"
"image/gif"
// "strings"
)
type FileController struct {
}
func (this *FileController) OnUploadDoc(c *gin.Context) {
// uid, e := uuid.NewV1()
// if nil != e {
// log.Print(e.Error())
// return
// }
// imgtype := c.Query("type")
// log.Print(imgtype)
// file, _, err := c.Request.FormFile("doc")
// if nil != err || nil == file {
// log.Print(err.Error())
// return
// }
// img, name, err := image.Decode(file)
// if nil != err {
// log.Print(err.Error())
// return
// }
// dx := img.Bounds().Dx()
// // resize to width 1000 using Lanczos resampling
// // and preserve aspect ratio
// if dx > 800 {
// dx = dx / 2
// }
// m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)
// datout, err := os.Create("image/" + uid.String() + "." + name)
// defer datout.Close()
// if err != nil {
// log.Fatal(err)
// }
// jpeg.Encode(datout, m, nil)
// c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})
}
func (this *FileController) OnUpload(c *gin.Context) {
uid, e := uuid.NewV1()
if nil != e {
log.Print(e.Error())
return
}
imgtype := c.Query("type")
log.Print(imgtype)
file, _, err := c.Request.FormFile("image")
if nil != err || nil == file {
log.Print(err.Error())
return
}
if imgtype == "gif" {
allgifs, er := gif.DecodeAll(file)
if nil != er {
log.Print("decode error", er.Error())
return
}
datout, err := os.Create("image/" + uid.String() + ".gif")
defer datout.Close()
if err != nil {
log.Fatal(err)
return
}
gif.EncodeAll(datout, allgifs)
c.JSON(200, map[string]interface{}{"url": uid.String() + ".gif"})
} else {
img, name, err := image.Decode(file)
if nil != err {
log.Print(err.Error())
return
}
dx := img.Bounds().Dx()
// resize to width 1000 using Lanczos resampling
// and preserve aspect ratio
if dx > 800 {
dx = dx / 2
}
m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)
datout, err := os.Create("image/" + uid.String() + "." + name)
defer datout.Close()
if err != nil {
log.Fatal(err)
}
jpeg.Encode(datout, m, nil)
c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})
}
}
func (this *FileController) OnUploadOrigin(c *gin.Context) {
uid, e := uuid.NewV1()
if nil != e {
log.Print(e.Error())
return
}
imgtype := c.Query("type")
file, _, err := c.Request.FormFile("image")
if nil != err || nil == file {
log.Print(err.Error())
return
}
if imgtype == "gif" {
allgifs, er := gif.DecodeAll(file)
if nil != er {
log.Print("decode error", er.Error())
return
}
datout, err := os.Create("image/" + uid.String() + ".gif")
defer datout.Close()
if err != nil {
log.Fatal(err)
return
}
gif.EncodeAll(datout, allgifs)
c.JSON(200, map[string]interface{}{"url": uid.String() + ".gif"})
} else {
img, name, err := image.Decode(file)
if nil != err {
log.Print(err.Error())
return
}
dx := img.Bounds().Dx()
// resize to width 1000 using Lanczos resampling
// and preserve aspect ratio
m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)
datout, err := os.Create("image/" + uid.String() + "." + name)
defer datout.Close()
if err != nil {
log.Fatal(err)
}
jpeg.Encode(datout, m, nil)
c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})
}
}
func (this *FileController) FileList(c *gin.Context) {
var nodes utils.FileDesc
path := c.Query("path")
utils.GetPathFileName("files\\"+path, &nodes)
log.Print(nodes)
bs, e := json.Marshal(nodes)
if nil != e {
log.Print(e.Error())
}
log.Print(string(bs))
c.JSON(200, map[string]interface{}{
"msg": "ok",
"status": 200,
"files": nodes,
})
}
func (this *FileController) FileType(c *gin.Context) {
}
func (this *FileController) DownloadFile(c *gin.Context) {
resp := RespBase{Msg: "FAIL", Status: 211}
filename := c.Query("filename")
file, e := os.Open("files//" + filename)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
bytes, e := ioutil.ReadAll(file)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
c.Header("X-Content-Type-Options", "nosniff")
c.Header("Content-Disposition",
"/files/"+filename)
c.Writer.Write(bytes)
}
func myAtoi(str string) int {
num := 0
s := ""
flag := false
str = strings.TrimSpace(str)
if len(str) == 0 {
return 0
}
for i := 0; i < len(str); i++ {
if !(str[i] >= '0' && str[i] <= '9') && !(str[i] == '+' || str[i] == '-') {
break
}
if str[i] == '+' {
if flag || s != "" {
break
}
flag = true
continue
}
if str[i] == '-' {
if flag || s != "" {
break
}
flag = true
s += "-"
continue
}
s += string(str[i])
}
num, _ = strconv.Atoi(s)
if num > math.MaxInt32 {
return math.MaxInt32
} else if num < math.MinInt32 {
return math.MinInt32
}
return num
}
func (this *FileController) OnFileUploadFileMarkdown(c *gin.Context) {
parent := c.Query("parent")
filename := c.Query("filename")
file, _, err := c.Request.FormFile("file")
if nil != err || nil == file {
log.Print(err.Error())
return
}
bytes, err := ioutil.ReadAll(file)
if nil != err {
log.Print(err.Error())
return
}
log.Print(parent, filename, string(bytes))
query := fmt.Sprintf("select * from doc_copy1 where doc_copy1.id = '%d'", int32(myAtoi(parent)))
docs := []model.DocTree{}
e := db.GetMysqlClient().Query2(query, &docs)
if nil != e {
log.Print(e.Error())
return
}
if len(docs) == 0 {
return
}
fork := strings.ReplaceAll(string(bytes), "\\\\", "\\\\\\\\")
fork = strings.ReplaceAll(string(fork), "\\", "\\\\")
e = model.CreateDocTree(
model.DocTree{
Title: filename,
Content: fork,
Author: "admin",
IsPublic: 1,
Father: int32(myAtoi(parent)),
Level: docs[0].Level + 1,
},
)
if nil != e {
log.Printf(e.Error())
}
c.JSON(200, map[string]interface{}{"msg": "ok"})
}
func (this *FileController) OnFileUploadFile(c *gin.Context) {
path := c.Query("path")
filename := c.Query("filename")
file, _, err := c.Request.FormFile("file")
if nil != err || nil == file {
log.Print(err.Error())
return
}
bytes, err := ioutil.ReadAll(file)
if nil != err {
log.Print(err.Error())
return
}
header := make([]byte, 512)
copy(header, bytes)
types := http.DetectContentType(header)
log.Print(types)
// jpg
defer file.Close()
out, err := os.Create("files/" + path + "/" + filename)
if err != nil {
log.Print(err)
}
defer out.Close()
out.Write(bytes)
log.Print(len(bytes))
c.JSON(200, map[string]interface{}{"msg": "ok"})
}
func (this *FileController) OnThumbnail(c *gin.Context) {
resp := RespBase{Msg: "FAIL", Status: 211}
fileName := c.Param("file")
if "" == fileName {
c.JSON(200, resp)
return
}
// input files
files := []string{"/home/ubuntu/api/bin/image/" + fileName}
// load images and make 100x100 thumbnails of them
var thumbnails []image.Image
for _, file := range files {
img, err := imaging.Open(file)
if err != nil {
panic(err)
}
thumb := imaging.Thumbnail(img, 100, 100, imaging.CatmullRom)
thumbnails = append(thumbnails, thumb)
}
// create a new blank image
dst := imaging.New(100*len(thumbnails), 100, color.NRGBA{0, 0, 0, 0})
// paste thumbnails into the new image side by side
for i, thumb := range thumbnails {
dst = imaging.Paste(dst, thumb, image.Pt(i*100, 0))
}
// save the combined image to file
err := imaging.Save(dst, "/home/ubuntu/api/bin/image/thumbnail_"+fileName)
if err != nil {
log.Print(err.Error())
return
}
// open file
file, e := os.Open("/home/ubuntu/api/bin/image/thumbnail_" + fileName)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
defer file.Close()
bytes, e := ioutil.ReadAll(file)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
c.Header("X-Content-Type-Options", "nosniff")
c.Header("Content-Type", "image/png")
c.Header("Content-Disposition",
"/image/"+fileName)
c.Writer.Write(bytes)
}
func (this *FileController) OnDownLoad(c *gin.Context) {
resp := RespBase{Msg: "FAIL", Status: 211}
fileName := c.Param("file")
if "" == fileName {
c.JSON(200, resp)
return
}
file, e := os.Open(utils.GetCurrentDirectory() + "/image/" + fileName)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
defer file.Close()
bytes, e := ioutil.ReadAll(file)
if nil != e {
log.Print(e.Error())
c.JSON(200, resp)
return
}
c.Header("X-Content-Type-Options", "nosniff")
c.Header("Content-Type", "image/png")
c.Header("Content-Disposition",
"/image/"+fileName)
c.Writer.Write(bytes)
}

97
controller/hardware.go Normal file
View File

@ -0,0 +1,97 @@
package controller
import (
"background/logs"
"background/model"
"github.com/gin-gonic/gin"
"qiniupkg.com/x/log.v7"
)
func AddHardware(c *gin.Context) {
resp := RespBase{"unkown error", -231, nil}
defer func() {
c.JSON(200, resp)
}()
var hardware model.Hardware
e := c.BindJSON(&hardware)
if nil != e {
log.Print(e)
print(e)
return
}
e = hardware.CreateHardware()
if nil != e {
resp.Status = -100
resp.Msg = e.Error()
log.Print(e)
return
}
resp.Data = nil
resp.Msg = "OK"
resp.Status = 0
}
func DeleteHardWare(c *gin.Context) {
resp := RespBase{"unkown error", -231, nil}
defer func() {
c.JSON(200, resp)
}()
name := c.Query("name")
if name == "" {
return
}
e := model.DeleteHardware(name)
if nil != e {
logs.Error(e.Error())
return
}
resp.Msg = "OK"
resp.Status = 0
resp.Data = nil
}
func SearchDoc(c *gin.Context){
type ReqSearch struct{
Content string `json:"content"`
}
resp := RespBase{"unkown error", -231, nil}
defer func() {
c.JSON(200, resp)
}()
req := ReqSearch{}
e := c.BindJSON(&req)
if nil != e {
log.Print(e)
print(e)
return
}
resp.Data = nil
resp.Msg = "OK"
resp.Status = 0
}
func UpdateHardWare(c *gin.Context) {
}
func ReadHardWare(c *gin.Context) {
rsp := RespBase{"ERR", -1, nil}
defer func() {
c.JSON(200, rsp)
}()
limit, offset := GetPageParaFromQuery(c)
log.Print(limit, offset)
hardware, e := model.GetHardwares(limit, offset)
if nil != e {
return
}
rsp.Data = hardware
rsp.Msg = "OK"
rsp.Status = 0
}

View File

@ -0,0 +1,19 @@
package helper
import (
"background/controller/params"
"github.com/gin-gonic/gin"
)
func GetPageParam(c *gin.Context) (int, int) {
var limit, offset int
var ok bool
limit, ok = c.Keys[params.K_OFFSET].(int)
if !ok {
}
offset, ok = c.Keys[params.K_OFFSET].(int)
if !ok {
}
return limit, offset
}

285
controller/mail.go Normal file
View File

@ -0,0 +1,285 @@
package controller
import (
"background/config"
"background/db"
"bufio"
"bytes"
"errors"
"fmt"
"io/ioutil"
"log"
"net/smtp"
"os"
"regexp"
"strings"
"text/template"
"time"
"github.com/gin-gonic/gin"
)
type MailController struct {
}
type RespJson struct {
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
Affected int64 `json:"affected,omitempty"`
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsExist(err) {
return true, nil
}
return false, err
}
func GetTemplateFile(template string) ([]byte, error) {
path := "G:\\GoPath\\Email\\" + template + ".tpl"
ok, err := PathExists(path)
if !ok {
return nil, errors.New("Count not Find File " + path)
}
file, err := os.Open(path)
if err != nil {
log.Println(err.Error())
}
ret, err := ioutil.ReadAll(file)
file.Close()
return ret, nil
}
//静态文件存放地
const PATH_STATIC = "G://GoPath//Email//static//"
type ReqSendEmailTpl struct {
From string `json:"from"`
To string `json:"to"`
Tittle string `json:"tittle"`
TempData interface{} `json:"temp_data"`
Template string `json:"template"`
Generate bool `json:"generate"`
}
type ReqSendEmail struct {
Email string `json:"email_address"`
Content string `json:"content"`
}
func SendToMailWithUserInfo(title, user, password, host, to, content string) error {
var content_type string
hp := strings.Split(host, ":")
auth := smtp.PlainAuth("", user, password, hp[0])
msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + title + "\r\n" +
content_type + "\r\n\r\n" + content + "\r\n")
send_to := strings.Split(to, ";")
//检测是否是邮件地址
for k, _ := range send_to {
match, _ := regexp.MatchString("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?", send_to[k])
if !match {
return errors.New("Format Error")
}
}
err := smtp.SendMail(host, auth, user, send_to, msg)
if err != nil {
return err
}
return err
}
func SendToMailTpl(title, user, password, host, to, tplname string, content interface{}, mailtype string, ifgenerate bool) error {
var content_type string
var paseresult bytes.Buffer
writer := bufio.NewWriter(&paseresult)
hp := strings.Split(host, ":")
auth := smtp.PlainAuth("", user, password, hp[0])
if mailtype == "html" {
content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
} else {
content_type = "Content-Type: text/plain" + "; charset=UTF-8"
}
//todo 获取模板文件内容
tpl, err := GetTemplateFile(tplname)
if err != nil {
log.Println(err.Error())
return err
}
//todo 渲染
tparse := template.New(tplname)
tparse, _ = tparse.Parse(string(tpl))
tparse.Execute(writer, content)
writer.Flush()
if err != nil {
log.Println(err.Error())
return err
}
msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + title + "\r\n" +
content_type + "\r\n\r\n" + paseresult.String() + "\r\n")
send_to := strings.Split(to, ";")
//todo 如果生成Html文件
if ifgenerate {
file, err := os.Create(PATH_STATIC + tplname + ".html")
if err != nil {
log.Println(err.Error())
}
file.WriteString(paseresult.String())
file.Close()
}
//检测是否是邮件地址
for k, _ := range send_to {
match, _ := regexp.MatchString("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?", send_to[k])
if !match {
return errors.New("Format Error")
}
}
err = smtp.SendMail(host, auth, user, send_to, msg)
if err != nil {
return err
}
return err
}
/*
func OnSendEmailSendCloud(c *gin.Context){
var req ReqSendEmail
var resp mysqlcurd.RespJson
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e!= nil{
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
sendcloud.UpdateApiInfo("a7458969_test_KIIqjl", "ovErXj6M8UJeiPJt")
var to = make([]map[string]string, 1)
to[0] = map[string]string{"to":"290198252@qq.com", "%url%": "http://www.baidu.com"}
var ok, err, result = sendcloud.SendTemplateMail("test_template_active", "290198252@sendcloud.org", "测试", "", "测试", to, nil)
if err != nil{
log.Print(err.Error())
resp.Msg = "Fail"
}
if !ok{
resp.Msg = "Fail"
}
resp.Msg = result
}*/
/*
{
"tittle":"运维通知",
"from":"c7458969@163.com",
"to":"290198252@qq.com",
"template":"test",
"generate":true,
"temp_data":{
"content":"f发撒旦法时代阿达是否",
"title":"运维通知2",
"topimg":"http://img2.imgtn.bdimg.com/it/u=387283908,3372540416&fm=27&gp=0.jpg",
"button1text":"客服热线",
"button1url":"http://www.baidu.com",
"button2text":"查看详情",
"button2url":"http://www.baidu.com",
"logoimg":"http://news.tom.com/dimg/2016/1027/img-1479784632271.jpg"
}
}
*/
//from: 发送人邮箱
//to:接收邮件,可以是"290198252@qq.com;29019822@qq.com;2901982@qq.com" 邮箱之间用分号隔开
//template:模板名字
//content :网页模板的参数 key-value结构
//temp_data 模板内具体要替换的变量名字 Key-value结构
//generate 是否生成静态html
func OnSendEmailTpl(c *gin.Context) {
var req ReqSendEmailTpl
var resp RespJson
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
user := "c7458969@163.com"
password := "caiyu123"
host := "smtp.163.com:25"
//抄送给自己
//e = SendToMail(user,password,host,req.From,req.Template,req.Content,"html")
//发送
e = SendToMailTpl(req.Tittle, user, password, host, req.To, req.Template, req.TempData, "html", req.Generate)
if nil != e {
log.Println(e.Error())
resp.Msg = "Error"
return
}
resp.Msg = "OK"
}
//from: 发送人邮箱
//to:接收邮件,可以是"290198252@qq.com;29019822@qq.com;2901982@qq.com" 邮箱之间用分号隔开
//template:模板名字
//content :网页模板的参数 key-value结构
//temp_data 模板内具体要替换的变量名字 Key-value结构
//generate 是否生成静态html
func (this *MailController) OnSendEmailCode(c *gin.Context) {
var req ReqSendEmail
var resp RespJson
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
if req.Email != "" {
type Count struct {
Count int32 `json:"count"`
}
cnt := []Count{}
query := fmt.Sprintf("select count(*) as count from users where users.email_address = '%s'", req.Email)
e := db.GetMysqlClient().Query2(query, &cnt)
if nil != e {
log.Println(e.Error())
return
}
} else {
return
}
user := "c7458969@163.com"
password := "caiyu123"
host := "smtp.163.com:25"
//抄送给自己
//e = SendToMail(user,password,host,req.From,req.Template,req.Content,"html")
//发送
verCode := CreateVerify(6)
content := "您的验证码是" + verCode
userKey := fmt.Sprintf("user_%s_verify", req.Email)
config.RedisOne().Set(userKey, verCode, time.Hour*24)
e = SendToMailWithUserInfo("后台管理系统验证码", user, password, host, req.Email, content)
if nil != e {
log.Println(e.Error())
resp.Msg = "Error"
return
}
resp.Msg = "OK"
}

57
controller/middle/auth.go Normal file
View File

@ -0,0 +1,57 @@
/*
* @Author: your name
* @Date: 2020-10-04 18:06:06
* @LastEditTime: 2021-07-17 22:22:05
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \background\controller\middle\auth.go
*/
package middle
import (
"background/config"
"background/controller"
"background/model"
"encoding/json"
"log"
"github.com/gin-gonic/gin"
)
func AuthMiddle(c *gin.Context) {
token := c.Query("token")
user := c.Query("userid")
if user == "" || token == "" {
log.Print("error user not existed or token missing")
log.Print(c.Request.URL.String())
c.JSON(200, controller.RespBase{
"auth err", 20, nil,
})
c.Abort()
return
}
cli := config.RedisOne()
if cli != nil{
if cli.Exists(token).Val() {
users := model.Users{}
userInfo := config.RedisOne().Get(token).Val()
e := json.Unmarshal([]byte(userInfo), &users)
if nil != e {
c.JSON(200, controller.RespBase{
"auth err", 10, nil,
})
c.Abort()
return
}
} else {
c.JSON(200, controller.RespBase{
"expired or no login", 210, nil,
})
c.Abort()
return
}
c.Next()
}
}

324
controller/openapi.go Normal file
View File

@ -0,0 +1,324 @@
package controller
import (
"background/utils"
"container/list"
"encoding/xml"
"fmt"
"io"
"log"
"github.com/gin-gonic/gin"
)
type OpenApiController struct {
}
type DiffRequest struct {
Origin string `json:"origin"`
New string `json:"new"`
}
//from: 发送人邮箱
//to:接收邮件,可以是"290198252@qq.com;29019822@qq.com;2901982@qq.com" 邮箱之间用分号隔开
//template:模板名字
//content :网页模板的参数 key-value结构
//temp_data 模板内具体要替换的变量名字 Key-value结构
//generate 是否生成静态html
func (this *OpenApiController) OndiffCallback(c *gin.Context) {
var req DiffRequest
var resp RespBase
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
resp.Msg = "OK"
}
type ReqDDL struct {
Data string `json:"data"`
}
func (this *OpenApiController) DDL2ORM(c *gin.Context) {
var req ReqDDL
resp := RespBase{
Msg: "err",
}
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
tbname, fields := utils.DDL2Field(req.Data)
log.Print(tbname, fields)
gocode := utils.CreateGoStruct(tbname,fields)
resp.Data = gocode
resp.Msg = "OK"
resp.Status = 0
}
func getAttr(name string, attr []xml.Attr) string {
for _, a := range attr {
if a.Name.Local == name {
return a.Value
}
}
return ""
}
type Widget struct{
Name string
Class string
Parent *Widget
Childs list.List
}
func RangeWidget(p *Widget ) string{
if nil == p{
return ""
}
ret := ""
parent := ""
tmp := p
for ;tmp != nil;tmp = tmp.Parent{
parent = tmp.Class + "#" + tmp.Name + " " + parent
}
ret += parent + ` \r\n{\r\n}\r\n`
if(p.Childs.Len() > 0){
wid := p.Childs.Front()
for ;wid != nil;wid = wid.Next(){
tmp := wid.Value.(*Widget)
ret += RangeWidget(tmp)
}
}
return ret
}
type Controller struct{
Type string
Name string
Parent *Controller
Childs list.List
}
func GetUifrom(path io.Reader) string{
list := list.List{}
decoder := xml.NewDecoder(path)
for {
token, _ := decoder.Token()
if token == nil {
break
}
switch startElement := token.(type) {
case xml.StartElement:
log.Print(0,startElement.Name)
if(list.Len() == 0){
ins := new(Controller)
ins.Name = getAttr("name",startElement.Attr)
log.Print(ins.Name)
ins.Parent = nil
list.PushBack(ins)
}else{
ins := new(Controller)
ins.Type = startElement.Name.Local
ins.Name = getAttr("name",startElement.Attr)
log.Print(ins.Name)
ins.Parent = list.Back().Value.(*Controller)
list.Back().Value.(*Widget).Childs.PushBack(ins)
list.PushBack(ins)
}
break
case xml.EndElement:
log.Print(1,startElement.Name)
if(startElement.Name.Local == "widget"){
if(list.Len() > 0){
if(list.Back().Value.(*Widget).Parent != nil){
list.Remove(list.Back())
}
}
}
break
}
}
p := list.Back().Value.(*Widget)
ret := RangeWidget(p)
log.Print(ret)
return ret
}
func (this *OpenApiController) DDL2Markdown(c *gin.Context) {
var req ReqDDL
resp := RespBase{
Msg: "err",
}
defer func() {
c.JSON(200, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
resp.Msg = "ParaErr"
return
}
tbname, fields := utils.DDL2Field(req.Data)
log.Print(tbname, fields)
gocode := utils.CreateMarkdownTable(tbname,fields)
resp.Data = gocode
resp.Msg = "OK"
resp.Status = 0
}
func (this *OpenApiController) UI2CSS(c *gin.Context) {
f, err := c.FormFile("ui") //根据name返回给第一个文件
if err != nil {
c.String(200,"上传文件错误")
return
}
file,e := f.Open()
if nil != e{
c.String(200,"上传文件错误")
return
}
ret := GetUifrom(file)
c.String(200,ret)
}
func GetXMLNode(xmltype string ) string{
return string("m_") + utils.ToSnakeString(xmltype) + "_"
}
func GetXmlController(path io.Reader) string{
list := list.List{}
maps := map[string]int{}
ret := ""
decoder := xml.NewDecoder(path)
for {
token, _ := decoder.Token()
if token == nil {
break
}
switch startElement := token.(type) {
case xml.StartElement:
if(list.Len() == 0){
ins := new(Controller)
ins.Type = startElement.Name.Local
ins.Name = getAttr("name",startElement.Attr)
ins.Parent = nil
list.PushBack(ins)
}else{
ins := new(Controller)
ins.Type = startElement.Name.Local
ins.Name = getAttr("name",startElement.Attr)
ins.Parent = list.Back().Value.(*Controller)
list.Back().Value.(*Controller).Childs.PushBack(ins)
list.PushBack(ins)
}
break
case xml.EndElement:
break
}
}
begin := list.Front()
first := true
fatherType := begin.Value.(*Controller).Type
log.Print(begin.Value.(*Controller).Type)
for begin.Next() != nil{
if begin.Value.(*Controller).Name != ""{
if first{
first = false
}else{
if _,ok := maps[begin.Value.(*Controller).Type] ;ok{
maps[begin.Value.(*Controller).Type]++
}else{
maps[begin.Value.(*Controller).Type] = 1
}
ret += fmt.Sprintf("ui::%s * m_%s_%d;\r\n",
begin.Value.(*Controller).Type,
utils.ToSnakeString(begin.Value.(*Controller).Type),
maps[begin.Value.(*Controller).Type])
}
}
begin = begin.Next()
}
ret+="\r\n\r\n"
begin = list.Front()
first = true
for k := range maps {
delete(maps, k)
}
for begin.Next() != nil{
if begin.Value.(*Controller).Name != ""{
if first{
first = false
}else{
if _,ok := maps[begin.Value.(*Controller).Type] ;ok{
maps[begin.Value.(*Controller).Type]++
}else{
maps[begin.Value.(*Controller).Type] = 1
}
if(fatherType == "Window"){
ret += fmt.Sprintf("ui::%s * m_%s_%d = dynamic_cast<ui::%s*>(FindControl(L\"%s\"));\r\n",
begin.Value.(*Controller).Type,
utils.ToSnakeString(begin.Value.(*Controller).Type),
maps[begin.Value.(*Controller).Type],
begin.Value.(*Controller).Type,
begin.Value.(*Controller).Name)
}
if(fatherType == "ChildBox"){
ret += fmt.Sprintf("ui::%s * m_%s_%d = dynamic_cast<ui::%s*>(FindSubControl(L\"%s\"));\r\n",
begin.Value.(*Controller).Type,
utils.ToSnakeString(begin.Value.(*Controller).Type),
maps[begin.Value.(*Controller).Type],
begin.Value.(*Controller).Type,
begin.Value.(*Controller).Name)
}
}
}
begin = begin.Next()
}
return ret
}
func (this *OpenApiController) DuilibXml2Cpp(c *gin.Context) {
f, err := c.FormFile("xml") //根据name返回给第一个文件
if err != nil {
c.String(200,"上传文件错误")
return
}
file,e := f.Open()
if nil != e{
c.String(200,"上传文件错误")
return
}
ret := GetXmlController(file)
log.Print(ret)
c.String(200,ret)
}

5
controller/params/params Normal file
View File

@ -0,0 +1,5 @@
package params
const K_OFFSET = "offset"
const K_LIMIT = "limit"

300
controller/plan.go Normal file
View File

@ -0,0 +1,300 @@
package controller
import (
"background/db"
"background/logs"
"background/model"
"fmt"
"log"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
type PlanController struct {
}
func (t *PlanController) GetPlan(c *gin.Context) {
}
func (t *PlanController) GetPlanDates(c *gin.Context) {
type Req struct {
Date string `json:"date"`
}
var req Req
resp := RespBase{
Msg: "ERROR",
Status: 23,
}
defer c.JSON(200, &resp)
e := c.BindJSON(&req)
if nil != e {
log.Print(e.Error())
return
}
plan := []model.Plan{}
e = db.GetOrm().Model(&plan).Where("date = ?", req.Date).Find(&plan).Error
if nil != e {
log.Print(e.Error())
}
resp.Status = 0
resp.Msg = "OK"
resp.Data = plan
return
}
func (t *PlanController) AddPlan(c *gin.Context) {
var req model.Plan
resp := RespBase{Msg: "r", Status: 0, Data: nil}
defer c.JSON(200, &resp)
e := c.BindJSON(&req)
if nil != e {
log.Print(e.Error())
return
}
e = db.GetOrm().Create(&req).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) DelPlan(c *gin.Context) {
resp := RespBase{Msg: "r", Status: 0, Data: nil}
defer c.JSON(200, &resp)
var e error
iid := 0
id := c.Query("id")
if "" != id {
iid, e = strconv.Atoi(id)
if nil != e {
log.Print(e.Error())
return
}
} else {
return
}
plan := model.Plan{}
plan.ID = uint32(iid)
e = db.GetOrm().Delete(&plan).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Msg = "OK"
resp.Status = 0
}
type ReqDate struct {
Date string `gorm:"date" json:"date"`
}
func (m *ReqDate) TableName() string {
return "plan"
}
func (t *PlanController) PlanDay(c *gin.Context) {
var req ReqDate
resp := RespBase{
Msg: "ERROR",
Status: 23,
}
defer c.JSON(200, &resp)
e := c.BindJSON(&req)
if nil != e {
log.Print(e.Error())
return
}
ret := make([]ReqDate, 1)
sql := fmt.Sprintf(`SELECT distinct plan.date FROM plan where DATE_FORMAT(plan.date,'%%Y-%%m')=DATE_FORMAT('%s','%%Y-%%m')`, req.Date)
log.Print(sql)
e = db.GetOrm().Raw(sql).Find(&ret).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Data = ret
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) Types(c *gin.Context) {
resp := RespBase{
Msg: "ERROR",
Status: 23,
}
defer c.JSON(200, &resp)
rets := []model.PlanType{}
e := db.GetOrm().Model(&model.PlanType{}).Find(&rets).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Data = rets
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) CreateUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
var req model.Undo
e := c.BindJSON(&req)
if nil != e {
logs.Error(e.Error())
resp.Msg = "wrong input"
return
}
req.CreateTime = time.Now().Format("2006-01-02 15:04:05")
e = db.GetOrm().Model(&model.Undo{}).Create(&req).Error
if nil != e {
log.Print(e.Error())
return
}
log.Print(req.ID)
resp.Data = req.ID
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) UnFinishUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
id := c.Param("id")
e := db.GetOrm().Exec(fmt.Sprintf("update background.`undo` set done = '0' where id = '%s'",id )).Error
if nil != e {
logs.Error(e.Error())
return
}
resp.Data = nil
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) FinishUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
id := c.Param("id")
log.Print("finish undo id",id)
e := db.GetOrm().Exec(fmt.Sprintf("update background.`undo` set done = 1,finish_time='%s' where id = %s",
time.Now().Format("2006-01-02 15:04:05"),id)).Error
log.Print(fmt.Sprintf("update background.`undo` set done = 1,finish_time='%s' where id = %s",time.Now().Format("2006-01-02 15:04:05"),id))
if nil != e {
logs.Error(e.Error())
return
}
resp.Data = nil
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) UpdateUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
var req model.Undo
e := c.BindJSON(&req)
if nil != e {
resp.Msg = "wrong input"
return
}
e = db.GetOrm().Model(&model.Undo{}).Update(&req).Error
if nil != e {
logs.Error(e.Error())
return
}
resp.Data = nil
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) GetDone(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
undos := []model.Undo{}
e := db.GetOrm().Model(&model.Undo{}).Where("done = 1").Find(&undos).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Data = undos
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) GetUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
undos := []model.Undo{}
e := db.GetOrm().Model(&model.Undo{}).Find(&undos).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Data = undos
resp.Msg = "OK"
resp.Status = 0
}
func (t *PlanController) GetPageUndo(c *gin.Context) {
type ReqGetPageUndo struct {
}
var req ReqGetPageUndo
resp := RespBase{}
// limit := c.Query("limit")
// offset := c.Query("offset")
// iLmit, e := strconv.Atoi(limit)
// if nil != e {
// return
// }
// iOffset, e := strconv.Atoi(offset)
// if nil != e {
// return
// }
defer func() {
c.JSON(200, resp)
}()
e := c.BindJSON(&req)
if nil != e {
logs.Error(e.Error())
return
}
}
func (t *PlanController) DeleteUndo(c *gin.Context) {
resp := RespBase{}
defer func() {
c.JSON(200, resp)
}()
sid := c.Param("id")
id := db.Atoi(sid)
e := db.GetOrm().Model(&model.Undo{}).Delete(&model.Undo{ID: int32(id)}).Error
if nil != e {
log.Print(e.Error())
return
}
resp.Status = 0
resp.Msg = "OK"
}

536
controller/user.go Normal file
View File

@ -0,0 +1,536 @@
package controller
import (
"background/config"
"background/db"
"background/logs"
"background/model"
"background/redis"
"background/utils"
"bytes"
"crypto/md5"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"math/rand"
"net/http"
"net/smtp"
"regexp"
"strconv"
"strings"
"time"
"github.com/fatih/structs"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
sessions "github.com/tommy351/gin-sessions"
)
type UserController struct {
}
type ReqSendEmailCode struct {
EmailAdress string `json:"email_address"`
}
type SetUserGroupReq struct {
Id int64 `json:"id,omitempty"`
Description string `json:"description"`
GroupName string `json:"group_name"`
UserIds []int `json:"user_ids"`
}
func (this *UserController) Auth(c *gin.Context) {
var resp RespBase
var statuscode int
statuscode = 200
var userinfo map[string]interface{}
//var userSockToken map[string] interface{}
defer func() {
c.JSON(statuscode, resp)
}()
socketToken := c.Query("socketToken")
struserinfo, e := redis.Get(socketToken)
if e != nil {
logs.Error(e.Error())
return
}
e = json.Unmarshal([]byte(struserinfo), userinfo)
if nil != e {
logs.Error(e.Error())
return
}
}
func (this *UserController) SetUser(c *gin.Context) {
}
func (this *UserController) ModifyPasswd(c *gin.Context) {
type ReqModifyPasswd struct {
id int `json:"id"`
UserName string `json:"user_name"`
Password string `json:"password"`
}
var req ReqModifyPasswd
var resp RespBase
resp.Status = -1
resp.Msg = "err"
defer func() {
c.JSON(200, resp)
}()
e := c.BindJSON(&req)
if nil != e {
logs.Error(e.Error())
return
}
e = model.ModyfyPassword(req.UserName, req.Password)
if nil != e {
logs.Error(e.Error())
return
}
resp.Msg = "OK"
resp.Status = 0
}
func (this *UserController) DelUser(c *gin.Context) {
}
func (this *UserController) GetUser(c *gin.Context) {
var resp RespBase
resp.Msg = "操作失败"
resp.Status = 20
defer func() {
c.JSON(200, resp)
}()
session := sessions.Get(c)
userinfo := session.Get("")
if userinfo == nil {
logs.Error("error could not find key")
return
}
var users map[string]interface{}
e := json.Unmarshal([]byte(userinfo.(string)), &users)
if nil != e {
logs.Error(e.Error())
}
delete(users, "socketToken")
resp.Status = 0
resp.Msg = "操作成功"
resp.Data = users
}
func (this *UserController) Users(c *gin.Context) {
var statuscode int
var resp RespBase
resp.Msg = "获取失败"
resp.Status = 0
statuscode = 200
defer func() {
c.JSON(statuscode, resp)
}()
offset := c.Query("offset")
limit := c.Query("limit")
ioffset, e := strconv.Atoi(offset)
if nil != e {
logs.Error(e.Error())
return
}
ilimit, er := strconv.Atoi(limit)
if nil != er {
logs.Error(e.Error())
return
}
dat := map[string]interface{}{}
users, all := model.GetUsers(int32(ilimit), int32(ioffset), "")
dat["users"] = users
dat["all"] = all
resp.Msg = "OK"
resp.Data = dat
}
func (this *UserController) SerarchUsers(c *gin.Context) {
var statuscode int
var resp RespBase
resp.Msg = "获取失败"
resp.Status = 0
statuscode = 200
defer func() {
c.JSON(statuscode, resp)
}()
offset := c.Query("offset")
limit := c.Query("limit")
username := c.PostForm("username")
ioffset, e := strconv.Atoi(offset)
if nil != e {
logs.Error(e.Error())
return
}
ilimit, er := strconv.Atoi(limit)
if nil != er {
logs.Error(e.Error())
return
}
dat := map[string]interface{}{}
users, all := model.GetUsers(int32(ilimit), int32(ioffset), username)
dat["users"] = users
dat["all"] = all
resp.Msg = "OK"
resp.Data = dat
}
func CreateVerify(length int32) string {
strAry := []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
result := string("")
for i := int32(0); i < length; i++ {
x := rand.Intn(len(strAry))
result += string(strAry[x])
}
return result
}
/**
* Token
* @param {Number} length Token
* @return {string} Token
*/
func createToken(length int32) string {
strAry := []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_'}
result := string("")
for i := int32(0); i < length; i++ {
x := rand.Intn(len(strAry))
result += string(strAry[x])
}
return result
}
func DefaultOption(c *gin.Context) {
var resp RespBase
defer func() {
c.JSON(204, resp)
}()
}
func (this *UserController) Login(c *gin.Context) {
// defer func() {
// if err := recover();err != nil{
// log.Printf("panic: v%",err)
// }
// }()
type LoginReq struct {
RememberMe int32 `json:"remember_me"`
UserName string `json:"user_name"`
UserPwd string `json:"user_pwd"`
}
var req LoginReq
statusCode := 200
var resp RespBase
defer func() {
c.JSON(statusCode, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
return
}
h := md5.New()
h.Write([]byte(req.UserPwd)) // 需要加密的字符串为 123456
passmd5 := h.Sum(nil)
var result []model.Users
query := fmt.Sprintf("select * from users where user_name = '%s'", req.UserName)
er := db.GetMysqlClient().Query2(query,
&result)
logs.Debug("sql query:" + query)
if nil != er {
log.Println(er.Error())
}
strpassmd5 := utils.ByteSliceToString(passmd5)
if len(result) == 1 {
if result[0].UserPwd == strpassmd5 {
socketToken := md5.New()
socketToken.Write([]byte(createToken(6))) // 需要加密的字符串为 123456
socketTokenMd5 := socketToken.Sum(nil)
m := structs.Map(result[0])
m["SocketToken"] = utils.ByteSliceToString(socketTokenMd5)
sessionInfo, err := json.Marshal(m)
if err != nil {
log.Println(err.Error())
}
if req.RememberMe == 1 {
config.RedisOne().Set(utils.ByteSliceToString(socketTokenMd5), string(sessionInfo), time.Second*24*3600)
} else {
log.Print(utils.ByteSliceToString(socketTokenMd5), string(sessionInfo), time.Second*8*3600)
cli := config.RedisOne()
if nil != cli{
status := cli.Set(utils.ByteSliceToString(socketTokenMd5), string(sessionInfo), time.Second*8*3600)
if status.Err() != nil{
log.Println(status)
}
}
}
//存储session
// session := sessions.Get(c)
// log.Println("set session", string(sessionInfo))
// session.Set("", string(sessionInfo))
// session.Clear()
//session.
// var Options *sessions.Options
// if req.RememberMe == 1 {
// Options = &sessions.Options{
// MaxAge: 2 * 24 * 3600 * 1000,
// }
// } else {
// Options = &sessions.Options{
// MaxAge: 8 * 3600 * 1000,
// }
// }
// session.Options(*Options)
// session.Save()
resp.Msg = "登录成功"
resp.Status = 0
resp.Data = string(sessionInfo)
} else {
resp.Status = 422
resp.Msg = "用户密码不正确"
}
} else {
resp.Status = 422
resp.Msg = "登录账号不存在,请重新输入"
}
}
func (this *UserController) Register(c *gin.Context) {
type RegisterReq struct {
DisplayName string `json:"display_name"`
EmailAdress string `json:"email_address"`
EmailCode string `json:"email_code"`
UserName string `json:"user_name"`
UserPwd string `json:"user_pwd"`
}
var req RegisterReq
statusCode := 200
var resp RespBase
var user model.Users
resp.Msg = "失败"
resp.Status = 1
defer func() {
c.JSON(statusCode, resp)
}()
e := c.Bind(&req)
if e != nil {
log.Println(e.Error())
return
}
userKey := fmt.Sprintf("user_%s_verify", req.EmailAdress)
verify := config.RedisOne().Get(userKey).Val()
if verify != req.EmailCode {
resp.Msg = "验证码错误"
resp.Status = 20
return
}
user.UserName = req.UserName
user.EmailAddress = req.EmailAdress
user.DisplayName = req.DisplayName
h := md5.New()
h.Write([]byte(req.UserPwd))
passwdmd5 := h.Sum(nil)
strpassmd5 := utils.ByteSliceToString(passwdmd5)
user.UserPwd = strpassmd5
user.UpdatedDate = time.Now().Format("2006-01-02 15:04:05")
user.CreatedDate = time.Now().Format("2006-01-02 15:04:05")
var result []model.Users
er := db.GetMysqlClient().Query2("select * from users where user_name = ?",
&result, req.UserName)
if nil != er {
log.Println(er.Error())
return
}
if len(result) > 0 {
resp.Msg = "失败,账号已经存在"
resp.Status = 20
return
}
query := fmt.Sprintf("insert into users(user_name,user_pwd,created_date,"+
"updated_date,display_name,email_address) values ('%s','%s','%s','%s','%s','%s')", user.UserName, user.UserPwd, user.CreatedDate, user.UpdatedDate,
user.DisplayName, user.EmailAddress)
n, er := db.GetMysqlClient().Insert(query)
if n == 0 || n < 0 {
statusCode = 422
logs.Error(er.Error())
resp.Msg = "失败,账号已经存在"
resp.Status = 20
return
}
if nil != er {
statusCode = 422
logs.Error(er.Error())
resp.Msg = "失败"
resp.Status = 20
return
}
resp.Msg = "成功"
resp.Status = 0
}
func (this *UserController) Logout(c *gin.Context) {
token := c.Param("token")
log.Print("logout token is ", token)
var resp RespBase
config.RedisOne().Del(token)
resp.Msg = "退出成功"
resp.Status = 0
defer func() {
c.JSON(200, resp)
}()
session := sessions.Get(c)
session.Delete("")
session.Save()
}
func Reader2Json(r io.ReadCloser) string {
var ret string
for i := 0; ; i++ {
s := make([]byte, 10)
_, e := r.Read(s)
ret += string(s)
if e != nil {
break
}
}
return ret
}
func SendExternalEmail(msg interface{}) error {
req := make(map[string]interface{}, 1)
req["type"] = "text"
req["action"] = "smtp-sys"
req["apiType"] = "send"
content, err := json.Marshal(msg)
if err != nil {
log.Println(err.Error())
return errors.New("Json marshal error")
}
req["content"] = string(content)
var buffer bytes.Buffer
b, e := json.Marshal(req)
if e != nil {
log.Println(e.Error())
}
buffer.Write(b)
resp, err := http.Post("http://47.93.230.163:8091/msg/v1/send", "application/json", &buffer)
if resp.StatusCode != 200 {
return errors.New("error send emain")
}
if err != nil {
logs.Error("error send email")
return err
}
return nil
}
func SendToMail(title, user string, password string, host string, to string, content string,
ifgenerate bool) error {
var content_type string
hp := strings.Split(host, ":")
auth := smtp.PlainAuth("", user, password, hp[0])
content_type = "Content-Type: text/plain" + "; charset=UTF-8"
msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + title + "\r\n" +
content_type + "\r\n\r\n" + content + "\r\n")
send_to := strings.Split(to, ";")
//检测是否是邮件地址
for k, _ := range send_to {
match, _ := regexp.MatchString("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?", send_to[k])
if !match {
return errors.New("Format Error")
}
}
err := smtp.SendMail(host, auth, user, send_to, msg)
if err != nil {
return err
}
return err
}
func (this *UserController) SendEmailCode(c *gin.Context) {
var req ReqSendEmailCode
var resp RespBase = RespBase{Msg: "邮件已经存在", Status: 0}
statusCode := 200
defer func() {
c.JSON(statusCode, resp)
}()
e := c.Bind(&req)
if nil != e {
log.Println(e.Error())
resp.Msg = "请求参数错误"
return
}
//判断邮箱是否存在
var users []model.Users
e = db.GetMysqlClient().Query2("select * from users where email_adress = ?", &users, req.EmailAdress)
if nil != e {
log.Print(e.Error())
resp.Msg = "email address error"
return
}
if len(users) != 0 {
statusCode = 422
return
}
//产生验证码
verify := CreateVerify(6)
session := sessions.Get(c)
session.Set(req.EmailAdress, verify)
session.Save()
sendcontent := make(map[string]interface{}, 1)
sendcontent["subject"] = "邮箱验证码,请注意查收"
sendcontent["receivers"] = req.EmailAdress
sendcontent["content"] = string("您本次注册的验证码为:") + verify + string(",工作人员不会向您索取,请勿泄露。请尽快完成操作。")
e = SendExternalEmail(sendcontent)
if e != nil {
log.Println(e.Error())
return
}
//成功
resp.Msg = "发送成功"
}

1
controller/webhook.go Normal file
View File

@ -0,0 +1 @@
package controller

0
db/README.md Normal file
View File

599
db/db.go Normal file
View File

@ -0,0 +1,599 @@
// 数据库工具包
package db
import (
"background/logs"
"database/sql"
"errors"
"fmt"
"reflect"
"strconv"
"sync"
"time"
)
// 数据容器抽象对象定义
type Database struct {
Type string // 用来给SqlBuilder进行一些特殊的判断 (空值或mysql 皆表示这是一个MySQL实例)
DB *sql.DB
}
// SQL异步执行队列定义
type queueList struct {
list []*QueueItem //队列列表
sleeping chan bool
loop chan bool
lock sync.RWMutex
quit chan bool
quited bool
}
// SQL异步执行队列子元素定义
type QueueItem struct {
DB *Database //数据库对象
Query string //SQL语句字符串
Params []interface{} //参数列表
}
// 缓存数据对象定义
type cache struct {
data map[string]map[string]interface{}
}
func (this *cache) Init() {
this.data["default"] = make(map[string]interface{})
}
// 设置缓存
func (this *cache) Set(key string, value interface{}, args ...string) {
var group string
if len(args) > 0 {
group = args[0]
if _, exist := this.data[group]; !exist {
this.data[group] = make(map[string]interface{})
}
} else {
group = "default"
}
this.data[group][key] = value
}
// 获取缓存数据
func (this *cache) Get(key string, args ...string) interface{} {
var group string
if len(args) > 0 {
group = args[0]
} else {
group = "default"
}
if g, exist := this.data[group]; exist {
if v, ok := g[key]; ok {
return v
}
}
return nil
}
// 删除缓存数据
func (this *cache) Del(key string, args ...string) {
var group string
if len(args) > 0 {
group = args[0]
} else {
group = "default"
}
if g, exist := this.data[group]; exist {
if _, ok := g[key]; ok {
delete(this.data[group], key)
}
}
}
var (
lastError error
Cache *cache
queue *queueList
Obj *Database
)
func init() {
Cache = &cache{data: make(map[string]map[string]interface{})}
Cache.Init()
queue = &queueList{}
go queue.Start()
}
// 关闭数据库连接
func (this *Database) Close() {
this.DB.Close()
}
// 获取最后发生的错误字符串
func LastErr() string {
if lastError != nil {
return lastError.Error()
}
return ""
}
// 执行语句
func (this *Database) Exec(query string, args ...interface{}) (sql.Result, error) {
return this.DB.Exec(query, args...)
}
// 查询单条记录
func (this *Database) Query(query string, args ...interface{}) (*sql.Rows, error) {
return this.DB.Query(query, args...)
}
// 查询单条记录
func (this *Database) QueryRow(query string, args ...interface{}) *sql.Row {
return this.DB.QueryRow(query, args...)
}
// Query2 查询实体集合
// obj 为接收数据的实体指针
func (this *Database) Query2(sql string, obj interface{}, args ...interface{}) error {
var tagMap map[string]int
var tp, tps reflect.Type
var n, i int
var err error
var ret reflect.Value
// 检测val参数是否为我们所想要的参数
tp = reflect.TypeOf(obj)
if reflect.Ptr != tp.Kind() {
return errors.New("is not pointer")
}
if reflect.Slice != tp.Elem().Kind() {
return errors.New("is not slice pointer")
}
tp = tp.Elem()
tps = tp.Elem()
if reflect.Struct != tps.Kind() {
return errors.New("is not struct slice pointer")
}
tagMap = make(map[string]int)
n = tps.NumField()
for i = 0; i < n; i++ {
tag := tps.Field(i).Tag.Get("sql")
if len(tag) > 0 {
tagMap[tag] = i + 1
}
}
// 执行查询
ret, err = this.queryAndReflect(sql, tagMap, tp, args...)
if nil != err {
return err
}
// 返回结果
reflect.ValueOf(obj).Elem().Set(ret)
return nil
}
// queryAndReflect 查询并将结果反射成实体集合
func (this *Database) queryAndReflect(sql string,
tagMap map[string]int,
tpSlice reflect.Type, args ...interface{}) (reflect.Value, error) {
var ret reflect.Value
// 执行sql语句
rows, err := this.DB.Query(sql, args...)
if nil != err {
return reflect.Value{}, err
}
defer rows.Close()
// 开始枚举结果
cols, err := rows.Columns()
if nil != err {
return reflect.Value{}, err
}
ret = reflect.MakeSlice(tpSlice, 0, 50)
// 构建接收队列
scan := make([]interface{}, len(cols))
row := make([]interface{}, len(cols))
for r := range row {
scan[r] = &row[r]
}
for rows.Next() {
feild := reflect.New(tpSlice.Elem()).Elem()
// 取得结果
err = rows.Scan(scan...)
// 开始遍历结果
for i := 0; i < len(cols); i++ {
n := tagMap[cols[i]] - 1
if n < 0 {
continue
}
switch feild.Type().Field(n).Type.Kind() {
case reflect.Bool:
if nil != row[i] {
feild.Field(n).SetBool("false" != string(row[i].([]byte)))
} else {
feild.Field(n).SetBool(false)
}
case reflect.String:
if nil != row[i] {
feild.Field(n).SetString(string(row[i].([]byte)))
} else {
feild.Field(n).SetString("")
}
case reflect.Float32:
if nil != row[i] {
//log.Println(row[i].(float32))
switch reflect.TypeOf(row[i]).Kind() {
case reflect.Slice:
v, e := strconv.ParseFloat(string(row[i].([]byte)), 0)
if nil == e {
feild.Field(n).SetFloat(float64(v))
//feild.Field(n).SetFloat(float64(row[i].(float32)))
}
break
case reflect.Float64:
feild.Field(n).SetFloat(float64(row[i].(float32)))
}
} else {
feild.Field(n).SetFloat(0)
}
case reflect.Float64:
if nil != row[i] {
//log.Println(row[i].(float32))
//v, e := strconv.ParseFloat(string(row[i].([]byte)), 0)
//if nil == e {
feild.Field(n).SetFloat(row[i].(float64))
//}
} else {
feild.Field(n).SetFloat(0)
}
case reflect.Int8:
fallthrough
case reflect.Int16:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
fallthrough
case reflect.Int:
if nil != row[i] {
byRow, ok := row[i].([]byte)
if ok {
v, e := strconv.ParseInt(string(byRow), 10, 64)
if nil == e {
feild.Field(n).SetInt(v)
}
} else {
v, e := strconv.ParseInt(fmt.Sprint(row[i]), 10, 64)
if nil == e {
feild.Field(n).SetInt(v)
}
}
} else {
feild.Field(n).SetInt(0)
}
}
}
ret = reflect.Append(ret, feild)
}
return ret, nil
}
// 执行UPDATE语句并返回受影响的行数
// 返回0表示没有出错, 但没有被更新的行
// 返回-1表示出错
func (this *Database) Update(query string, args ...interface{}) (int64, error) {
ret, err := this.Exec(query, args...)
if err != nil {
return -1, err
}
aff, err := ret.RowsAffected()
if err != nil {
return -1, err
}
return aff, nil
}
// 执行DELETE语句并返回受影响的行数
// 返回0表示没有出错, 但没有被删除的行
// 返回-1表示出错
func (this *Database) Delete(query string, args ...interface{}) (int64, error) {
return this.Update(query, args...)
}
func GenSql(obj interface{}) (string, error) {
ret := ""
typ := reflect.TypeOf(obj).Kind()
if typ != reflect.Struct {
return (""), errors.New("not a struct")
}
value := obj.(reflect.Value)
num := value.NumField()
for i := 0; i < num; i++ {
if i == 0 {
ret += "("
}
switch value.Field(i).Type().Kind() {
case reflect.String:
str := value.Field(i).Interface().(string)
if str[0] != '"' {
ret += "\""
str += "\""
ret += str
} else {
ret += value.Field(i).Interface().(string)
}
case reflect.Int:
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int))
case reflect.Int8:
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int8))
case reflect.Int32:
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int32))
case reflect.Int64:
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int64))
case reflect.Int16:
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int16))
case reflect.Bool:
if value.Field(i).Interface().(bool) {
ret += fmt.Sprintf("true")
} else {
ret += fmt.Sprintf("false")
}
case reflect.Float32:
ret += fmt.Sprintf("%x", value.Field(i).Interface().(float32))
case reflect.Float64:
ret += fmt.Sprintf("true", value.Field(i).Interface().(float64))
}
if i == num-1 {
ret += ")"
} else {
ret += ","
}
}
return ret, nil
}
func (this *Database) InsertObejct(tb_name string, obj interface{}) (int64, error) {
var tagMap map[int]string
var tp, tps reflect.Type
var n, i int
// 检测val参数是否为我们所想要的参数
tp = reflect.TypeOf(obj)
if reflect.Ptr != tp.Kind() {
return 0, errors.New("is not pointer")
}
if reflect.Slice != tp.Elem().Kind() {
return 0, errors.New("is not slice pointer")
}
tp = tp.Elem()
tps = tp.Elem()
value := reflect.ValueOf(obj).Elem()
if reflect.Struct != tps.Kind() {
return 0, errors.New("is not struct slice pointer")
}
for z := 0; z < value.Len(); z++ {
tagMap = make(map[int]string)
n = tps.NumField()
var query_struct string
for i = 0; i < n; i++ {
tag := tps.Field(i).Tag.Get("sql")
if len(tag) > 0 {
tagMap[i] = tag
}
if i == 0 {
query_struct += "("
}
query_struct += tagMap[i]
if i == n-1 {
query_struct += ")"
} else {
query_struct += ","
}
}
vs, e := GenSql(value.Index(z))
if nil != e {
logs.Error(e.Error())
}
query := "insert into " + tb_name + query_struct + "values " + vs
_, e = this.Insert(query)
if e != nil {
logs.Error(e.Error())
}
}
return 0, nil
}
// 执行INSERT语句并返回最后生成的自增ID
// 返回0表示没有出错, 但没生成自增ID
// 返回-1表示出错
func (this *Database) Insert(query string, args ...interface{}) (int64, error) {
ret, err := this.Exec(query, args...)
if err != nil {
return -1, err
}
last, err := ret.LastInsertId()
if err != nil {
return -1, err
}
return last, nil
}
type OneRow map[string]string
type Results []OneRow
// 判断字段是否存在
func (row OneRow) Exist(field string) bool {
if _, ok := row[field]; ok {
return true
}
return false
}
// 获取指定字段的值
func (row OneRow) Get(field string) string {
if v, ok := row[field]; ok {
return v
}
return ""
}
// 获取指定字段的整数值, 注意, 如果该字段不存在则会返回0
func (row OneRow) GetInt(field string) int {
if v, ok := row[field]; ok {
return Atoi(v)
}
return 0
}
// 获取指定字段的整数值, 注意, 如果该字段不存在则会返回0
func (row OneRow) GetInt64(field string) int64 {
if v, ok := row[field]; ok {
return Atoi64(v)
}
return 0
}
// 设置值
func (row OneRow) Set(key, val string) {
row[key] = val
}
// 查询不定字段的结果集
func (this *Database) Select(query string, args ...interface{}) (Results, error) {
rows, err := this.DB.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
cols, err := rows.Columns()
if err != nil {
return nil, err
}
colNum := len(cols)
rawValues := make([][]byte, colNum)
scans := make([]interface{}, len(cols)) //query.Scan的参数因为每次查询出来的列是不定长的所以传入长度固定当次查询的长度
// 将每行数据填充到[][]byte里
for i := range rawValues {
scans[i] = &rawValues[i]
}
results := make(Results, 0)
for rows.Next() {
err = rows.Scan(scans...)
if err != nil {
return nil, err
}
row := make(map[string]string)
for k, raw := range rawValues {
key := cols[k]
/*if raw == nil {
row[key] = "\\N"
} else {*/
row[key] = string(raw)
//}
}
results = append(results, row)
}
return results, nil
}
// 查询一行不定字段的结果
func (this *Database) SelectOne(query string, args ...interface{}) (OneRow, error) {
ret, err := this.Select(query, args...)
if err != nil {
return nil, err
}
if len(ret) > 0 {
return ret[0], nil
}
return make(OneRow), nil
}
// 队列入栈
func (this *queueList) Push(item *QueueItem) {
this.lock.Lock()
this.list = append(this.list, item)
this.lock.Unlock()
}
// 队列出栈
func (this *queueList) Pop() chan *QueueItem {
item := make(chan *QueueItem)
go func() {
defer close(item)
for {
switch {
case len(this.list) == 0:
timeout := time.After(time.Second * 2)
select {
case <-this.quit:
this.quited = true
return
case <-timeout:
//log.Println("SQL Queue polling")
}
default:
this.lock.Lock()
i := this.list[0]
this.list = this.list[1:]
this.lock.Unlock()
select {
case item <- i:
return
case <-this.quit:
this.quited = true
return
}
}
}
}()
return item
}
// 执行开始执行
func (this *queueList) Start() {
for {
if this.quited {
return
}
c := this.Pop()
item := <-c
item.DB.Exec(item.Query, item.Params...)
}
}
// 停止队列
func (this *queueList) Stop() {
this.quit <- true
}
// 向Sql队列中插入一条执行语句
func (this *Database) Queue(query string, args ...interface{}) {
item := &QueueItem{
DB: this,
Query: query,
Params: args,
}
queue.Push(item)
}

320
db/elasticEngine.go Normal file
View File

@ -0,0 +1,320 @@
package db
import (
"background/utils"
"encoding/json"
"reflect"
"github.com/pkg/errors"
"golang.org/x/net/context"
"gopkg.in/olivere/elastic.v7"
"qiniupkg.com/x/log.v7"
)
const (
ERROR_PTR = "null pointer error"
INPUT_TYPE_ERROR = "wrong input parameter: "
CREATED_ERROR = "create error"
DELETE_ERROR = "delete error"
INDEX_EXISTED = "index existed"
)
type ElkEngine struct {
cli *elastic.Client
}
func (p *ElkEngine) Create(index string, types string, id string, data interface{}) error {
if nil != p {
if (reflect.TypeOf(data).Kind() == reflect.String) || (reflect.TypeOf(data).Kind() == reflect.Struct) {
resp, err := p.cli.Index().
Index(index).
BodyJson(data).
Do(context.Background())
if err != nil {
log.Print("create error", err)
return err
}
log.Print(resp)
} else {
log.Print(reflect.TypeOf(data).Kind())
return errors.New(INPUT_TYPE_ERROR)
}
} else {
return errors.New(ERROR_PTR)
}
return nil
}
func (p *ElkEngine) Delete(query elastic.Query, index string) error {
if nil != p {
_, err := p.cli.DeleteByQuery().Index(index).Query(query).
Do(context.Background())
if err != nil {
log.Print(err)
return err
}
} else {
return errors.New(ERROR_PTR)
}
return nil
}
func (p *ElkEngine) QueryHighlight(index string, query elastic.Query, v interface{}, hightlight *elastic.Highlight,
limit int, offset int) ([]string, error) {
if reflect.ValueOf(v).Kind() != reflect.Ptr {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Ptr")
}
if reflect.ValueOf(v).Elem().Kind() != reflect.Slice {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Slice")
}
if reflect.ValueOf(v).Elem().Type().Elem().Kind() != reflect.Struct {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Struct")
}
eletype := reflect.ValueOf(v).Elem().Type().Elem()
obj := reflect.ValueOf(v).Elem()
objAdd := make([]reflect.Value, 0)
if nil != p {
if limit == 0 {
res, err := p.cli.Search().Index(index).Query(query).Highlight(hightlight).Do(context.TODO())
if err != nil {
print(err)
return nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
data, e := vs.Source.MarshalJSON()
if nil != e {
log.Print(e.Error())
}
mapobj := map[string]interface{}{}
mapobj["highlight"] = vs.Highlight["content"]
e = json.Unmarshal(data, &mapobj)
if nil != e {
log.Print(e.Error())
}
obj, e := utils.UnmarshalJson2StructGen(eletype, mapobj)
if nil != e {
log.Print(e.Error())
}
objAdd = append(objAdd, reflect.ValueOf(obj))
}
return id, nil
} else {
res, err := p.cli.Search(index).Query(query).Highlight(hightlight).Size(limit).From(limit * offset).Do(context.TODO())
if err != nil {
print(err)
return nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
data, e := vs.Source.MarshalJSON()
// log.Print(string(data))
if nil != e {
log.Print(e.Error())
}
mapobj := map[string]interface{}{}
e = json.Unmarshal(data, &mapobj)
if nil != e {
log.Print(e.Error())
}
mapobj["content"] = ""
mapobj["highlight"] = vs.Highlight["content"]
obj, e := utils.UnmarshalJson2StructGen(eletype, mapobj)
if nil != e {
log.Print(e.Error())
}
objAdd = append(objAdd, reflect.ValueOf(obj))
}
addOp := reflect.Append(obj, objAdd...)
obj.Set(addOp)
return id, nil
}
} else {
return nil, errors.New(ERROR_PTR)
}
}
func (p *ElkEngine) Query(index string, query elastic.Query, v interface{},
limit int, offset int) ([]string, error) {
if reflect.ValueOf(v).Kind() != reflect.Ptr {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Ptr")
}
if reflect.ValueOf(v).Elem().Kind() != reflect.Slice {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Slice")
}
if reflect.ValueOf(v).Elem().Type().Elem().Kind() != reflect.Struct {
return nil, errors.New(INPUT_TYPE_ERROR + "shoulbe be Struct")
}
eletype := reflect.ValueOf(v).Elem().Type().Elem()
obj := reflect.ValueOf(v).Elem()
objAdd := make([]reflect.Value, 0)
if nil != p {
if limit == 0 {
res, err := p.cli.Search(index).Query(query).Do(context.Background())
if err != nil {
print(err)
return nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
data, e := vs.Source.MarshalJSON()
if nil != e {
log.Print(e.Error())
}
mapobj := map[string]interface{}{}
e = json.Unmarshal(data, &mapobj)
if nil != e {
log.Print(e.Error())
}
obj, e := utils.UnmarshalJson2StructGen(eletype, mapobj)
if nil != e {
log.Print(e.Error())
}
objAdd = append(objAdd, reflect.ValueOf(obj))
}
return id, nil
} else {
res, err := p.cli.Search(index).Query(query).Size(limit).From(limit * offset).Do(context.Background())
if err != nil {
log.Print(err.Error())
return nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
data, e := vs.Source.MarshalJSON()
log.Print(string(data))
if nil != e {
log.Print(e.Error())
}
mapobj := map[string]interface{}{}
e = json.Unmarshal(data, &mapobj)
if nil != e {
log.Print(e.Error())
}
obj, e := utils.UnmarshalJson2StructGen(eletype, mapobj)
if nil != e {
log.Print(e.Error())
}
objAdd = append(objAdd, reflect.ValueOf(obj))
}
addOp := reflect.Append(obj, objAdd...)
obj.Set(addOp)
return id, nil
}
} else {
return nil, errors.New(ERROR_PTR)
}
}
func (p *ElkEngine) QueryGen(index string, query elastic.Query, typ reflect.Type,
limit int, offset int) ([]interface{}, []string, error) {
rets := []interface{}{}
if nil != p {
if limit == 0 {
res, err := p.cli.Search(index).Query(query).Do(context.Background())
if err != nil {
print(err)
return nil, nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
}
return rets, id, nil
} else {
res, err := p.cli.Search(index).Query(query).Size(limit).From(limit * offset).Do(context.Background())
if err != nil {
print(err)
return nil, nil, err
}
id := []string{}
for _, vs := range res.Hits.Hits {
id = append(id, vs.Id)
data, e := vs.Source.MarshalJSON()
if nil != e {
log.Print(e.Error())
}
mapobj := map[string]interface{}{}
e = json.Unmarshal(data, &mapobj)
if nil != e {
log.Print(e.Error())
}
obj, e := utils.UnmarshalJson2StructGen(typ, mapobj)
if nil != e {
log.Print(e.Error())
}
rets = append(rets, obj)
}
return rets, id, nil
}
} else {
return nil, nil, errors.New(ERROR_PTR)
}
}
func (p *ElkEngine) Update(index string, types string, id string, data map[string]interface{}) error {
if nil != p {
_, err := p.cli.Update().
Index(index).
Id(id).
Doc(data).
Do(context.Background())
if err != nil {
println(err.Error())
return err
}
}
return errors.New(ERROR_PTR)
}
func (p *ElkEngine) CreateIndex(index string, typemaping string) error {
if nil != p {
exists, err := p.cli.IndexExists(index).Do(context.Background())
if err != nil {
// Handle error
log.Print(err)
return err
}
if exists {
return errors.New(INDEX_EXISTED)
}
createIndex, err := p.cli.CreateIndex(index).Body(typemaping).Do(context.Background())
if err != nil {
log.Print(err)
return err
}
if !createIndex.Acknowledged {
return errors.New("create index error")
// Not acknowledged
}
return nil
}
return errors.New(ERROR_PTR)
}
func (p *ElkEngine) IndexExisted(index string) (bool, error) {
if nil != p {
exists, err := p.cli.IndexExists(index).Do(context.Background())
if exists {
return true, nil
}
if err != nil {
// Handle error
log.Print(err)
return false, err
}
return false, nil
}
return false, nil
}

76
db/mssql.go Normal file
View File

@ -0,0 +1,76 @@
package db
import (
"database/sql"
_ "github.com/denisenkom/go-mssqldb"
)
// ProcExec 执行存储过程, 返回受影响的行数
func (this *Database) ExecProc(procname string, params ...interface{}) (int64, error) {
result, err := this.Exec("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
if err != nil {
return 0, err
}
affected, err := result.RowsAffected()
if err != nil {
return 0, err
}
lastinsertid, err := result.LastInsertId()
if err != nil {
return affected, nil
}
return lastinsertid, nil
}
// GetExecProcErr 执行存储过程, 返回是否在执行过程中出现错误
func (this *Database) GetExecProcErr(procname string, params ...interface{}) error {
_, err := this.ExecProc(procname, params...)
if err != nil {
return err
}
return nil
}
// ProcQuery 通过存储过程查询记录
func (this *Database) ProcQuery(procname string, params ...interface{}) (rows *sql.Rows, err error) {
rows, err = this.Query("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
return
}
// ProcQueryRow 通过存储过程查询单条记录
func (this *Database) ProcQueryRow(procname string, params ...interface{}) *sql.Row {
return this.QueryRow("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
}
// ProcStatus 调用存储过程并获取最终的执行状态码和提示信息
func (this *Database) ProcStatus(procname string, params ...interface{}) (int, string) {
var status int
var msg string
err := this.QueryRow("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...).Scan(&status, &msg)
if err != nil {
return -99, err.Error()
}
return status, msg
}
// ProcSelect 通过存储过程查询结果集
func (this *Database) ProcSelect(procname string, params ...interface{}) (Results, error) {
return this.Select("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
}
// ProcSelectOne 通过存储查询一行不定字段的结果
func (this *Database) ProcSelectOne(procname string, params ...interface{}) (OneRow, error) {
return this.SelectOne("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
}
// GetProcPlaceholder 按照指定数量生成调用存储过程时所用的参数占位符
func (this *Database) GetProcPlaceholder(count int) (placeholder string) {
placeholder = ""
for i := 0; i < count; i++ {
if i > 0 {
placeholder += ","
}
placeholder += "?"
}
return
}

226
db/sqlManager.go Normal file
View File

@ -0,0 +1,226 @@
package db
import (
"background/config"
"background/logs"
"crypto/tls"
"crypto/x509"
"database/sql"
"fmt"
"io/ioutil"
"log"
"os"
"time"
"github.com/go-sql-driver/mysql"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"gopkg.in/mgo.v2"
"gopkg.in/olivere/elastic.v7"
)
var gEla ElkEngine
var gDb Database
var blogDb Database
var gMongo *mgo.Session
var gElkEngine ElkEngine
var gOrm *gorm.DB
func Init() {
var e error
mysqlconf := config.GetMysqlConfig()
log.Print("api runmode is " + config.ApiConfig().RunMode)
if config.ApiConfig().RunMode == "debug" {
gDb = Database{Type: string(""), DB: initMysqlTLS(mysqlconf)}
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("pem/ca.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("pem/client-cert.pem", "pem/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
InsecureSkipVerify: true,
})
// try to connect to mysql database.
cfg := mysql.Config{
User: config.GetMysqlBlogConfig().UserName,
Passwd: config.GetMysqlBlogConfig().Password,
Addr: config.GetMysqlBlogConfig().Addr, //IP:PORT
Net: "tcp",
DBName: "background",
Loc: time.Local,
AllowNativePasswords: true,
}
cfg.TLSConfig = "custom"
str := cfg.FormatDSN()
gOrm, e = gorm.Open("mysql", str)
if nil != e {
log.Print(e.Error())
os.Exit(-1)
}
} else {
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("pem/ca.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("pem/client-cert.pem", "pem/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
log.Print("client cert is ", clientCert)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
})
// try to connect to mysql database.
cfg := mysql.Config{
User: config.GetMysqlBlogConfig().UserName,
Passwd: config.GetMysqlBlogConfig().Password,
Addr: config.GetMysqlBlogConfig().Addr, //IP:PORT
Net: "tcp",
DBName: "background",
Loc: time.Local,
AllowNativePasswords: true,
}
cfg.TLSConfig = "custom"
str := cfg.FormatDSN()
log.Print(str)
gOrm, e = gorm.Open("mysql", str)
if nil != e {
log.Print(e.Error())
os.Exit(-1)
}
}
}
func InitELK() {
var e error
elkconf := config.GetElkConfig()
gElkEngine.cli, e = elastic.NewClient(
elastic.SetURL(elkconf.Address),
// Must turn off sniff in docker
elastic.SetSniff(false),
elastic.SetBasicAuth(elkconf.User, elkconf.Password),
)
log.Print("init elk cli is ",gElkEngine.cli,elkconf)
if nil != e {
logs.Error(e.Error())
gElkEngine.cli = nil
}
}
func initMysql(mysqlconf *config.MysqlConfig) *sql.DB {
cnn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8", mysqlconf.UserName, mysqlconf.Password,
mysqlconf.Addr, mysqlconf.Db)
log.Print("Connect to mysql " + cnn)
_db, err := sql.Open("mysql", cnn)
if err != nil {
fmt.Println("connect sql server ", err.Error())
os.Exit(200)
}
e := _db.Ping()
if nil != e {
fmt.Println("ping mysql server error", e.Error())
os.Exit(200)
}
return _db
}
func initMysqlTLS(mysqlconf *config.MysqlConfig) *sql.DB {
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("pem/ca.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("pem/client-cert.pem", "pem/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
InsecureSkipVerify: true,
})
cnn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8&tls=custom", mysqlconf.UserName, mysqlconf.Password,
mysqlconf.Addr, mysqlconf.Db)
log.Print("Connect to mysql " + cnn)
_db, err := sql.Open("mysql", cnn)
if err != nil {
fmt.Println("connect sql server ", err.Error())
os.Exit(200)
}
e := _db.Ping()
if nil != e {
fmt.Println(e.Error())
os.Exit(200)
}
return _db
}
func initMongoDb(conf *config.MongoConfig) *mgo.Session {
var url string
if conf.UserName == "" {
url = fmt.Sprintf("mongodb://%s:%d/%s", conf.Addr, conf.Port, conf.Db)
} else {
url = fmt.Sprintf("mongodb://%s:%s@%s:%d/%s", conf.UserName, conf.Password, conf.Addr, conf.Port, conf.Db)
}
log.Print("connect to url " + url)
logs.Debug("connect to url " + url)
mgo, err := mgo.Dial(url)
if nil != err {
logs.Error(err.Error())
return nil
}
return mgo
}
func GetMysqlClient() *Database {
return &gDb
}
func GetBlogMysql() *Database {
return &blogDb
}
func GetMongoDb() *mgo.Session {
return gMongo
}
func InitMongoDb() {
mongoConf := config.GetMongoDBConfig()
gMongo = initMongoDb(mongoConf)
if gMongo == nil {
log.Print("error mongo initial")
os.Exit(25)
}
}
func GetElastic() *ElkEngine {
return &gElkEngine
}
func GetOrm() *gorm.DB {
return gOrm
}

542
db/sql_builder.go Normal file
View File

@ -0,0 +1,542 @@
package db
import (
"database/sql"
"errors"
"fmt"
"log"
"math/big"
"reflect"
"strconv"
"strings"
"git.jiaxianghudong.com/go/utils"
)
const (
_ = iota
TYPE_INSERT
TYPE_DELETE
TYPE_UPDATE
TYPE_SELECT
TYPE_INSERTUPDATE
)
var (
WrapSymbol = "`"
DBType = "mysql"
)
// SQL语句构造结构
type SB struct {
db *Database
t int
field, table, where, group, order, limit string
values SBValues
values2 SBValues
ignore bool
fullsql bool
debug bool
unsafe bool //是否进行安全检查, 专门针对无限定的UPDATE和DELETE进行二次验证
args []interface{}
}
// Exec返回结果
type SBResult struct {
Success bool //语句是否执行成功
Code int //错误代码
Msg string //错误提示信息
LastID int64 //最后产生的ID
Affected int64 //受影响的行数
Sql string //最后执行的SQL
}
// 值对象
type SBValues map[string]interface{}
// 增量值
type IncVal struct {
Val int64
BaseField string // 为空表示对当前字段累加
}
// 向值对象中加入值
func (v SBValues) Add(key string, val interface{}) {
v[key] = val
}
// 删除值对象中的某个值
func (v SBValues) Del(key string) {
delete(v, key)
}
// 判断指定键是否存在
func (v SBValues) IsExist(key string) bool {
if _, exist := v[key]; exist {
return true
}
return false
}
// 获取键的整形值
func (v SBValues) Get(key string) interface{} {
if val, exist := v[key]; exist {
return val
}
return nil
}
// 获取键的字符串值
func (v SBValues) GetString(key string) string {
if val, exist := v[key]; exist {
if trueVal, ok := val.(string); ok {
return trueVal
}
}
return ""
}
// 获取键的整形值
func (v SBValues) GetInt(key string) int {
if val, exist := v[key]; exist {
if trueVal, ok := val.(int); ok {
return trueVal
}
}
return 0
}
// 获取键的无符号整形值
func (v SBValues) GetUint(key string) uint {
if val, exist := v[key]; exist {
if trueVal, ok := val.(uint); ok {
return trueVal
}
}
return 0
}
// 获取键的64位整形值
func (v SBValues) GetInt64(key string) int64 {
if val, exist := v[key]; exist {
if trueVal, ok := val.(int64); ok {
return trueVal
}
}
return 0
}
// 返回绑定完参数的完整的SQL语句
func FullSql(str string, args ...interface{}) (string, error) {
if !strings.Contains(str, "?") {
return str, nil
}
sons := strings.Split(str, "?")
var ret string
var argIndex int
var maxArgIndex = len(args)
for _, son := range sons {
ret += son
if argIndex < maxArgIndex {
switch v := args[argIndex].(type) {
case int:
ret += strconv.Itoa(v)
case int8:
ret += strconv.Itoa(int(v))
case int16:
ret += strconv.Itoa(int(v))
case int32:
ret += utils.I64toA(int64(v))
case int64:
ret += utils.I64toA(v)
case uint:
ret += utils.UitoA(v)
case uint8:
ret += utils.UitoA(uint(v))
case uint16:
ret += utils.UitoA(uint(v))
case uint32:
ret += utils.Ui32toA(v)
case uint64:
ret += utils.Ui64toA(v)
case float32:
ret += utils.F32toA(v)
case float64:
ret += utils.F64toA(v)
case *big.Int:
ret += v.String()
case bool:
if v {
ret += "true"
} else {
ret += "false"
}
case string:
ret += "'" + strings.Replace(strings.Replace(v, "'", "", -1), `\`, `\\`, -1) + "'"
case nil:
ret += "NULL"
default:
return "", errors.New(fmt.Sprintf("invalid sql argument type: %v => %v (sql: %s)", reflect.TypeOf(v).String(), v, str))
}
argIndex++
}
}
return ret, nil
}
// 构建SQL语句
// param: returnFullSql 是否返回完整的sql语句(即:绑定参数之后的语句)
func (q *SB) ToSql(returnFullSql ...bool) (str string, err error) {
q.args = make([]interface{}, 0)
switch q.t {
case TYPE_INSERT:
if q.table == "" {
err = errors.New("table cannot be empty.")
return
}
if len(q.values) == 0 {
err = errors.New("values cannot be empty.")
return
}
if q.ignore {
str = "INSERT IGNORE INTO " + q.table
} else {
str = "INSERT INTO " + q.table
}
var fields, placeholder string
for k, v := range q.values {
fields += "," + WrapSymbol + k + WrapSymbol
placeholder += ",?"
q.args = append(q.args, v)
}
str += " (" + utils.Substr(fields, 1) + ") VALUES (" + utils.Substr(placeholder, 1) + ")"
case TYPE_DELETE:
if q.table != "" {
if q.where == "" && !q.unsafe {
err = errors.New("deleting all data is not safe.")
return
}
str = "DELETE " + q.table
if q.table != "" {
str += " FROM " + q.table
}
if q.where != "" {
str += " WHERE " + q.where
}
}
case TYPE_UPDATE:
if q.table != "" {
if q.where == "" && !q.unsafe {
err = errors.New("updating all data is not safe.")
return
}
str = "UPDATE " + q.table
str += " SET " + utils.Substr(q.buildUpdateParams(q.values), 1)
if q.where != "" {
str += " WHERE " + q.where
}
}
case TYPE_INSERTUPDATE:
if q.table != "" {
str = "INSERT INTO " + q.table
var fields, placeholder string
for k, v := range q.values {
fields += "," + WrapSymbol + k + WrapSymbol
placeholder += ",?"
q.args = append(q.args, v)
}
str += " (" + utils.Substr(fields, 1) + ") VALUES (" + utils.Substr(placeholder, 1) + ") ON DUPLICATE KEY UPDATE "
placeholder = q.buildUpdateParams(q.values2)
str += utils.Substr(placeholder, 1)
}
case TYPE_SELECT:
str = "SELECT " + q.field
if q.table != "" {
str += " FROM " + q.table
}
if q.where != "" {
str += " WHERE " + q.where
}
if q.group != "" {
str += " GROUP BY " + q.group
}
if q.order != "" {
str += " ORDER BY " + q.order
}
if q.limit != "" && (q.db.Type == "" || q.db.Type == "mysql") {
str += " LIMIT " + q.limit
}
}
if len(returnFullSql) == 1 && returnFullSql[0] {
str, err = FullSql(str, q.args...)
}
return
}
// 构造Update更新参数
func (q *SB) buildUpdateParams(vals SBValues) string {
var placeholder string
for k, v := range vals {
if iv, ok := v.(IncVal); ok {
placeholder += "," + WrapSymbol + k + WrapSymbol + "=" + utils.Ternary(iv.BaseField == "", k, iv.BaseField).(string)
if iv.Val >= 0 {
placeholder += "+" + utils.I64toA(iv.Val)
} else {
placeholder += utils.I64toA(iv.Val)
}
} else {
placeholder += "," + WrapSymbol + k + WrapSymbol + "=?"
q.args = append(q.args, v)
}
}
return placeholder
}
// 设置数据库对象
func (q *SB) DB(db *Database) *SB {
q.db = db
return q
}
// 设置FROM字句
func (q *SB) From(str string) *SB {
q.table = str
return q
}
// 设置表名
func (q *SB) Table(str string) *SB {
return q.From(str)
}
// 设置WHERE字句
func (q *SB) Where(str string) *SB {
q.where = str
return q
}
// 设置GROUP字句
func (q *SB) Group(str string) *SB {
q.group = str
return q
}
// 设置GROUP字句
func (q *SB) Order(str string) *SB {
q.order = str
return q
}
// 设置LIMIT字句
func (q *SB) Limit(count int, offset ...int) *SB {
if len(offset) > 0 {
q.limit = utils.Itoa(offset[0]) + "," + utils.Itoa(count)
} else {
q.limit = "0," + utils.Itoa(count)
}
return q
}
// 设置安全检查开关
func (q *SB) Unsafe(unsefe ...bool) *SB {
if len(unsefe) == 1 && !unsefe[0] {
q.unsafe = false
} else {
q.unsafe = true
}
return q
}
// 是否Debug
func (q *SB) Debug(debug ...bool) *SB {
if len(debug) == 1 && !debug[0] {
q.debug = false
} else {
q.debug = true
}
return q
}
// 设置值
func (q *SB) Value(m SBValues) *SB {
q.values = m
return q
}
// 设置值2
func (q *SB) Value2(m SBValues) *SB {
q.values2 = m
return q
}
// 添加值
func (q *SB) AddValue(key string, val interface{}) *SB {
q.values.Add(key, val)
return q
}
// 添加值2
func (q *SB) AddValue2(key string, val interface{}) *SB {
q.values2.Add(key, val)
return q
}
// 获取一个值对象
func NewValues() SBValues {
return SBValues{}
}
// 构建INSERT语句
func Insert(ignore ...bool) *SB {
var i bool
if len(ignore) == 1 && ignore[0] {
i = true
}
return &SB{t: TYPE_INSERT, db: Obj, ignore: i, values: SBValues{}, args: make([]interface{}, 0)}
}
// 构建DELETE语句
func Delete() *SB {
return &SB{t: TYPE_DELETE, db: Obj}
}
// 构建UPDATE语句
func Update() *SB {
return &SB{t: TYPE_UPDATE, db: Obj, values: SBValues{}, args: make([]interface{}, 0)}
}
// 构建InsertUpdate语句, 仅针对MySQL有效, 内部使用ON DUPLICATE KEY UPDATE方式实现
func InsertUpdate() *SB {
return &SB{t: TYPE_INSERTUPDATE, db: Obj, values: SBValues{}, values2: SBValues{}, args: make([]interface{}, 0)}
}
// 构建SELECT语句
func Select(str ...string) *SB {
fields := "*"
if len(str) == 1 {
fields = str[0]
}
return &SB{t: TYPE_SELECT, db: Obj, field: fields}
}
// 获取构造SQL后的参数
func (q *SB) GetArgs() []interface{} {
return q.args
}
//
func (q *SB) FullSql(yes ...bool) *SB {
if len(yes) == 1 {
q.fullsql = yes[0]
} else {
q.fullsql = true
}
return q
}
// 执行INSERT、DELETE、UPDATE语句
func (q *SB) Exec(args ...interface{}) *SBResult {
var err error
sbRet := &SBResult{}
sbRet.Sql, err = q.ToSql()
if err != nil {
sbRet.Msg = err.Error()
} else {
if q.debug {
log.Println("\n\tSQL prepare statement:\n\t", sbRet.Sql, "\n\tMap args:\n\t", q.args, "\n\tParams:\n\t", args)
}
var ret sql.Result
var err error
if q.fullsql {
var sqlStr string
sqlStr, err = FullSql(sbRet.Sql, append(q.args, args...)...)
if err == nil {
ret, err = q.db.Exec(sqlStr)
}
} else {
ret, err = q.db.Exec(sbRet.Sql, append(q.args, args...)...)
}
if err != nil {
sbRet.Msg = err.Error()
} else {
sbRet.Success = true
switch q.t {
case TYPE_INSERT:
if DBType == "mysql" {
last, err := ret.LastInsertId()
if err == nil {
sbRet.LastID = last
}
}
case TYPE_DELETE:
fallthrough
case TYPE_UPDATE:
fallthrough
case TYPE_INSERTUPDATE:
aff, err := ret.RowsAffected()
if err == nil {
sbRet.Affected = aff
}
}
}
}
return sbRet
}
// 查询记录集
func (q *SB) Query(args ...interface{}) (Results, error) {
s, e := q.ToSql()
if e != nil {
return nil, e
}
if q.debug {
log.Println("\n\tSQL prepare statement:\n\t", s, "\n\tParams:\n\t", args)
}
return q.db.Select(s, args...)
}
// 查询单行数据
func (q *SB) QueryOne(args ...interface{}) (OneRow, error) {
q.Limit(1, 0)
s, e := q.ToSql()
if e != nil {
return nil, e
}
if q.debug {
log.Println("\n\tSQL prepare statement:\n\t", s, "\n\tParams:\n\t", args)
}
return q.db.SelectOne(s, args...)
}
// 查询记录集
func (q *SB) QueryAllRow(args ...interface{}) (*sql.Rows, error) {
s, e := q.ToSql()
if e != nil {
return nil, e
}
if q.debug {
log.Println("\n\tSQL prepare statement:\n\t", s, "\n\tParams:\n\t", args)
}
return q.db.Query(s, args...)
}
// 查询单行数据
func (q *SB) QueryRow(args ...interface{}) *sql.Row {
s, e := q.ToSql()
if e != nil {
return nil
}
if q.debug {
log.Println("\n\tSQL prepare statement:\n\t", s, "\n\tParams:\n\t", args)
}
return q.db.QueryRow(s, args...)
}

63
db/utils.go Normal file
View File

@ -0,0 +1,63 @@
package db
import (
"database/sql"
"strconv"
"strings"
)
// 根据传入的字段列表生成相符数量的占位符
func GetPlaceholderByFields(fileds string) string {
fileds = strings.Replace(fileds, " ", "", -1)
fileds = strings.Trim(fileds, ",")
count := len(strings.Split(fileds, ","))
ret := make([]string, count)
for i := 0; i < count; i++ {
ret[i] = "?"
}
return strings.Join(ret, ",")
}
// Atoi 转换成整型
func Atoi(s string, d ...int) int {
i, err := strconv.Atoi(s)
if err != nil {
if len(d) > 0 {
return d[0]
} else {
return 0
}
}
return i
}
// Atoi64 转换成整型int64
func Atoi64(s string, d ...int64) int64 {
i, err := strconv.ParseInt(s, 10, 64)
if err != nil {
if len(d) > 0 {
return d[0]
} else {
return 0
}
}
return i
}
// 返回一个带有Null值的数据库字符串
func NewNullString(s string) sql.NullString {
if len(s) == 0 {
return sql.NullString{}
}
return sql.NullString{
String: s,
Valid: true,
}
}
// 返回一个带有Null值的数据库整形
func NewNullInt64(s int64, isNull bool) sql.NullInt64 {
return sql.NullInt64{
Int64: s,
Valid: !isNull,
}
}

57
docs/docs.go Normal file
View File

@ -0,0 +1,57 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// 2021-01-27 22:40:54.1593671 +0800 CST m=+0.052880501
package docs
import (
"bytes"
"github.com/alecthomas/template"
"github.com/swaggo/swag"
)
var doc = `{
"swagger": "2.0",
"info": {
"description": "{{.Description}}",
"title": "大厅功能api",
"contact": {},
"license": {},
"version": "1.0"
},
"host": "localhost:8080",
"basePath": "/api/v1",
"paths": {}
}`
type swaggerInfo struct {
Version string
Host string
BasePath string
Title string
Description string
}
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo swaggerInfo
type s struct{}
func (s *s) ReadDoc() string {
t, err := template.New("swagger_info").Parse(doc)
if err != nil {
return doc
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, SwaggerInfo); err != nil {
return doc
}
return tpl.String()
}
func init() {
swag.Register(swag.Name, &s{})
}

113
files/file/test Normal file

File diff suppressed because one or more lines are too long

27
id_rsa_local Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA1Ekg7QR6yjJWv82QpBdxYkwalhAbcLD2b4l4yx787vQKJvG/
Ylf8lmk+yVbxhFcrpZi0DtwbpyatqR4yvHmK7gBVotK5nVLPEZASIRB330k2ud1p
aUYVExf/8O3MS9WIPfQ3rz20protDS2LAufKq2FRGl+HLRqK2+FGfHxAy+SvuteC
CXYP+YwPewJ5e3Lw5i7DguW2Yxz2qx+tTZzkcv44z40MOjRZQtRYs6k2mJLr2VIh
rgjCClziAYNZbKnj8ZvRf/QFul10ouAz8n8uDmUfw2RfM+RFj5xwXDqbNFhAciKF
U0jFPmcRfLT9ldpVG58Nap2xZ06NMkduDFaR1QIDAQABAoIBABfgPbbKuTDCpqUd
7rW1+Uev/ZGBMETlcmIrGQ3nZ1VM11N3/ymFceBM6AXnJHTZBQyz9xRwxx9upzuN
LPGrzedk3Dza7It4Q9fa118mpgTUDDatY2y2uCoUmfG0HTUuSAuHyzeHfij+aZDA
3ZCvF0ldQazwr5hwEswWM0JPC06jLnUi6MY+RSLZtpJqxJFOJyQPHTyqLlcWXp1c
+I9kw+VJqO3IR7hsldAGnRa0JzO1B5wdZY/lCv7K/+JiLSCxCRWByYnHQIB+26Q8
PBLJfIqXn9CGqW9HDuH/qQ/D+vh0FWAoWjIY2FWNTVSSaEUnWHW1tPWO971xbOar
PdVgo8UCgYEA8MamKKfXoOxDJ0dr9gTP6g6/n7zt9M1kv9KOvYSEIxVeiaCqbd/o
eJTTTqx4AIg3T0N7cMXx+0RPBWKLjLvObglSvjuC4rcBX9qKzb1IBZMrQFhTzeww
GBWvp12c2FWMpE/+p+m6AcQPFLau1d8ndQC8XpOYbBJYqnfFAqOcsHMCgYEA4bVR
RQ7+NTiZZewQzQVAM8940b9AELoO18wcuvtx5iTI+Lo3sPqIgl1YNZHCY4f/QHCS
hqEUEj/JEk0j7K6yw5TDOLjd1Ymmm8cNh9x1hed51SH5ittleOjNG9ABlh9A76b+
lin/wybLVQdTrfaMD1Y8BZaHOQXfeO+A6KBiCpcCgYEAmbRmrDuBhsRsli2c+P/X
bradk667RXS9JUuYPdnTtMXWhQtg4SV4NUnknyuwq75JeLs+mR50PJA91dUz+tKF
lG81OCWrh2mGYheUVoTH7m8lxDzeuu1VQnrNmI1FLEFouBgtHCozyR7M9c8tS3Da
snGWztVwD0Wi/qfYx7eEtosCgYApHUA6liqUQ0UeHcxJrGUviuF1Q6NF6L5/bLzn
CpqK07SQKkuuv1RSevJwf6arPsCuWlM2luzzDg9weADNQl1p5xVQpcwy86oXwkCi
uPPnemzk+BVex+xKBA4ovNEtKXBIt2C0td3TDKQJTxZdIAYPXSP92Je1OW6ltusC
dQSm7QKBgEQs8OvuKGESk+TvpUBCcfpwCWpkmhhXQV54miRRhhz0Vc+DeWQsjOGl
xBIooPUI5DU70PhIsbV9g2lfoIa2BiXove6F5Rq6B+I75CIvJpqlxa56ikLVnAZE
tqWT5XeC/bs6BszNyL+5tLUNCL3AhVHNfyBR6Ik60kBG6v1hQvnb
-----END RSA PRIVATE KEY-----

148
logs/logs.go Normal file
View File

@ -0,0 +1,148 @@
package logs
import (
"fmt"
"os"
"runtime"
"time"
)
const (
LOG_ERROR = iota
LOG_WARING
LOG_INFO
LOG_DEBUG
)
var log *mylog
/*
*
*/
func init() {
log = newMylog()
}
func Init(dir string, file string, level int, savefile bool) {
log.setDir(dir)
log.setFile(file)
log.setLevel(level)
log.setSavefile(savefile)
}
func Error(err ...interface{}) {
log.write(LOG_ERROR, fmt.Sprint(err...))
}
func Waring(war ...interface{}) {
log.write(LOG_WARING, fmt.Sprint(war...))
}
func SetLevel(level int) {
log.setLevel(level)
}
func Info(info ...interface{}) {
log.write(LOG_INFO, fmt.Sprint(info...))
}
func Debug(deb ...interface{}) {
log.write(LOG_DEBUG, fmt.Sprint(deb...))
}
/*
*
*/
type mylog struct {
log chan string // 日志chan
dir string // 日志存放目录
file string // 日志文件名
savefile bool // 是否保存到文件
level int // 日志级别
}
func newMylog() *mylog {
log := &mylog{}
log.log = make(chan string, 100)
log.dir = "/opt/logs"
log.file = "out"
log.savefile = false
go log.run()
return log
}
func (l *mylog) setDir(dir string) {
l.dir = dir
}
func (l *mylog) setFile(file string) {
l.file = file
}
func (l *mylog) setSavefile(b bool) {
l.savefile = b
}
func (l *mylog) setLevel(level int) {
l.level = level
}
func (l *mylog) getLevelString(level int) string {
switch level {
case LOG_ERROR:
return "ERROR"
case LOG_WARING:
return "WARING"
case LOG_INFO:
return "INFO"
case LOG_DEBUG:
return "DEBUG"
}
return "unknown"
}
func (l *mylog) write(level int, str string) {
// 判断级别
if level > l.level {
return
}
// 输出日志
pc, _, line, _ := runtime.Caller(2)
p := runtime.FuncForPC(pc)
t := time.Now()
str = fmt.Sprintf("[%04d-%02d-%02d %02d:%02d:%02d] [%s] %s(%d): %s\n",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(),
l.getLevelString(level), p.Name(), line, str)
// 输出到控制台
if false == l.savefile {
fmt.Print(str)
return
}
// 输出到文件
l.log <- str
}
func (l *mylog) run() {
for {
str := <-l.log
// 判断文件夹是否存在
_, err := os.Stat(l.dir)
if nil != err {
os.MkdirAll(l.dir, os.ModePerm)
}
// 获取时间
t := time.Now()
path := fmt.Sprintf("%s/%s-%04d-%02d-%02d.log", l.dir, l.file,
t.Year(), t.Month(), t.Day())
fp, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModePerm)
if nil == err {
fp.WriteString(str)
fp.Close()
}
}
}

257
main.go Normal file
View File

@ -0,0 +1,257 @@
package main
import (
"background/config"
"background/controller"
"background/controller/middle"
"background/db"
_ "background/docs"
"background/logs"
"background/model"
"log"
"strconv"
"tcptemplate/logger"
"tcptemplate/network"
"github.com/gin-gonic/gin"
ginSwagger "github.com/swaggo/gin-swagger" // gin-swagger middleware
"github.com/swaggo/gin-swagger/swaggerFiles"
sessions "github.com/tommy351/gin-sessions"
)
// @title 大厅功能api
// @version 1.0
// @host localhost:8080
// @BasePath /api/v1
var (
userController = controller.UserController{}
mailContoller = controller.MailController{}
fileController = controller.FileController{}
planController = controller.PlanController{}
openapiController = controller.OpenApiController{}
)
func CORSMiddleware(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
if config.ApiConfig().RunMode == "release" {
c.Writer.Header().Set("Access-Control-Allow-Origin", "https://testingcloud.club")
} else {
c.Writer.Header().Set("Access-Control-Allow-Origin", "https://testingcloud.club")
}
c.Writer.Header().Set("Access-Control-Max-Age", "86400")
c.Writer.Header().Set("Access-Control-Allow-Headers",
"X-Requested-With,"+
" Content-Type, Origin, Authorization,"+
"Accept,Client-Security-Token, Accept-Encoding,"+
"x-access-token,Access-Control-Request-Method,"+
"Access-Control-Request-Headers")
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
log.Print("remote addr is ", c.Request.RemoteAddr)
if c.Request.Method == "OPTIONS" {
log.Println("OPTIONS")
c.AbortWithStatus(200)
} else {
c.Next()
}
}
func InitConfig() {
e := config.Init("user.yaml")
if nil != e {
log.Println(e.Error())
}
}
func InitMysql() {
c := config.GetMysqlConfig()
if c == nil {
logs.Error("cannnot connect mysql server")
} else {
db.Init()
}
}
func InitRedisConfig() {
e := config.InitRedis()
if nil != e {
logs.Error(e.Error())
return
}
}
func InitElasticSearch() {
e := db.GetElastic().CreateIndex("hardware", model.HardwareTypeMapping())
if nil != e {
}
}
func InitLogs() {
logs.Init(config.GetLogConfig().Dir, config.GetLogConfig().File, config.GetLogConfig().Level, config.GetLogConfig().SaveFile)
}
type WsHandle struct {
}
func (this WsHandle) OnDisConected(*network.ConnectionContext) {
}
func (this WsHandle) OnConected(c *network.ConnectionContext) {
log.Print(c.IpAdress, c.Cnntime)
}
func (this WsHandle) OnDataRecv(p *network.ConnectionContext, dat []byte) {
log.Print(p.IpAdress)
logger.LogRealeaseInfo(string(dat))
}
func main() {
InitConfig()
InitLogs()
InitRedisConfig()
InitMysql()
db.InitELK()
r := gin.Default()
store := sessions.NewCookieStore([]byte("secret123"))
r.Use(sessions.Middleware("sess_store", store))
r.Use(CORSMiddleware) // Cross domain
go func() {
server := network.ServerFactory("0.0.0.0", config.ApiConfig().WsServerConf)
server.SetHandle(WsHandle{})
e := server.Run()
if nil != e {
}
}()
go func() {
// programatically set swagger info
r := gin.New()
// use ginSwagger middleware to serve the API docs
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":9992")
}()
api := r.Group("/api")
{
/** 添加或修改用户 **/
api.POST("/user", userController.SetUser)
/** 删除用户 **/
api.DELETE("/user", userController.DelUser)
/** 获取单独用户详情信息 methods(id) **/
api.GET("/user", middle.AuthMiddle, userController.GetUser)
/** 获取所有用户 **/
api.GET("/users", middle.AuthMiddle, userController.Users)
api.POST("/search_users", middle.AuthMiddle, userController.SerarchUsers)
/** 用户登录 **/
api.POST("/login", userController.Login)
/** 用户注册 **/
api.POST("/register", userController.Register)
/** 用户退出登陆 **/
api.GET("/logout/:token", userController.Logout)
api.POST("/verify", mailContoller.OnSendEmailCode)
/** 修改密码**/
api.POST("modify_pass", middle.AuthMiddle, userController.ModifyPasswd)
api.GET("/article/:id", controller.GetArticle) //获取文章
api.POST("/articles", controller.GetArticles) // 获取所有文章
api.GET("/articles_tree", controller.GetArticlesTree) // 获取所有文章
api.PUT("/article", controller.AddArticle) // 添加文章
api.PUT("/article_file", controller.AddArticle) // 添加文章
api.PUT("/article_tree", controller.AddArticleTree) // 添加文章
api.PUT("/article_tree_history", controller.AddArticleHistory) // 添加文章
api.PUT("/article_search", controller.SearchArticles) // 添加文章
api.GET("/article_type", controller.ArticlesType) //获取所有文章分类
api.PUT("/article_type", controller.AddArticleType) // 添加文章分类
api.DELETE("/article_type", controller.DeleteArticleType) // 删除文章分类
api.POST("/doc_search_term", controller.SearchArticleES) // 文章内容搜索,基于es的倒排
api.POST("/doc_match_search_hightlight", controller.SearchArticleESHightLight) // 文章内容搜索,基于es的倒排
api.POST("/article_update", controller.UpdateArtilce) //更新文章
api.POST("/article_update_tree", controller.UpdateArtilceTree) //更新文章
api.GET("/articleCount", controller.GetArticleCount) //获取所有文章个数
api.DELETE("/article/:id", controller.DeleteArticle) ////删除文章
api.DELETE("/article_tree/:id", controller.DeleteArticleTree) ////删除文章
api.GET("/article_history", controller.GetArticleHistory) // 历史
api.POST("/image_upload", fileController.OnUpload) // 上传图片,如果图片太大自动裁减为原来的一半
api.POST("/image_upload_origin", fileController.OnUploadOrigin) // 上传图片
api.GET("/image_download/:file", fileController.OnDownLoad) // 下载图片
api.GET("/image_thumbnail/:file", fileController.OnThumbnail) // 下载图片
api.GET("/doc_types", controller.ArticlesTypes) // 获取所有的文章类型
api.POST("/hardware", controller.AddHardware) // 新增硬件
api.GET("/hardware", controller.ReadHardWare) // 读取硬件
api.DELETE("/hardware", controller.DeleteHardWare) // 读取硬件
api.POST("/upload_doc", fileController.OnFileUploadFileMarkdown) // 上传文件
api.PUT("/file", fileController.OnFileUploadFile) // 上传文件
api.GET("/file", fileController.DownloadFile) // 下载 文件
api.GET("/filelist", fileController.FileList) // 文件列表
api.GET("/fileType", fileController.FileType) // 文件类型
api.PUT("/memo", controller.CreateMemo) // 备忘录新建
api.POST("/memo", controller.UpdateMemo) // 备忘录更新
api.POST("/memos", controller.GetMemos) // 备忘录批量
api.POST("/delmemo", controller.DeleteMemos) //删除备忘录
api.GET("/memo", controller.GetMemo) // 单独读取备忘录
api.GET("/memocnt", controller.GetMemoCnt) // 单独读取备忘录
api.GET("doc_groups", controller.GetDocGroup) // 获取所有的文章分组
api.POST("type_group", controller.GetDocTypeGroup) // 获取类所在的组
api.POST("group_type", controller.GetDoGroupcType) // 获取类所在的组
api.GET("doc_versions", nil) // 获取文章的某个版本
api.PUT("/book", controller.CreateBook) //新建书籍
api.POST("/book", controller.UpdateBook) // 更新书籍
api.POST("/getbook", controller.GetBook) // 单书籍数据
api.POST("/getbooks", controller.GetPageBook) // 批量书籍
api.POST("/delbook", controller.Delbook) // 删除书籍
api.GET("/bookcount", controller.BookCount) // 书籍名称
api.POST("/get_plans", planController.GetPlanDates) // 获取当天的所有计划
api.PUT("/plan", planController.AddPlan) // 添加计划
api.DELETE("/plan", planController.DelPlan) // 删除计划
api.POST("/plan_days", planController.PlanDay) // 获取本月有计划天数
api.GET("/plan_types", planController.Types)
api.PUT("/undo", planController.CreateUndo) // 新增待办事项
api.POST("/undo", planController.UpdateUndo) // 更新待办事项
api.POST("/undo_finish/:id", planController.FinishUndo) // 完成待办事项
api.POST("/undo_unfinish/:id", planController.UnFinishUndo) // 已完成事项改未完成
api.GET("/undo", planController.GetUndo) // 获得待办事项
api.GET("/done", planController.GetDone) // 获得待办事项
api.DELETE("/undo/:id", planController.DeleteUndo) // 删除待办事项
api.PUT("/doc_template", controller.CreateDocTemplate) // 创建文章模板
api.POST("/doc_template", controller.UpdateDocTemplate) // 更新文章模板
api.POST("/get_doc_template", controller.GetDocTemplate) // 获得文章模板
api.DELETE("/doc_template/:id", controller.DeleteDocTemplate) // 删除文章模板
api.GET("/doc_template/:id", controller.GetDocTemplateId) //获得单个文章模板信息
}
openapi := r.Group("openapi")
{
openapi.POST("/diff") // 比较两个文档差异
openapi.POST("/ddl2orm", openapiController.DDL2ORM) // sql ddl转gorm 结构体
openapi.POST("/ddl2markdown", openapiController.DDL2Markdown) // sql ddl转markdown 文档
openapi.POST("/ui2css", openapiController.UI2CSS) // qt ui文件转css文档
openapi.POST("/duilib_xml2cpp", openapiController.DuilibXml2Cpp) // duilib to cpp
}
e := r.Run(":" + strconv.Itoa(config.GetPort()))
if nil != e {
log.Print(e.Error())
}
}

340
model/blog.go Normal file
View File

@ -0,0 +1,340 @@
package model
import (
"background/db"
"background/logs"
"fmt"
"strings"
"time"
"github.com/pkg/errors"
"qiniupkg.com/x/log.v7"
)
type Doc struct {
ID int64 `json:"id" gorm:"column:id" sql:"id"`
Title string `json:"title" gorm:"column:title" sql:"title"`
Type int32 `json:"type" gorm:"column:type" sql:"type"`
Content string `json:"content" gorm:"column:content" sql:"content"`
Author string `json:"author" gorm:"column:author" sql:"author"`
CreateTime time.Time `json:"create_time" gorm:"column:create_time" sql:"create_time"`
UpdateTime time.Time `json:"update_time" gorm:"column:update_time" sql:"update_time"`
DeleteTime time.Time `json:"delete_time" gorm:"column:delete_time" sql:"delete_time"`
Version int32 `json:"version" gorm:"column:version" sql:"version"`
IsPublic int32 `json:"is_public" gorm:"column:is_public" sql:"is_public"`
Deleted int32 `json:"deleted" gorm:"column:deleted" sql:"deleted"`
OriginUrl string `json:"origin_url" gorm:"column:origin_url" sql:"origin_url"`
EsId string `json:"es_id" gorm:"column:es_id" sql:"es_id"`
DeletedAt time.Time `json:"deleted_at" gorm:"column:deleted_at" sql:"deleted_at"`
Father int32 `json:"father" gorm:"column:father" sql:"father"`
Level int32 `json:"level" gorm:"column:level" sql:"level"`
}
type DocTree struct {
ID int64 `json:"id" gorm:"column:id" sql:"id"`
Title string `json:"title" gorm:"column:title" sql:"title"`
Type int32 `json:"type" gorm:"column:type" sql:"type"`
Content string `json:"content" gorm:"column:content" sql:"content"`
Author string `json:"author" gorm:"column:author" sql:"author"`
CreateTime time.Time `json:"create_time" gorm:"column:create_time" sql:"create_time"`
UpdateTime time.Time `json:"update_time" gorm:"column:update_time" sql:"update_time"`
DeleteTime time.Time `json:"delete_time" gorm:"column:delete_time" sql:"delete_time"`
Version int32 `json:"version" gorm:"column:version" sql:"version"`
IsPublic int32 `json:"is_public" gorm:"column:is_public" sql:"is_public"`
Deleted int32 `json:"deleted" gorm:"column:deleted" sql:"deleted"`
OriginUrl string `json:"origin_url" gorm:"column:origin_url" sql:"origin_url"`
EsId string `json:"es_id" gorm:"column:es_id" sql:"es_id"`
DeletedAt time.Time `json:"deleted_at" gorm:"column:deleted_at" sql:"deleted_at"`
Father int32 `json:"father" gorm:"column:father" sql:"father"`
Level int32 `json:"level" gorm:"column:level" sql:"level"`
}
// 设置User的表名为`profiles`
func (DocTree) TableName() string {
return "doc_copy1"
}
type DocType struct {
Id int32 `json:"id" gorm:"column:id" sql:"id"`
TypeName string `json:"type_name" gorm:"column:type_name" sql:"type_name"`
Group int32 `json:"group" gorm:"column:group" sql:"group"`
}
type DocHistory struct {
ID int32 `json:"id" gorm:"column:id" sql:"id"`
Title string `json:"title" gorm:"column:title" sql:"title"`
DocId int32 `json:"doc_id" gorm:"column:doc_id" sql:"doc_id"`
Content string `json:"content" gorm:"column:content" sql:"content"`
EditTime string `json:"edit_time" gorm:"column:edit_time" sql:"edit_time"`
}
type DocGroup struct {
Int int32 `sql:"int"`
Name string `sql:"name"`
}
type ArticleType struct {
Id int64 `sql:"id" json:"id"`
Name string `sql:"type_name" json:"type_name"`
Author string `sql:"author" json:"author"`
Group int32 `sql:"group" json:"group"`
GroupName string `json:"group_name"`
}
func GetArticlesType() []ArticleType {
ret := []ArticleType{}
sql := fmt.Sprintf("select * from doc_type")
e := db.GetMysqlClient().Query2(sql, &ret)
log.Print(ret)
for k, _ := range ret {
group := []DocGroup{}
sql = fmt.Sprintf("select * from doc_group where doc_group.int = %d", ret[k].Group)
db.GetMysqlClient().Query2(sql, &group)
if len(group) > 0 {
ret[k].GroupName = group[0].Name
}
}
if nil != e {
logs.Error(e.Error())
return nil
}
return ret
}
/*
CreateDoc
*/
func CreateDoc(doc Doc) error {
sql := fmt.Sprintf(`INSERT INTO doc ( doc.title, doc.content, doc.author, doc.type,doc.is_public,doc.create_time) SELECT
'%s',
'%s',
'%s',
%d ,
%d,
'%s'
FROM
DUAL
WHERE
NOT EXISTS ( SELECT * FROM doc WHERE doc.title = '%s' );`, doc.Title, strings.Replace(doc.Content, "'", "\\'", -1),
doc.Author, doc.Type, doc.IsPublic, time.Now().Format("2006-01-02 15:04:05"), doc.Title)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
log.Print(sql)
logs.Error(e.Error())
return e
}
return nil
}
/*
CreateDoc
*/
func CreateDocTree(doc DocTree) error {
sql := fmt.Sprintf(`INSERT INTO doc_copy1 ( doc_copy1.title, doc_copy1.content,
doc_copy1.author, doc_copy1.type,doc_copy1.is_public,doc_copy1.create_time,father,level) SELECT
'%s',
'%s',
'%s',
%d ,
%d,
'%s',
%d,
%d
FROM
DUAL
WHERE
NOT EXISTS ( SELECT * FROM doc_copy1 WHERE doc_copy1.title = '%s' );`, doc.Title, strings.Replace(doc.Content, "'", "\\'", -1),
doc.Author, doc.Type, doc.IsPublic, time.Now().Format("2006-01-02 15:04:05"), doc.Father, doc.Level, doc.Title)
_, e := db.GetMysqlClient().Query(sql)
log.Print(sql)
if nil != e {
log.Print(sql)
logs.Error(e.Error())
return e
}
return nil
}
func GetIdFromTitle(title string) int {
motors := []DocTree{}
db.GetOrm().LogMode(true)
db.GetOrm().Model(&DocTree{}).Find(&motors, fmt.Sprintf("title = '%s'", title))
if len(motors) == 0 {
return -1
}
db.GetOrm().LogMode(false)
return int(motors[0].ID)
}
/*
UpdateDoc
*/
func UpdateDoc(doc Doc) error {
sql := fmt.Sprintf(`update doc set doc.author = '%s' ,doc.title = '%s',doc.type = '%d',doc.content = '%s' ,doc.update_time = '%s' ,doc.version = '%d' where doc.id = '%d'; `,
doc.Author, doc.Title, doc.Type,
strings.Replace(doc.Content, "'", "\\'", -1), time.Now().Format("2006-01-02 15:04:05"), doc.Version, doc.ID)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
// sql = fmt.Sprintf(`insert into doc_history(title,doc_id,content,edit_time) values('%s',%d,'%s','%s');`,
// doc.Title,doc.ID,strings.Replace(doc.Content, "'", "\\'", -1), time.Now().Format("2006-01-02 15:04:05"))
// _, er := db.GetMysqlClient().Query(sql)
// if nil != er {
// logs.Error(e.Error())
// return e
// }
return nil
}
// 添加文件版本。
func InsertDocHistory(doc DocTree) error {
sql := fmt.Sprintf(`insert into doc_history(title,doc_id,content,edit_time) values('%s',%d,'%s','%s');`,
doc.Title, doc.ID, strings.Replace(doc.Content, "'", "\\'", -1), time.Now().Format("2006-01-02 15:04:05"))
_, er := db.GetMysqlClient().Query(sql)
if nil != er {
logs.Error(er.Error())
return er
}
return nil
}
/*
UpdateDoc
*/
func UpdateDocTree(doc DocTree) error {
sql := fmt.Sprintf(`update doc_copy1 set doc_copy1.author = '%s' ,doc_copy1.title = '%s',
doc_copy1.type = '%d',doc_copy1.content = '%s' ,doc_copy1.update_time = '%s' ,
doc_copy1.version = '%d' where doc_copy1.id = '%d'; `,
doc.Author, doc.Title, doc.Type,
strings.Replace(doc.Content, "'", "\\'", -1), time.Now().Format("2006-01-02 15:04:05"), doc.Version, doc.ID)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
/*
DeleteDoc
*/
func DeleteDoc(id int64) error {
sql := fmt.Sprintf(`delete from doc where id = %d`, id)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
/*
DeleteDoc
*/
func DeleteDocTree(id int64) error {
sql := fmt.Sprintf(`delete from doc_copy1 where id = %d`, id)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
/*
AddArticleType
*/
func AddArticleType(t ArticleType) error {
sql := fmt.Sprintf("insert into doc_type(id,type_name,`group`) values ('%d','%s','%d')", t.Id, t.Name, t.Group)
log.Print(sql)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
/*
UpdateArticleType
*/
func UpdateArticleType(t ArticleType) error {
sql := fmt.Sprintf("update doc_type set type_name = '%s' and group = '%d' where id = %d", t.Name, t.Group, t.Id)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
/*
DeleteArticleType
*/
func DeleteArticleType(id int32) error {
sql := fmt.Sprintf("delete from doc_type where id = '%d'", id)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func GetAllDocs() ([]DocTree, error) {
ret := []DocTree{}
sql := fmt.Sprintf("select * from doc_copy1")
e := db.GetMysqlClient().Query2(sql, &ret)
if nil != e {
logs.Error(e.Error())
return nil, e
}
return ret, nil
}
func GetAllGroup() ([]DocGroup, error) {
ret := []DocGroup{}
sql := fmt.Sprintf("select * from doc_group")
e := db.GetMysqlClient().Query2(sql, &ret)
if nil != e {
logs.Error(e.Error())
return nil, e
}
return ret, nil
}
func GetTypeGroup(id int32) (DocGroup, error) {
ret := []DocGroup{}
sql := fmt.Sprintf("select * from doc_group where doc_group = ?", id)
e := db.GetMysqlClient().Query2(sql, &ret)
if nil != e {
logs.Error(e.Error())
return DocGroup{}, e
}
if len(ret) > 0 {
return ret[0], nil
} else {
return DocGroup{}, errors.New("no existed")
}
}
func GetGroupTypes(id int32) ([]ArticleType, error) {
ret := []ArticleType{}
sql := fmt.Sprintf("select * from doc_type where doc_type.group = %d", id)
log.Print(sql)
e := db.GetMysqlClient().Query2(sql, &ret)
if nil != e {
logs.Error(e.Error())
return nil, e
}
if len(ret) > 0 {
return ret, nil
} else {
return nil, errors.New("no existed")
}
}

22
model/book.go Normal file
View File

@ -0,0 +1,22 @@
package model
import "background/utils"
// Book sss
type Book struct {
ID int64 `gorm:"column:id;primaryKey;default:0" sql:"id" json:"id"`
BookName string `gorm:"column:book_name" sql:"book_name" json:"book_name"`
Author string `gorm:"column:author" sql:"author" json:"author"`
Title string `gorm:"column:title" sql:"title" json:"title"`
Tag string `gorm:"column:tag" sql:"tag" json:"tag"`
Content string `gorm:"column:content" sql:"content" json:"content"`
CreateTime utils.OrmTime ` gorm:"column:create_time" sql:"create_time" json:"create_time"`
}
// 设置User的表名为`profiles`
func (Book) TableName() string {
return "book"
}
// ReadHistory sss
type ReadHistory struct {
ID int64 `sql:"id" json:"id"`
}

49
model/file.go Normal file
View File

@ -0,0 +1,49 @@
package model
import (
"background/db"
"background/logs"
"fmt"
"log"
)
type File struct {
ID int64 `sql:"id" json:"id"`
Filename string `sql:"filename" json:"filename"`
Size int64 `sql:"size" json:"size"`
Types string `sql:"types" json:"types"`
}
func GetFiles() ([]File,error){
ret := []File{}
sql := fmt.Sprintf("select * from files")
e := db.GetBlogMysql().Query2(sql, &ret)
log.Print(ret)
if nil != e {
logs.Error(e.Error())
return nil,e
}
return ret,nil
}
func DeleteFiles(id int) error{
sql := fmt.Sprintf("delete from files where id = '%d'",id)
_,e := db.GetBlogMysql().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func AddFile(f File) error{
sql := fmt.Sprintf("insert into files(filename,size,types) values(%s,%d,%d)",f.Filename,
f.Size,f.Types)
var ret map[string]interface{}
e := db.GetBlogMysql().Query2(sql, &ret)
if nil != e{
logs.Error(e.Error())
return e
}
return nil
}

101
model/hardware.go Normal file
View File

@ -0,0 +1,101 @@
package model
import (
"background/db"
"background/utils"
"reflect"
"github.com/pkg/errors"
"gopkg.in/olivere/elastic.v3"
"qiniupkg.com/x/log.v7"
)
const (
ERR_COLUMN_EXISTED = "column_existed"
)
func HardwareTypeMapping() string {
return `"mappings":{
"hardware":{
"properties":{
"id":{"type":"keyword"},
"name":{"type":"keyword"},
"desc":{"type":"text"},
"pic":{"type":"doc"},
"doc":{"type":"doc"}
}
}
}`
}
// this api is based on elasticsearch
type Hardware struct {
ID string `json:"_id,omitempty"`
BuyDate string `json:"buy_date,omitempty"` //购入时间
Name string `json:"name,omitempty"` // 名字
Desc string `json:"desc,omitempty"` // 描述
Pic string `json:"pic,omitempty"` // 图片
Doc string `json:"doc,omitempty"` //文档资料
}
func (this *Hardware) CreateHardware() error {
if nil == this {
return errors.New(utils.ERRNULLPOINTER)
}
log.Print(this.Name)
matchPhraseQuery := elastic.NewMatchQuery("name", this.Name)
existedHardware, e := QueryHardwares(matchPhraseQuery, 10, 0)
log.Print(e, existedHardware)
for _, v := range existedHardware {
if v.Name == this.Name {
log.Print(v.ID)
return errors.New(ERR_COLUMN_EXISTED)
}
}
e = db.GetElastic().Create("hardware_data", "0", "", *this)
if nil != e {
log.Print("shit1")
log.Print(e.Error())
return e
}
log.Print("shit2")
return nil
}
func GetHardwares(limit int, size int) ([]Hardware, error) {
var ret []Hardware
ids, e := db.GetElastic().Query("hardware_data", nil, reflect.TypeOf(Hardware{}), limit, size)
if nil != e {
return nil, e
}
i := 0
for _, v := range ids {
ret[i].ID = v
i++
}
return ret, nil
}
func QueryHardwares(query elastic.Query, limit int, offset int) ([]Hardware, error) {
ret := []Hardware{}
ids, e := db.GetElastic().Query("hardware_data", query, ret, limit, offset)
if nil != e {
return nil, e
}
i := 0
for _, v := range ids {
ret[i].ID = v
i++
}
return ret, nil
}
func DeleteHardware(name string) error {
query := elastic.NewTermQuery("name", name)
err := db.GetElastic().Delete(query, "hardware_data")
if err != nil {
return err
}
return nil
}

93
model/memo.go Normal file
View File

@ -0,0 +1,93 @@
package model
import (
"background/db"
"background/logs"
"fmt"
"strings"
"qiniupkg.com/x/log.v7"
)
type Memo struct {
ID int64 `sql:"id" json:"id"`
Title string `sql:"title" json:"title"`
CreateTime string `sql:"create_time" json:"create_time"`
Content string `sql:"content" json:"content"`
}
func CreateMemo(memo Memo) error {
sql := fmt.Sprintf(`insert into memo(title,create_time,content) select '%s','%s','%s'
from dual where not exists (select * from memo where memo.title='%s') `,
memo.Title, memo.CreateTime, strings.Replace(memo.Content, "'", "\\'", -1), memo.Title)
log.Print(sql)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func UpdateMemo(memo Memo) error {
sql := fmt.Sprintf(`update memo set title = '%s',
create_time = '%s',
content = '%s' where memo.id = %d`,
memo.Title, memo.CreateTime, strings.Replace(memo.Content, "'", "\\'", -1), memo.ID)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func DeleteMemo(id int32) error {
sql := fmt.Sprintf(`delete from memo where memo.id = '%d'`, id)
log.Print(sql)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func ReadMemo(id int32) ([]Memo, error) {
memo := []Memo{}
sql := fmt.Sprintf(`select * from memo where memo.id = '%d'`, id)
e := db.GetMysqlClient().Query2(sql, &memo)
if nil != e {
logs.Error(e.Error())
return nil, e
}
return memo, nil
}
func MemoCnt() int {
sql := fmt.Sprintf(`select count(*) from memo`)
type Count struct {
Count int32 `sql:"count(*)"`
}
cnts := []Count{}
e := db.GetMysqlClient().Query2(sql, &cnts)
if nil != e {
logs.Error(e.Error())
return 0
}
return int(cnts[0].Count)
}
func GetMemos(title string, limit int, offset int) ([]Memo, error) {
memo := []Memo{}
sql := fmt.Sprintf(`select * from memo where memo.title like '%s%%' limit %d offset %d`,
title, limit, offset)
log.Print(sql)
e := db.GetMysqlClient().Query2(sql, &memo)
if nil != e {
logs.Error(e.Error())
return nil, e
}
return memo, nil
}

106
model/model.go Normal file
View File

@ -0,0 +1,106 @@
package model
import (
"background/db"
"background/logs"
"background/utils"
"crypto/md5"
"fmt"
"log"
"time"
"github.com/jinzhu/gorm"
)
type Plan struct {
ID uint32 `gorm:"column:id;primary_key" json:"id"`
StartTime utils.OrmTime `gorm:"column:start_time" json:"start_time"`
EndTime utils.OrmTime `gorm:"column:end_time" json:"end_time"`
Date string `gorm:"column:date" json:"date"`
Content string `gorm:"column:content" json:"content"`
Type uint32 `gorm:"column:type" json:"type"`
}
type Undo struct {
model gorm.Model
ID int32 `json:"id" gorm:"column:id" sql:"id"`
Content string `json:"content" gorm:"column:content" sql:"content"`
SpendTime int32 `json:"spend_time" gorm:"column:spend_time" sql:"spend_time"`
Parent int32 `json:"parent" gorm:"column:parent" sql:"parent"`
Level int32 `json:"level" gorm:"column:level" sql:"level"`
Type int32 `json:"type" gorm:"column:type" sql:"type"`
Done int `json:"done" gorm:"done" sql:"done"`
DeletedAt *time.Time `json:"deleted_at"`
CreateTime string `json:"create_time"`
FinishTime string `json:"finish_time"`
}
type PlanType struct {
ID uint32 `gorm:"column:id;primary_key" json:"id"`
TypeName string `gorm:"column:type_name;" json:"type_name"`
}
func (m *Undo) TableName() string {
return "undo"
}
func (m *PlanType) TableName() string {
return "plan_type"
}
func (m *Plan) TableName() string {
return "plan"
}
type Users struct {
ID int64 `sql:"id" json:"id"`
UserName string `sql:"user_name" json:"user_name"`
UserPwd string `sql:"user_pwd" json:"user_pwd"`
CreatedDate string `sql:"created_date" json:"created_date"`
UpdatedDate string `sql:"updated_date" json:"updated_date"`
DisplayName string `sql:"display_name" json:"display_name"`
EmailAddress string `sql:"email_address" json:"email_address"`
Tel string `sql:"tel" json:"tel"`
Avatar string `sql:"avatar" json:"avatar"`
}
func GetUsers(limit int32, offsetPage int32, name string) ([]Users, int32) {
users := []Users{}
var query string
if name != "" {
log.Println(name)
query = fmt.Sprintf("select * from users where user_name like '%s' limit %d offset %d",
"%%"+name+"%%", limit, offsetPage*limit)
log.Printf(query)
} else {
query = fmt.Sprintf("select * from users limit %d offset %d", limit, offsetPage*limit)
}
err := db.GetMysqlClient().Query2(query, &users)
if nil != err {
logs.Error(err.Error())
}
type Count struct {
Count int32 `sql:"count"`
}
cnts := []Count{}
query = fmt.Sprintf("select count(*) as count from users")
err = db.GetMysqlClient().Query2(query, &cnts)
if nil != err {
logs.Error(err.Error())
}
return users, cnts[0].Count
}
func ModyfyPassword(UserName string, Password string) error {
h := md5.New()
h.Write([]byte(Password))
query := fmt.Sprintf("update users set user_pwd = '%s' where user_name = '%s' ",
utils.ByteSliceToString(h.Sum(nil)), UserName)
n, err := db.GetMysqlClient().Update(query)
if nil != err {
logs.Error(err.Error())
return err
}
if n == 0 {
return nil
}
return nil
}

191
model/port.go Normal file
View File

@ -0,0 +1,191 @@
package model
import (
"background/db"
"strings"
"ubntgo/logger"
"github.com/go-openapi/errors"
json "github.com/json-iterator/go"
"gopkg.in/olivere/elastic.v3"
"qiniupkg.com/x/log.v7"
)
type Field struct {
Field string `sql:"Field"`
Type string `sql:"Type"`
Key string `sql:"Key"`
}
func MysqlToElasticSearchMapping(types string, Key string) string {
if Key == "PRI" {
return "keyword"
}
if strings.Contains(types, "int(") {
return "integer"
}
if strings.Contains(types, "longblob") {
return "text"
}
if strings.Contains(types, "varchar") {
return "text"
}
if strings.Contains(types, "datetime") {
return "date"
}
return ""
}
/*
"settings":{
"number_of_shards":1,
"number_of_replicas":0
},
"mappings":{
"properties":{
"user":{
"type":"keyword"
},
"message":{
"type":"text",
"store": true,
"fielddata": true
},
"tags":{
"type":"keyword"
},
"location":{
"type":"geo_point"
},
"suggest_field":{
"type":"completion"
}
}
}
*/
// 不同类型db之间进行缓存
func QueryDocument(query elastic.Query, limit int, offset int) ([]Hardware, error) {
var ret []Hardware
ids, e := db.GetElastic().Query("doc", query, ret, limit, offset)
if nil != e {
return nil, e
}
i := 0
for _, v := range ids {
ret[i].ID = v
i++
}
return ret, nil
}
func InsertDocToElaticSearch(doc DocTree) error {
matchPhraseQuery := elastic.NewMatchQuery("title", doc.Title)
existedHardware, e := QueryHardwares(matchPhraseQuery, 10, 0)
log.Print(e, existedHardware)
for _, v := range existedHardware {
if v.Name == doc.Title {
log.Print(v.ID)
return errors.New(200, "existed title")
}
}
e = db.GetElastic().Create("doc", "0", "", doc)
if nil != e {
log.Print(e.Error())
return e
}
return nil
}
func CreateIndexFromMysqlTable(tblname string) error {
columns := []Field{}
e := db.GetMysqlClient().Query2("describe "+tblname, &columns)
if nil != e {
logger.Debug(e.Error())
return e
}
if existed, _ := db.GetElastic().IndexExisted(tblname); existed {
log.Print("index not existed , create " + tblname)
} else {
props := map[string]interface{}{}
mapping := map[string]interface{}{
"settings": map[string]interface{}{
"analysis": map[string]interface{}{
"analyzer": map[string]interface{}{
"default": map[string]interface{}{
"type": "smartcn",
},
},
},
},
"mappings": map[string]interface{}{
"properties": props,
},
}
for _, v := range columns {
props[v.Field] = map[string]string{"type": MysqlToElasticSearchMapping(v.Type, v.Key)}
}
dat, e := json.Marshal(mapping)
if nil != e {
log.Print(e.Error())
}
e = db.GetElastic().CreateIndex(tblname, string(dat))
if nil != e {
log.Print(e.Error())
}
log.Print(string(dat))
}
return nil
}
func PortDocumentToElasticsearch(tblname string) error {
ret, e := GetAllDocs()
if nil != e {
log.Print(e.Error())
}
columns := []Field{}
e = db.GetMysqlClient().Query2("describe "+tblname, &columns)
if nil != e {
logger.Debug(e.Error())
return e
}
if existed, _ := db.GetElastic().IndexExisted(tblname); !existed {
props := map[string]interface{}{}
mapping := map[string]interface{}{
"settings": map[string]interface{}{
"analysis": map[string]interface{}{
"analyzer": map[string]interface{}{
"default": map[string]interface{}{
"type": "ik_smart",
// "type": "smartcn",
},
},
},
},
"mappings": map[string]interface{}{
"properties": props,
},
}
for _, v := range columns {
props[v.Field] = map[string]string{"type": MysqlToElasticSearchMapping(v.Type, v.Key)}
}
dat, e := json.Marshal(mapping)
if nil != e {
log.Print(e.Error())
}
log.Print(string(dat))
e = db.GetElastic().CreateIndex(tblname, string(dat))
if nil != e {
log.Print(e.Error())
}
log.Print(string(dat))
for _, v := range ret {
e := InsertDocToElaticSearch(v)
if nil != e {
log.Print(e.Error())
}
}
}
return nil
}

71
model/template.go Normal file
View File

@ -0,0 +1,71 @@
package model
import (
"background/db"
"background/logs"
"fmt"
"log"
)
type DocTemplate struct {
Id int32 `sql:"id" json:"id"`
Content string `sql:"content" json:"content"`
Name string `sql:"name" json:"name"`
}
func CreateDocTemplate(templ DocTemplate) error{
sql := fmt.Sprintf(`insert into doc_template(content,name) values('%s','%s')`,templ.Content,templ.Name)
log.Print(sql)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
log.Print(sql)
return e
}
return nil
}
func UpdateDocTemplate(templ DocTemplate) error{
sql := fmt.Sprintf(`update doc_template set content = '%s',name = '%s' where doc_template.id = %d`,templ.Content,templ.Name,templ.Id)
log.Print(sql)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
log.Print(e.Error())
return e
}
return nil
}
func DeleteDocTemplate(id int32) error{
sql := fmt.Sprintf(`delete from doc_template where id = '%d'`,id)
_, e := db.GetMysqlClient().Query(sql)
if nil != e {
logs.Error(e.Error())
return e
}
return nil
}
func ReadDocTemplate(id int32) ([]DocTemplate,error){
memo := []DocTemplate{}
sql := fmt.Sprintf(`select * from doc_template where doc_template.id = '%d'`,id)
e := db.GetMysqlClient().Query2(sql,&memo)
if nil != e {
logs.Error(e.Error())
return nil,e
}
return memo,nil
}
func GetDocTemplate(title string,limit int,offset int) ([]DocTemplate,error) {
memo := []DocTemplate{}
sql := fmt.Sprintf(`select * from doc_template limit %d offset %d`,
limit,offset)
log.Print(sql)
e := db.GetMysqlClient().Query2(sql,&memo)
if nil != e {
logs.Error(e.Error())
return nil,e
}
return memo,nil
}

4
mq/mq.go Normal file
View File

@ -0,0 +1,4 @@
package mq
type mq struct {
}

View File

@ -1,91 +0,0 @@
{
"name": "backgroun-front",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"alpha": "vue-cli-service build && node upload.js",
"analyz": "NODE_ENV=production; npm_config_report=true npm run build"
},
"dependencies": {
"@vue/cli-service-global": "^3.2.1",
"babel-polyfill": "^6.26.0",
"babel-runtime": "^6.26.0",
"core-js": "^2.6.5",
"cpm": "^0.2.0",
"element-ui": "^2.13.2",
"eslint-plugin-html": "^6.2.0",
"file-loader": "^3.0.1",
"js-cookie": "^2.2.0",
"markdown-it": "^8.4.2",
"mavon-editor": "^2.9.1",
"npm": "^6.10.2",
"scp2": "^0.5.0",
"scriptjs": "^2.5.9",
"uglifyjs-webpack-plugin": "^2.2.0",
"vue": "^2.5.2",
"vue-proportion-directive": "^1.1.0",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.11.2"
},
"devDependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.1.1",
"@vue/cli-service": "^3.2.0",
"axios": "^0.21.1",
"babel-eslint": "^10.0.1",
"babel-plugin-component": "^1.1.1",
"babel-plugin-import": "^1.8.0",
"babel-plugin-transform-runtime": "^6.23.0",
"compression-webpack-plugin": "^1.1.12",
"css-loader": "^2.0.2",
"eslint": "^5.14.1",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-vue": "^5.0.0-0",
"image-webpack-loader": "^4.1.0",
"less": "^3.9.0",
"less-loader": "^4.0.6",
"node-sass": "^6.0.1",
"sass-loader": "^7.1.0",
"vue-cli-plugin-axios": "0.0.4",
"vue-cli-plugin-webpack-bundle-analyzer": "^1.3.0",
"vue-template-compiler": "^2.5.17",
"webpack-chain": "^6.0.0"
},
"peerDependencies": {
"css-loader": "*"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"extends": "standard"
},
"parser": "babel-eslint"
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"mode": "production"
}

View File

@ -1,13 +0,0 @@
/*
* @Author: your name
* @Date: 2021-11-06 16:40:19
* @LastEditTime: 2021-11-06 16:40:19
* @LastEditors: your name
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \background-front\postcss.config.js
*/
module.exports = {
plugins: {
'autoprefixer': { browsers: 'last 5 version' }
}
}

51
process.ui Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Process</class>
<widget class="QDialog" name="Process">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>324</width>
<height>88</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QProgressBar" name="progressBar">
<property name="geometry">
<rect>
<x>30</x>
<y>50</y>
<width>281</width>
<height>31</height>
</rect>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>120</x>
<y>30</y>
<width>121</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>正在加载数据</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.png">
<title>后台系统</title>
</head>
<body>
<noscript>
<strong>We're sorry but untitled2 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

426
redis/redis.go Normal file
View File

@ -0,0 +1,426 @@
package redis
import (
"errors"
"fmt"
// "errors"
"strconv"
"time"
"gopkg.in/redis.v3"
)
const maxConn = 100
var redisChan chan *redis.Client
var option *redis.Options
func Init(addr string, pwd string, db int64) error {
option = &redis.Options{
Addr: addr,
Password: pwd,
DB: db,
}
redisChan = make(chan *redis.Client, maxConn)
for i := 0; i < maxConn; i++ {
client, err := creatRedisClient(option)
if err != nil {
return err
}
redisChan <- client
}
return nil
}
// 创建redis对象
func creatRedisClient(option *redis.Options) (*redis.Client, error) {
client := redis.NewClient(option)
// 检测client有效性
if nil != client {
_, err := client.Ping().Result()
if nil != err {
client.Close()
return nil, errors.New(fmt.Sprintf("fail to ping redis-svr,addr :%s , pwd :%s ,DB :%d", option.Addr, option.Password, option.DB))
}
} else {
return nil, errors.New(fmt.Sprintf("fail to connect redis-svr,,addr :%s , pwd :%s ,DB :%d", option.Addr, option.Password, option.DB))
}
return client, nil
}
// 获取redis
func getRedis() (*redis.Client, error) {
var client *redis.Client
select {
case <-time.After(time.Second * 10):
case client = <-redisChan:
}
// 检测client有效性
if nil != client {
_, err := client.Ping().Result()
if nil != err {
client.Close()
// 尝试3次重连
for i := 0; i < 3; i++ {
client, err = creatRedisClient(option)
if client != nil {
return client, err
}
}
return nil, err
}
}
return client, nil
}
// 将redis链接放回连接池
func relaseRedis(client *redis.Client) {
select {
case <-time.After(time.Second * 10):
client.Close()
case redisChan <- client:
}
}
func Get(key string) (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.Get(key).Result()
if nil != err {
if err.Error() == "redis: nil" {
return "", nil
}
return "", err
}
return val, nil
}
// redis查询
func Keys(key string) ([]string, error) {
client, err := getRedis()
if err != nil {
return nil, err
}
if client == nil {
return nil, errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.Keys(key).Result()
if nil != err {
var nullResult = []string{""}
return nullResult, err
}
return val, nil
}
func Set(key string, val string, expire ...time.Duration) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
var t time.Duration = 0
if len(expire) == 1 {
t = expire[0]
}
_, err = client.Set(key, val, t).Result()
return err
}
func HSet(key string, filed, val string) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.HSet(key, filed, val).Result()
return err
}
func SIsMember(key string, val int32) (bool, error) {
client, err := getRedis()
if err != nil {
return false, err
}
if client == nil {
return false, errors.New("failed to get rds client")
}
defer relaseRedis(client)
isExist, err := client.SIsMember(key, val).Result()
return isExist, err
}
func SAdd(key string, members ...string) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.SAdd(key, members...).Result()
return err
}
func SRem(key string, members ...string) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.SRem(key, members...).Result()
return err
}
func SMembers(key string) ([]string, error) {
client, err := getRedis()
if err != nil {
return nil, err
}
if client == nil {
return nil, errors.New("failed to get rds client")
}
defer relaseRedis(client)
members, err := client.SMembers(key).Result()
return members, err
}
func HIncrBy(key, filed string, val int64) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.HIncrBy(key, filed, val).Result()
return err
}
func LPush(key string, val ...string) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.LPush(key, val...).Result()
return err
}
func BRPopLPush(source string, dest string, time time.Duration) (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.BRPopLPush(source, dest, time).Result()
return val, err
}
func RPop(key string) (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.RPop(key).Result()
return val, err
}
func LLen(key string) (int64, error) {
client, err := getRedis()
if err != nil {
return 0, err
}
if client == nil {
return 0, errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.LLen(key).Result()
return val, err
}
func LTrim(key string, start, stop int64) (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.LTrim(key, start, stop).Result()
return val, err
}
func LRange(key string, start, stop int64) ([]string, error) {
client, err := getRedis()
if err != nil {
return nil, err
}
if client == nil {
return nil, errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.LRange(key, start, stop).Result()
if nil != err {
return nil, err
}
return val, nil
}
func UpdateExpire(key string, expire time.Duration) error {
client, err := getRedis()
if err != nil {
return err
}
if client == nil {
return errors.New("failed to get rds client")
}
defer relaseRedis(client)
_, err = client.Expire(key, expire).Result()
return err
}
func HGet(key string, hash string) (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.HGet(key, hash).Result()
if nil != err {
return "", err
}
return val, nil
}
func HGetInt64(key string, hash string) (int64, error) {
client, err := getRedis()
if err != nil {
return 0, err
}
if client == nil {
return 0, errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.HGet(key, hash).Int64()
if nil != err {
return 0, err
}
return val, nil
}
func SCard(key string) (int64, error) {
client, err := getRedis()
if err != nil {
return 0, err
}
if client == nil {
return 0, errors.New("failed to get rds client")
}
defer relaseRedis(client)
val, err := client.SCard(key).Result()
if nil != err {
return 0, err
}
return val, nil
}
// 获取时间
func Time() (int64, error) {
client, err := getRedis()
if err != nil {
return 0, err
}
if client == nil {
return 0, errors.New("failed to get rds client")
}
defer relaseRedis(client)
// 读取redis时间
r := client.Time()
if nil == r {
return 0, errors.New("read redis error")
}
if nil != r.Err() {
return 0, r.Err()
}
return strconv.ParseInt(r.Val()[0], 10, 0)
}
// 删除指定key的redis记录
func Del(key string) (int64, error) {
client, err := getRedis()
if err != nil {
return 0, err
}
if client == nil {
return 0, errors.New("failed to get rds client")
}
defer relaseRedis(client)
var iResult int64
cmdResult := client.Del(key)
if nil == cmdResult.Err() {
iResult, _ = cmdResult.Result()
} else {
iResult = 0
}
return iResult, nil
}
// 清空rendis_db
func TruncateDB() (string, error) {
client, err := getRedis()
if err != nil {
return "", err
}
if client == nil {
return "", errors.New("failed to get rds client")
}
defer relaseRedis(client)
cmdResult := client.FlushDb()
if cmdResult.Err() != nil {
return "", cmdResult.Err()
}
return cmdResult.Result()
}

View File

@ -1,125 +0,0 @@
<template>
<div id="app">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
import Cookie from 'js-cookie'
import store from './store/index'
import Const from './const'
import Vue from 'vue';
import axios from "@/api/ajax";
import Message from "element-ui/lib/message";
export default {
name: 'app',
store:store,
methods:{
getPlayType(){
console.log("shit",this.Global)
axios.get('/plan_types').then(response => {
if (response.data.Status === 0) {
for(let i = 0;i < response.data.Data.length; i ++){
this.Global.planTypes.push({
value: response.data.Data[i].id,
label: response.data.Data[i].type_name
})
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
open: function () {
console.log("socket连接成功")
this.send("hello world")
},
error: function () {
console.log("连接错误")
},
getMessage: function (msg) {
console.log("recv data ",msg.data)
},
send: function (params) {
this.socket.send(params)
},
close: function () {
console.log("socket已经关闭")
}
},
mounted() {
this.getPlayType()
},
created() {
if(typeof(WebSocket) === "undefined"){
console.log("您的浏览器不支持socket")
}else{
console.log("start connect")
// socket
this.socket = new WebSocket("ws://127.0.0.1:9850/ws")
// socket
this.socket.onopen = this.open
// socket
this.socket.onerror = this.error
// socket
this.socket.onmessage = this.getMessage
this.Global.SetWebsocket(this.socket)
}
let prefix = process.env.NODE_ENV === 'production'
? "/dist/admin/index.html#"
: 'http://127.0.0.1:8080';
let routes = '';
//console.log(window.location.href.search(prefix));
if(window.location.href.search(prefix) != -1) {
routes = window.location.href.substr(window.location.href.search(prefix) + prefix.length,window.location.href.length);
}else{
routes = '/BarIview';
}
if((window.location.href.search("article") != -1 ) && (window.location.href.search("articleManage") === -1 )){
this.$router.push(routes);
return;
}
if (Cookie.get(Const.KEY_USER_INFO)) {
//cookievuexredirect
store.commit("setAccount",Cookie.get(Const.KEY_USER_INFO));
//
console.log("current request path not replace: ",window.location.href);
let route_true = window.location['pathname'].replace('/dist/admin/index.html','/BarIview');
if(route_true === "/"){
this.$router.push("/BarIView");
}else{
this.$router.push(route_true);
}
return;
}else{
this.$router.push('/login');
}
},
activated() {
},
destroyed() {
this.socket.onclose = this.close
},
}
</script>
<style>
body{
margin: 0px;
height:100%;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 100%;
}
</style>

View File

@ -1,36 +0,0 @@
import axios from 'axios'
import store from '@/store/index.js'
/**
* 获取一个新的自定义的axios实例
*/
const ajaxUrl =
process.env.NODE_ENV === 'development'
? "http://127.0.0.1:4596/api/" // 开发环境中的后端地址
: process.env.NODE_ENV === 'production'
? "https://www.testingcloud.club/sapi/api" // 生产环境中的后端地址
: window.config.Host.test // 测试环境的后端地址
let ajax = axios.create({
baseURL: ajaxUrl,
timeout: 30000,
withCredentials: true,
async:true,
crossDomain:true,
});
ajax.interceptors.request.use(function (xhr) {
return xhr;
}, function (error) {
console.log(error);
// 对请求错误做些什么
return Promise.reject(error);
});
ajax.interceptors.response.use(function(response) {
console.log("response is :",response)
return response
}, function(error) {
// Vue.$vux.loading.hide()
console.log(error);
return Promise.reject(error)
});
export default ajax;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546483355753" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4098" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M563.072 376.48a79.456 79.456 0 0 0 28.928-61.12 80 80 0 1 0-160 0c0 24.672 11.392 46.432 28.928 61.12l-202.88 540.256a32 32 0 1 0 59.904 22.496l49.28-131.264h289.504l49.28 131.264a32.064 32.064 0 0 0 41.248 18.752c16.544-6.208 24.896-24.672 18.72-41.216l-202.912-540.288z m-1.312 178.624h-99.552L512 422.56l49.76 132.544z m-170.464 188.896l46.912-124.896h147.616l46.912 124.896h-241.44zM662.464 417.408a32 32 0 1 0 53.12 35.648 254.72 254.72 0 0 0 43.136-142.304 255.04 255.04 0 0 0-43.136-142.304 32 32 0 1 0-53.12 35.68 190.944 190.944 0 0 1 32.288 106.624 190.816 190.816 0 0 1-32.288 106.656zM289.888 453.024a32 32 0 1 0 53.184-35.616 191.36 191.36 0 0 1-32.32-106.656 191.328 191.328 0 0 1 32.32-106.656 32.064 32.064 0 0 0-8.768-44.416 32.096 32.096 0 0 0-44.416 8.768 254.976 254.976 0 0 0-43.136 142.304 254.976 254.976 0 0 0 43.136 142.272zM210.656 117.12A32 32 0 1 0 157.44 81.536a420.032 420.032 0 0 0-70.848 233.824 419.744 419.744 0 0 0 70.88 233.856 31.936 31.936 0 0 0 44.416 8.768 32 32 0 0 0 8.768-44.416 355.168 355.168 0 0 1-60.032-198.24A355.36 355.36 0 0 1 210.656 117.12zM896.224 154.304a416.96 416.96 0 0 0-38.912-72.768 32 32 0 1 0-53.184 35.584 354.912 354.912 0 0 1 60.064 198.24 355.2 355.2 0 0 1-60.064 198.208 32.032 32.032 0 0 0 53.184 35.648 418.816 418.816 0 0 0 70.88-233.856c0-55.68-10.752-109.856-31.968-161.056z" p-id="4099"></path></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546483364693" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4214" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M142.88 205.44c-12.96 0-24.128 4.672-33.44 13.984-9.344 9.344-14.016 20.48-14.016 33.44s4.672 24.128 14.016 33.472c9.312 9.344 20.48 13.984 33.44 13.984 12.96 0 24.128-4.672 33.44-14.016 9.344-9.344 14.016-20.48 14.016-33.44s-4.672-24.096-14.016-33.44a45.504 45.504 0 0 0-33.44-13.984zM142.88 366.752c-10.432 0-19.36 3.712-26.816 11.136a36.576 36.576 0 0 0-11.136 26.816v455.52c0 10.432 3.712 19.36 11.136 26.816 7.424 7.424 16.352 11.136 26.816 11.136s19.36-3.712 26.816-11.136c7.424-7.424 11.136-16.352 11.136-26.816V404.704c0-10.432-3.712-19.36-11.136-26.816a36.544 36.544 0 0 0-26.816-11.136zM547.168 139.008c-151.84 0-227.744 75.936-227.744 227.744v28.48H281.44c-10.432 0-19.36 3.712-26.816 11.136-7.424 7.424-11.136 16.384-11.136 26.816s3.712 19.36 11.136 26.816c7.424 7.424 16.384 11.136 26.816 11.136h37.952v389.088c0 10.432 3.712 19.36 11.168 26.816 7.424 7.424 16.352 11.136 26.816 11.136 10.432 0 19.36-3.712 26.816-11.136 7.424-7.424 11.136-16.352 11.136-26.816V471.136h114.368c10.432 0 19.36-3.712 26.816-11.136 7.424-7.424 11.136-16.384 11.136-26.816s-3.712-19.36-11.136-26.816a36.544 36.544 0 0 0-26.816-11.136h-114.368v-28.48c0-101.216 50.624-151.84 151.84-151.84 10.432 0 19.36-3.712 26.816-11.168 7.424-7.424 11.136-16.352 11.136-26.816s-3.712-19.36-11.136-26.816a36.736 36.736 0 0 0-26.816-11.104zM921.952 585.344a279.968 279.968 0 0 0-24.032-66.208c-6.4-12.448-13.376-24.704-20.928-36.768s-15.456-23.936-23.776-35.648c-4.512-8.672-10.56-14.528-18.112-17.536-7.552-3.008-14.912-3.68-22.08-1.984s-13.28 5.76-18.4 12.16c-5.088 6.4-7.456 14.528-7.072 24.32 0.384 6.4 2.176 11.968 5.376 16.672l9.888 14.432c7.552 11.328 15.008 22.816 22.336 34.528 7.36 11.68 13.472 24.128 18.4 37.344 7.168 19.232 12.256 40.448 15.264 63.648 3.008 23.2 3.968 46.752 2.816 70.72-1.12 23.968-4.512 47.232-10.176 69.856s-13.952 42.816-24.896 60.544c-2.656 4.16-5.088 7.712-7.36 10.752a74.88 74.88 0 0 1-7.072 8.192l-15.552 15.552-7.904 8.48a56.64 56.64 0 0 0-5.664 18.4c-0.768 6.208-0.096 11.968 1.984 17.248 2.08 5.28 5.664 9.632 10.752 13.024s11.584 5.088 19.52 5.088c8.672 0 16.608-2.656 23.776-7.936 7.168-5.28 13.568-10.944 19.232-16.992 13.184-13.952 24.032-30.08 32.544-48.352 8.48-18.304 15.744-36.48 21.792-54.592 6.784-21.12 11.872-43.84 15.264-68.16 3.392-24.32 4.608-48.928 3.68-73.824a388.608 388.608 0 0 0-9.6-72.96zM722.88 861.184a23.04 23.04 0 0 0-1.504-1.728l-5.952-6.784a511.296 511.296 0 0 1-8.192-9.632 67.712 67.712 0 0 1-7.36-10.464 224.48 224.48 0 0 1-24.896-59.68 325.856 325.856 0 0 1-10.176-66.464c-1.12-22.624-0.384-45.184 2.272-67.616a394.432 394.432 0 0 1 15.264-72.416c1.12-3.2 2.72-6.88 4.8-11.04a961.664 961.664 0 0 1 20.064-37.312c3.392-5.28 7.84-11.68 13.28-19.232 5.472-7.552 9.984-15.36 13.568-23.488 3.584-8.096 4.992-16.032 4.256-23.776-0.736-7.712-5.664-14.432-14.72-20.064-9.44-5.664-18.208-6.976-26.304-3.968s-15.552 8.096-22.336 15.264a122.432 122.432 0 0 0-17.824 24.32l-12.736 22.624c-5.664 10.56-11.328 21.024-16.96 31.392a164.448 164.448 0 0 0-13.568 33.088c-13.952 45.632-20.192 92.512-18.656 140.576s11.872 94.368 31.104 138.88c3.008 7.552 7.552 17.344 13.568 29.408s13.216 23.584 21.504 34.496 17.632 19.616 28 26.016c10.368 6.4 21.216 7.552 32.544 3.392 12.064-4.896 18.848-12.544 20.352-22.912a50.144 50.144 0 0 0-5.664-30.848l-13.728-12.032z" p-id="4215"></path></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,317 +0,0 @@
<template>
<div style="display: block;background: #505458">
<el-row>
<el-col :span="10">
<el-form ref="formInline" :model="formInline" :rules="ruleInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="文章名字" style="float: left"></el-input>
</el-form-item>
<el-form-item prop="is_public" style="float: left;margin-left: 20px;">
<el-checkbox v-model="is_public" style="color:white"></el-checkbox>
</el-form-item>
<el-form-item style="float: left">
<el-button @click="getArticles" type="primary" style="float: left;margin-left: 10px; ">查询</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="1">
<div style="display: block;margin-top: 8px; font-size:15px; ">
分类:
</div>
</el-col>
<el-col :span="3" style="margin-left: 20px">
<el-select v-model="currentGroup" placeholder="选择分组" @change="OnChangeGroup">
<el-option v-for="item in this.docgroups" :key="item.Int" :label="item.Name" :value="item.Int"></el-option>
</el-select>
</el-col>
<el-col :span="3">
<el-select v-model="docType" placeholder="分类" style="margin-left: 20px">
<el-option v-for="item in this.doc_types" :key="item.id" :label="item.type_name" :value="item.id">
</el-option>
</el-select>
</el-col>
</el-row>
<el-table :data="data1" border style="width: 100%;text-aligin:center;background: #505458" highlight-current-row ref="singleTable">
<el-table-column type="index" width="50">
</el-table-column>
<el-table-column prop="title" label="标题" width="120">
</el-table-column>
<el-table-column prop="author" label="作者" width="120">
</el-table-column>
<el-table-column prop="content" label="内容">
</el-table-column>
<el-table-column prop="typename" label="类型" width="180">
</el-table-column>
<el-table-column fixed="right" label="操作" width="150">
<template slot-scope="scope">
<el-button type="text" @click="handleClick(scope)" size="small">查看</el-button>
<el-button type="text" @click="handleEdit(scope)" size="small">编辑</el-button>
<el-button type="text" @click="handleDelete(scope)" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination layout="prev, pager, next" :total="articleCount" @current-change="handleChangePage">
</el-pagination>
</div>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Cookie from 'js-cookie'
import Const from '@/const.js'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "tes",
data: () => {
return {
currentGroup: "",
is_public: 0,
dialogVisible: false,
type: "",
types: [],
limit: 10,
offset: 0,
formInline: {
dockname: '',
type: ''
},
articleCount: 0,
articleCountAll: 3,
ruleInline: {
dockname: [{
message: '请输入查询的文章名字',
trigger: 'blur'
}],
password: [{
message: 'Please fill in the password.',
trigger: 'blur'
},
{
type: 'string'
}
]
},
data1: [{}],
data2: [],
docKey: "",
docType: 110,
doc_types: [],
doc_typess: new Map,
}
},
methods: {
handleTypeSelect(obj) {
let j = 0;
let tmp = [];
for (let len = this.data2.length; j < len; j++) {
if (this.data2[j].type === obj) {
tmp.push(this.data2[j]);
}
}
this.data1 = [];
j = 0;
for (let len = tmp.length; j < len; j++) {
this.data1.push(tmp[j]);
}
},
handlerShow(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleChangePage(page) {
axios.post('/articles?limit=' + this.limit + '&offset=' + (page - 1) * this.limit, {
name: this.formInline.user,
types: this.docType
}).then(response => {
this.data1 = [];
this.data2 = [];
if (response.data.Status === 0) {
let j = 0;
for (let len = response.data.Data.length; j < len; j++) {
response.data.Data[j].typename = this.doc_typess.get(String(response.data.Data[j].type)).type_name
this.data1.push(response.data.Data[j]);
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleClick(row) {
this.$router.push("/article/" + row.row.id);
},
handleEdit(row) {
this.$router.push("/BarIView/editor?id=" + row.row.id);
},
handleDelete(row) {
MessageBox.confirm('确认关闭?')
.then(_ => {
axios.delete('/article/' + row.row.id, {}).then(response => {
if (response.data.Status === 0) {
let j = 0;
for (let len = this.data1.length; j < len; j++) {
if (this.data1[j].id == row.row.id) {
this.data1.splice(j, 1)
}
//this.data1.push(response.data.Data[j]);
}
Message.success("删除成功");
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
done();
})
.catch(_ => {});
},
getArticles() {
axios.post('/articles?limit=' + this.limit + '&offset=' + this.offset + '&is_public=' + this.is_public, {
name: this.formInline.user,
types: this.docType
}).then(response => {
this.data1 = [];
if (response.data.Status === 0) {
let j = 0;
for (let len = response.data.Data.length; j < len; j++) {
this.data2.push(response.data.Data[j]);
response.data.Data[j].typename = this.doc_typess.get(String(response.data.Data[j].type)).type_name
this.data1.push(response.data.Data[j]);
}
if (this.docType != 110)
this.articleCount = response.data.Data.length;
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getArtcleTypes(){
axios.get("doc_types", {
withCredentials: true
}).then(
resp => {
this.doc_types.push({
"Id": 110,
"type_name": "全部"
});
let j = 0;
for (let typeNum = resp.data.Data.length; j < typeNum; j++) {
this.doc_types.push(resp.data.Data[j])
this.doc_typess.set(String(resp.data.Data[j]["id"]),resp.data.Data[j])
}
}
).catch(
reason => {
Message.error(reason)
}
)
},
getArticleCount() {
axios.get('/articleCount', {}).then(response => {
if (response.data.Status === 0) {
this.articleCountAll = response.data.Data.cnt
this.articleCount = this.articleCountAll;
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
OnChangeGroup() {
console.log(this.currentGroup, this.docgroups[this.currentGroup])
this.getGroupType(this.docgroups[this.currentGroup].Int);
},
getGroupType(id) {
axios.post("/group_type", {
id: id,
})
.then(response => {
if (response.data.Status === 0) {
console.log(response.data.Data)
this.doc_types = response.data.Data;
this.docType = this.doc_types[0].id;
}
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
},
getDocGroup() {
axios.get('/doc_groups', {}).then(response => {
if (response.data.Status === 0) {
console.log(response.data.Data);
this.docgroups = response.data.Data;
} else {}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
created() {
this.getArtcleTypes()
console.log(this.Global.ws.send("shjit"))
this.getDocGroup()
this.getArticles()
let userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
console.log(userInfo)
let url = '/user';
url += 'user=' + userInfo["UserName"]
url += '&token=' + userInfo["SocketToken"]
axios.get(url)
.then(response => {
console.log(response);
if (response.data.Status === 0) {
} else {
this.$router.push("/login");
}
})
},
mounted() {
this.getArticleCount()
},
beforeCreate() {
}
}
</script>
<style scoped>
.el-button--primary:focus,
.el-button--primary:hover {
background: #DCDFE6;
}
</style>

View File

@ -1,549 +0,0 @@
<template>
<div style="display: block; ">
<el-row>
<el-col :span="10">
<el-form ref="formInline" :model="formInline" :rules="ruleInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="文章名字" style="float: left"></el-input>
</el-form-item>
<el-form-item prop="is_public" style="float: left;margin-left: 20px;">
<el-checkbox v-model="is_public" style="color:white"></el-checkbox>
</el-form-item>
<el-form-item style="float: left">
<el-button @click="getArticles" type="primary" style="float: left;margin-left: 10px; ">查询</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="1">
<div style="display: block;margin-top: 8px; font-size:15px; ">
分类:
</div>
</el-col>
<el-col :span="3" style="margin-left: 20px">
<el-select v-model="currentGroup" placeholder="选择分组" @change="OnChangeGroup">
<el-option v-for="item in this.docgroups" :key="item.Int" :label="item.Name" :value="item.Int"></el-option>
</el-select>
</el-col>
<el-col :span="3">
<el-select v-model="docType" placeholder="分类" style="margin-left: 20px">
<el-option v-for="item in this.doc_types" :key="item.id" :label="item.type_name" :value="item.id">
</el-option>
</el-select>
</el-col>
</el-row>
<div style="display: inline-block;width: 100%;float: left;height: 100%;">
<el-col :span="20" style="height: 100%;margin-right: 30px;">
<el-tree
:data="this.data"
node-key="id"
default-expand-all
style="height: 100%; "
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<el-button
type="text"
size="mini"
@click="() => edit(node, data)" style="margin-left:20px">
编辑文章
</el-button>
<el-button
type="text"
size="mini"
@click="() => append(data)" style="margin-left:20px">
添加子文章
</el-button>
<el-button
type="text"
size="mini"
@click="() => remove(node, data)" style="margin-left:20px">
删除文章
</el-button>
<el-button type="text" size="mini" @click="() => generate_show_url(node, data)" style="margin-left:20px">
生成浏览外链
</el-button>
</span>
</span>
</el-tree>
</el-col>
</div>
<el-drawer
title="新增文章"
:visible.sync="drawer"
:with-header="false"
:size=1256
:before-close="handleCloseDraw"
>
<div class="container">
<el-row style="margin-top: 10px;">
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">标题:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="标题" v-model="currentEditTitle"></el-input>
</el-col>
</el-row>
<el-row style="margin-top:30px;">
<mavon-editor style="height: 600px;margin-left: 4px;" v-model="currentEditContent" :subfield=this.subfield
:editable=this.editable ref="md" @imgAdd="$imgAdd" @imgAddOrigin="$imgAddOrigin"/>
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addOrUpdateArtile">{{btnSave}}</el-button>
<el-button @click="addHistoryArtile"></el-button>
</el-col>
</el-row>
</div>
</el-drawer>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Cookie from 'js-cookie'
import Const from '@/const.js'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "tes",
data: () => {
return {
currentGroup: "",
is_public: 0,
dialogVisible: false,
type: "",
types: [],
limit: 10,
offset: 0,
formInline: {
dockname: '',
type: ''
},
articleCount: 0,
articleCountAll: 3,
ruleInline: {
dockname: [{
message: '请输入查询的文章名字',
trigger: 'blur'
}],
password: [
{
message: 'Please fill in the password.',
trigger: 'blur'
},
{
type: 'string'
}
]
},
data:[],
currentNode: {},
data2: [],
docKey: "",
docType: 110,
doc_types: [],
doc_typess: new Map,
drawer: false,
currentEditID: -1,
currentEditTitle: "",
currentEditContent: "",
btnSave: "提交"
}
},
methods: {
$imgAddOrigin(pos, $file) {
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_upload_origin?type=' : 'https://www.testingcloud.club/sapi/api/image_upload_origin?type=') + $file.type.substring(6,) ,
method: 'post',
data: formdata,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then((url) => {
var url1 = (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_download/' : 'https://www.testingcloud.club/sapi/api/image_download/') + url.data.url;
// .url![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后`$vm``mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>`$vm``this.$refs.md`
*/
this.$refs.md.$img2Url(pos, url1);
})
},
// @imgAdd event
$imgAdd(pos, $file) {
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_upload?type=' : 'https://www.testingcloud.club/sapi/api/image_upload?type=') + $file.type.substring(6,) ,
method: 'post',
data: formdata,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then((url) => {
var url1 = (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_download/' : 'https://www.testingcloud.club/sapi/api/image_download/') + url.data.url;
// .url![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后`$vm``mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>`$vm``this.$refs.md`
*/
this.$refs.md.$img2Url(pos, url1);
})
},
addOrUpdateArtile(){
if(this.btnSave == "提交"){
axios.put("article_tree",{
title:this.currentEditTitle,
content:this.currentEditContent,
author:"admin",
type: this.currentNode.id,
is_public: 1,
father: this.currentNode.id,
level: this.currentNode.level + 1
}).then(resp => {
console.log(resp)
if (resp.data.Status == 0){
console.log(this.data)
this.currentNode.children.push({
level:this.currentNode.level + 1,
father: this.currentNode.id,
label:this.currentEditTitle,
id: resp.data.Data,
children:[],
})
Message.success("插入成功")
this.btnSave = "更新"
this.currentEditID = resp.data.Data
}
}
)
}
if(this.btnSave == "更新"){
console.log(this.currentNode)
axios.post("article_update_tree",{
id: this.currentEditID,
title:this.currentEditTitle,
content:this.currentEditContent,
author:"admin",
type: this.currentNode.id,
is_public: 1,
father: this.currentNode.id,
level: this.currentNode.level + 1
}).then(resp => {
console.log(resp)
if (resp.data.Status == 0){
Message.success("更新成功")
}
}
)
}
},
addHistoryArtile() {
axios.put("article_tree_history", {
id: this.currentEditID,
title: this.currentEditTitle,
content: this.currentEditContent,
author: "admin",
type: this.currentNode.id,
is_public: 1,
father: this.currentNode.id,
level: this.currentNode.level + 1
}).then(resp => {
console.log(resp)
if (resp.data.Status == 0) {
Message.success("更新成功")
}
}
)
},
handleCloseDraw(done) {
MessageBox.confirm('确认关闭?')
.then( _ => {
done()
})
.catch(_ => {});
},
edit(node, data){
this.drawer = true
this.currentEditID = data.id
axios.get("article/" + data.id, {
withCredentials: true
}).then(
resp => {
console.log(resp.data.Data)
this.currentEditTitle = resp.data.Data.title
this.currentEditContent = resp.data.Data.content
}
)
this.btnSave = "更新"
},
findChildren(id){
this.data.forEach(element => {
console.log(element)
if(element.id == id){
}
});
},
remove(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id) //
if(data.children.length > 0){
Message.error("请先删除子项")
return
}
MessageBox.confirm('确认删除?')
.then( _ => {
axios.delete('/article_tree/' + data.id, {}).then(response => {
if (response.data.Status === 0) {
Message.success("删除成功");
children.splice(index, 1)
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
done();
}).catch(_ => {})
},
generate_show_url(node, data) {
console.log(node, 'https://www.testingcloud.club/dist/admin/index.html#/article/' + node.data.id)
MessageBox.alert('<a href=\'https://www.testingcloud.club/dist/admin/index.html#/article/' + node.data.id
+ '\'> 外链</a>' ,
'生成外链', {
dangerouslyUseHTMLString: true
});
},
handleTypeSelect(obj) {
let j = 0;
let tmp = [];
for (let len = this.data2.length; j < len; j++) {
if (this.data2[j].type === obj) {
tmp.push(this.data2[j]);
}
}
this.data1 = [];
j = 0;
for (let len = tmp.length; j < len; j++) {
this.data1.push(tmp[j]);
}
},
handlerShow(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
append(data) {
console.log(data)
this.drawer = true
if (!data.children) {
this.$set(data, 'children', [])
}
this.currentNode = data
this.currentEditID = -1
this.currentEditTitle = ""
this.currentEditContent = ""
this.btnSave = "提交"
console.log(data)
},
handleChangePage(page) {
axios.post('/articles?limit=' + this.limit + '&offset=' + (page - 1) * this.limit, {
name: this.formInline.user,
types: this.docType
}).then(response => {
this.data1 = [];
this.data2 = [];
if (response.data.Status === 0) {
let j = 0;
for (let len = response.data.Data.length; j < len; j++) {
response.data.Data[j].typename = this.doc_typess.get(String(response.data.Data[j].type)).type_name
this.data1.push(response.data.Data[j]);
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
})
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {})
},
handleClick(row) {
this.$router.push("/article/" + row.row.id);
},
handleEdit(row) {
this.$router.push("/BarIView/editor?id=" + row.row.id);
},
handleDelete(row) {
MessageBox.confirm('确认关闭?')
.then(_ => {
axios.delete('/article/' + row.row.id, {}).then(response => {
if (response.data.Status === 0) {
let j = 0;
for (let len = this.data1.length; j < len; j++) {
if (this.data1[j].id == row.row.id) {
this.data1.splice(j, 1)
}
//this.data1.push(response.data.Data[j]);
}
Message.success("删除成功");
}
}).catch(reason => {
Message.error("网络错误:" + reason);
})
done()
})
.catch(_ => {});
},
getArtileTree(){
axios.get('/articles_tree').then(response=>{
if (response.data.Status === 0) {
this.data = response.data.Data
for(let i = 0;i < (response.data.Data.length) ; i ++){
console.log(response.data.Data[i])
}
}
})
},
getArtcleTypes(){
axios.get("doc_types", {
withCredentials: true
}).then(
resp => {
this.doc_types.push({
"Id": 110,
"type_name": "全部"
})
let j = 0;
for (let typeNum = resp.data.Data.length; j < typeNum; j++) {
this.doc_types.push(resp.data.Data[j])
this.doc_typess.set(String(resp.data.Data[j]["id"]),resp.data.Data[j])
}
}
).catch(
reason => {
Message.error(reason)
}
)
},
getArticleCount() {
axios.get('/articleCount', {}).then(response => {
if (response.data.Status === 0) {
this.articleCountAll = response.data.Data.cnt
this.articleCount = this.articleCountAll;
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
OnChangeGroup() {
console.log(this.currentGroup, this.docgroups[this.currentGroup])
this.getGroupType(this.docgroups[this.currentGroup].Int);
},
getGroupType(id) {
axios.post("/group_type", {
id: id,
})
.then(response => {
if (response.data.Status === 0) {
console.log(response.data.Data)
this.doc_types = response.data.Data;
this.docType = this.doc_types[0].id;
}
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
},
getDocGroup() {
axios.get('/doc_groups', {}).then(response => {
if (response.data.Status === 0) {
console.log(response.data.Data);
this.docgroups = response.data.Data;
} else {}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
created() {
this.getArtileTree()
this.getArtcleTypes()
console.log(this.Global.ws.send("test for send"))
this.getDocGroup()
let userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
console.log(userInfo)
let url = '/user';
url += 'user=' + userInfo["UserName"]
url += '&token=' + userInfo["SocketToken"]
axios.get(url)
.then(response => {
console.log(response);
if (response.data.Status === 0) {
} else {
this.$router.push("/login");
}
})
},
mounted() {
this.getArticleCount()
},
beforeCreate() {
}
}
</script>
<style scoped>
.el-button--primary:focus,
.el-button--primary:hover {
background: #DCDFE6;
}
.custom-tree-node {
justify-content: space-around;
display:block;
padding-right: 8px;
overflow-x: auto;
overflow-y: auto;
margin-top: 10px;
}
</style>

View File

@ -1,187 +0,0 @@
<template>
<div class="container">
<el-row>
<el-col :span="2">
<div style="float: left;font-size: 16px;font-stretch: semi-condensed;margin-top: 8px">文章分类管理:</div>
</el-col>
<el-col :span="8">
<el-col :span="6">
<el-form ref="formInline" v-model="addTypeName" style="float: left">
<el-input v-model="addTypeName" placeholder="请输入分类名称"></el-input>
</el-form>
</el-col>
<el-col :span="9" style="margin-left: 20px">
<el-select v-model="currentGroup" placeholder="选择分组">
<el-option v-for="item in this.docgroups" :key="item.Int" :label="item.Name" :value="item.Int"></el-option>
</el-select>
</el-col>
<el-col :span="3" style="margin-left: 20px">
<el-button type="primary" @click="putArticleType"></el-button>
</el-col>
</el-col>
</el-row>
<el-row style="width: 800px; background: #505458">
<el-col style="margin-top: 20px;width: 800px;">
<el-table :data="doctypes" border style="width: 700px;text-aligin: center;border-radius: 4px; ">
<el-table-column prop="id" label="文章类型id" width="120">
</el-table-column>
<el-table-column prop="type_name" label="文章类型名字" width="250">
</el-table-column>
<el-table-column prop="group_name" label="分组" width="100">
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button type="primary" @click="editArticleType(scope)"></el-button>
<el-button type="primary" @click="showconfirmdelete(scope)"></el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</div>
</template>
<script>
import Vue from 'vue';
import axios from "@/api/ajax.js";
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import MessageBox from "element-ui/lib/message-box"
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "article_type",
components: {},
data: () => {
return {
doctypes: {},
addTypeName: "",
docgroups: [],
currentGroup: 0,
};
},
methods: {
editArticleType(row) {
MessageBox.prompt('请输入新分类名称', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
}).then(({
value
}) => {
Message({
type: 'success',
message: '你的邮箱是: ' + row.row.id
});
}).catch(() => {
Message({
type: 'info',
message: '取消输入'
});
});
},
showconfirmdelete(row) {
MessageBox.confirm('此操作将永久删除该分类, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.delete('/article_type' + "?id=" + row.row.id, {}).then(response => {
if (response.data.Status === 0) {
Message("删除分类成功");
this.getArticleType();
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
Message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
Message({
type: 'info',
message: '已取消删除'
});
});
},
getArticleType() {
axios.get('/article_type', {}).then(response => {
if (response.data.Status === 0) {
this.doctypes = response.data.Data;
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
putArticleType() {
axios.put('/article_type' + '?name=' + this.addTypeName + '&group=' + this.currentGroup, {}).then(response => {
if (response.data.Status === 0) {
Message({
type: 'success',
message: '新建分类成功!'
})
} else {
Message({
type: 'error',
message: '新建分类失败!'
});
}
this.getArticleType();
}).catch(reason => {
Message.error("网络错误:" + reason);
})
},
getDocGroup() {
axios.get('/doc_groups', {}).then(response => {
if (response.data.Status === 0) {
console.log(response.data.Data);
this.docgroups = response.data.Data;
} else {}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
},
created() {
this.getArticleType();
this.getDocGroup();
},
mounted() {
},
beforeCreate() {
}
};
</script>
<style>
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,382 +0,0 @@
<template>
<div style="display: block">
<el-row>
<el-col :span="10">
<el-form ref="formInline" :model="formInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="书名" style="float: left"></el-input>
</el-form-item>
<el-form-item style="float: left">
<el-button @click="getBooks" type="primary" style="float: left;margin-left: 10px; ">查询</el-button>
<el-button @click="drawer = true;reset()" type="primary" style="float: left;margin-left: 10px; ">新建</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-table
:data="memos"
border
style="width: 100%;text-aligin:center">
<el-table-column
prop="id"
label="id"
width="120" >
</el-table-column>
<el-table-column
prop="book_name"
label="书名"
width="120" >
</el-table-column>
<el-table-column
prop="author"
label="作者"
width="120" >
</el-table-column>
<el-table-column
prop="tag"
label="类别"
width="120" >
</el-table-column>
<el-table-column
prop="create_time"
label="添加或者购入时间"
width="160">
</el-table-column>
<el-table-column
prop="content"
label="简介"
>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150">
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope)" size="small">编辑</el-button>
<el-button type="text" @click="handleDelete(scope)" size="small">刪除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
layout="prev, pager, next"
:total="articleCount"
@current-change="handleChangePage"
>
</el-pagination>
</div>
<el-drawer
title="新增书籍"
:visible.sync="drawer"
:with-header="true"
:before-close="handleCloseDraw" >
<div style="background: #cac6c6;height: 100%">
<el-row style="margin-top: 2px;">
<el-col :span="5" style="text-align:center; display:table;">
<p style="color: black;font-size: 15px;">书名:</p>
</el-col>
<el-col :span="15" style="margin-top: 15px;">
<el-input placeholder="书名" v-model="book_name"></el-input>
</el-col>
</el-row>
<el-row style="margin-top: 2px;">
<el-col :span="5" style="text-align:center;display:table;">
<p style="color: black;font-size: 15px;">作者:</p>
</el-col>
<el-col :span="15" style="margin-top: 15px;">
<el-input placeholder="作者" v-model="author"></el-input>
</el-col>
</el-row>
<el-row style="margin-top: 2px;">
<el-col :span="5" style="text-align:center;display:table;">
<p style="color: black;font-size: 15px;">标签:</p>
</el-col>
<el-col :span="15" style="margin-top: 15px;">
<el-input placeholder="类别" v-model="tag"></el-input>
</el-col>
</el-row>
<el-row style="margin-top: 2px;">
<el-col :span="5" style="text-align:center;display:table;">
<p style="color: black;font-size: 15px;">简介:</p>
</el-col>
<el-col :span="50" style="margin-top: 15px;">
<el-input
type="textarea"
:rows="10"
placeholder="请输入内容"
style="margin-left: 15px;margin-top: -10px;"
v-model="content">
</el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addOrUpdateMemo">{{btnSave}}</el-button>
</el-col>
</el-row>
</div>
</el-drawer>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import utils from '@/util/times.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Drawer from 'element-ui/lib/drawer'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Drawer);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "tes",
data:()=>{
return{
editid:-1,
memos:[],
btnSave:"保存",
drawer: false,
content: "",
limit:10,
offset :0,
formInline: {
dockname: '',
type: ''
},
memoCount:0,
isupdate:false,
preview:false,
subfield:true,
editable:true,
title:"",
brief:"",
author:"",
book_name:"",
tag:"",
create_time:"",
timer: "",//
}
},
methods: {
reset(){
this.author = ""
this.content = ""
this.book_name = ""
this.tag = ""
},
NowDate(fmt)
{ //author: meizz
var aData = new Date();
var o = {
"M+" : aData.getMonth()+1, //
"d+" : aData.getDate(), //
"h+" : aData.getHours(), //
"m+" : aData.getMinutes(), //
"s+" : aData.getSeconds(), //
"q+" : Math.floor((aData.getMonth()+3)/3), //
"S" : aData.getMilliseconds() //
};
if(/(y+)/.test(fmt))
fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
for(var k in o)
if(new RegExp("("+ k +")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
return fmt;
},
addOrUpdateMemo(){
console.log(this.isupdate);
if(this.isupdate === false){
console.log(this.isupdate);
axios.put('/book',{
"book_name":this.book_name,
"author":this.author,
"title": this.title,
"content":this.content,
"create_time": utils.getDateFormat(),
"tag":this.tag,
}).then(response=> {
if (response.data.Status === 0)
{
this.book_name = "";
this.author = "";
this.getBooks();
this.title = "";
this.content = "";
this.create_time = "";
this.tag = "";
this.drawer = false;
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}else{
axios.post('/book',{
"id": this.editid,
"book_name":this.book_name,
"author":this.author,
"tag":this.tag,
"content":this.content,
"title":this.title,
"create_time": utils.getDateFormat(),
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("更新成功")
this.drawer = false
this.getBooks()
}
})
}
this.title = "";
this.content = "";
this.editid = -1;
},
handlerShow(done) {
Message.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleChangePage(page){
this.memos = [];
axios.post('/memos?limit=' + this.limit + '&offset=' + (page-1)*this.limit,{
}).then(response=> {
if (response.data.Status === 0)
{
let j = 0;
for(let len= response.data.Data.length; j < len; j++) {
this.memos.push(response.data.Data[j]);
}
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleEdit(row){
console.log(row.row.id);
this.author = row.row.author;
this.book_name = row.row.book_name;
this.content = row.row.content;
this.drawer = true;
this.isupdate = true;
this.editid = row.row.id;
},
handleCloseDraw(done) {
MessageBox.confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
this.title = "";
this.content = "";
this.editid = -1;
},
handleDelete(row){
console.log(row.row.id);
axios.post('/delbook',{
"id":row.row.id
}).then(response=> {
if (response.data.Status === 0)
{
this.getBooks()
Message.success("删除成功")
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
//this.$router.push("/BarIView/editor?id=" + row.row.id);
},
getBooks(){
axios.post('/getbooks?limit=' + this.limit + '&offset=' + this.offset ,{
"book_name":this.title,
}).then(response=> {
this.memos = [];
if (response.data.Status === 0)
{
let j = 0;
for(let len= response.data.Data.length; j < len; j++) {
this.memos.push(response.data.Data[j]);
}
if(this.docType != 110)
this.articleCount = response.data.Data.length;
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getArticleCount(){
axios.get('/bookcount',{
}).then(response=> {
if (response.data.Status === 0)
{
this.articleCountAll =response.data.data
this.articleCount = this.articleCountAll;
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
},
created(){
this.getBooks();
},
mounted() {
this.getArticleCount();
},
beforeCreate() {
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer); // Vue
}
}
}
</script>
<style scoped>
.el-button--primary:focus, .el-button--primary:hover{
background: lightblue;
}
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,59 +0,0 @@
<template>
<div class="container">
<el-row>
</el-row>
<el-row style="margin-top:30px;">
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
</el-col>
</el-row>
</div>
</template>
<script>
import Message from "element-ui/lib/message";
import axios from "@/api/ajax.js";
import Cookie from "js-cookie";
import Const from "@/const.js";
export default {
name: "template",
components: {
},
data: () => {
return {
};
},
methods: {
},
created() {
},
beforeCreate() {
}
};
</script>
<style >
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<div class="container">
<el-row>
</el-row>
<el-row style="margin-top:30px;">
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
</el-col>
</el-row>
</div>
</template>
<script>
import axios from "@/api/ajax.js";
import Cookie from "js-cookie";
import Const from "@/const.js";
export default {
name: "template",
components: {
},
data: () => {
return {
};
},
methods: {
},
created() {
},
beforeCreate() {
}
};
</script>
<style >
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,305 +0,0 @@
<template>
<div class="container">
<el-row>
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">标题:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="标题" v-model="title"></el-input>
</el-col>
<el-col :span="1" style="text-align:center; display:table;">
<p style="font-size:15px; margin-top:8px;">分类:</p>
</el-col>
<el-col :span="3" style="margin-left: 20px">
<el-select v-model="currentGroup" placeholder="选择分组" @change="OnChangeGroup">
<el-option v-for="item in this.docgroups" :key="item.Int" :label="item.Name" :value="item.Int"></el-option>
</el-select>
</el-col>
<el-col :span="3" style="margin-left:5px;">
<el-select v-model="docType" placeholder="请选择" :value-key="docKey" @change="OnChangeType">
<el-option v-for="item in this.doc_types" :key="item.id" :label="item.type_name" :value="item.id">
</el-option>
</el-select>
</el-col>
<el-col :span="1" style="text-align:center; display:table; margin-top: 10px;margin-left:20px; font-size: 15px;">
<el-checkbox v-model="is_public" style="color: white"></el-checkbox>
</el-col>
<el-col :span="1" style="text-align:center; display:table;margin-left:20px; font-size: 15px;">
<el-button @click="this.addTemplate"></el-button>
</el-col>
<el-col :span="3" style="margin-left:5px;">
<el-select v-model="selectTemplate" placeholder="请选择" :value-key="docKey" @change="OnChangeType">
<el-option v-for="item in this.templates" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-col>
</el-row>
<el-row style="margin-top:30px;">
<mavon-editor v-proportion="0.5" style="height: 700px" v-model="content" ref="md" @imgAdd="$imgAdd" @imgAddOrigin="$imgAddOrigin" />
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addArticle">{{btnSave}}</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
import axios from "@/api/ajax.js";
import Const from "@/const.js";
import Message from "element-ui/lib/message"
import Cookie from 'js-cookie'
export default {
name: "editor",
components: {},
data: () => {
return {
currentGroup: "",
docgroups: [],
userInfo: {},
content: "",
title: "",
btnSave: "提交",
anchorAttrs: {
target: "_blank",
rel: "noopener noreferrer nofollow"
},
docGroupKey: "0",
docKey: 1,
docType: 0,
doc_types: [],
is_public: false,
templates : [],
selectTemplate:{},
};
},
methods: {
$imgAddOrigin(pos, $file) {
console.log("$imgAddOrigin")
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_upload_origin?type=' : 'https://www.testingcloud.club/sapi/api/image_upload_origin?type=') + $file.type.substring(6,) ,
method: 'post',
data: formdata,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then((url) => {
var url1 = (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_download/' : 'https://www.testingcloud.club/sapi/api/image_download/') + url.data.url;
// .url![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后`$vm``mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>`$vm``this.$refs.md`
*/
this.$refs.md.$img2Url(pos, url1);
})},
// @imgAdd event
$imgAdd(pos, $file) {
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_upload?type=' : 'https://www.testingcloud.club/sapi/api/image_upload?type=') + $file.type.substring(6,) ,
method: 'post',
data: formdata,
headers: {
'Content-Type': 'multipart/form-data'
},
}).then((url) => {
var url1 = (process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:4596/api/image_download/' : 'https://www.testingcloud.club/sapi/api/image_download/') + url.data.url;
// .url![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后`$vm``mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>`$vm``this.$refs.md`
*/
this.$refs.md.$img2Url(pos, url1);
})
},
getAllTypes() {
axios.get("doc_types", {
withCredentials: true
}).then(
resp => {
this.doc_types = resp.data.Data;
}
).catch(
reason => {
Message.error(reason)
}
)
},
getGroupType(id) {
axios.post("/group_type", {
id: id,
})
.then(response => {
if (response.data.Status === 0) {
this.doc_types = response.data.Data;
this.docType = this.doc_types[0].id;
}
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
},
OnChangeGroup() {
this.getGroupType(this.docgroups[this.currentGroup].Int);
},
OnChangeType() {
console.log(Number(this.docType))
},
addArticle() {
if (this.btnSave === '提交') {
axios.put("/article", {
title: this.title,
content: this.content,
type: Number(this.docType),
author: "admin",
is_public: this.is_public ? 1 : 0,
})
.then(response => {
if (response.data.Status === 0) {
Message.success("新增文章成功");
}
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
} else if(this.btnSave === '更新'){
axios.post("/article_update", {
title: this.title,
content: this.content,
author: "shit",
type: this.docType,
id: Number(this.$route.query['id']),
is_public: this.is_public ? 1 : 0,
}).then(response => {
if (response.data.Status === 0) {
Message.success("更新文章成功");
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
getDocGroup() {
axios.get('/doc_groups', {}).then(response => {
if (response.data.Status === 0) {
this.docgroups = response.data.Data;
} else {}
}).catch(reason => {
Message.error("网络错误:" + reason);
})
},
addTemplate(){
console.log("add template",this.selectTemplate)
this.getSingleTemplate()
console.log("shit")
},
getTemplate(){
axios.post('/get_doc_template?limit=' + this.limit + '&offset=' + this.offset ,{
"title":"",
}).then(response=> {
this.templates = [];
if (response.data.Status === 0)
{
this.templates = response.data.Data
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getSingleTemplate(id){
axios.get('/doc_template/' + this.selectTemplate).then(response=> {
if (response.data.Status === 0)
{
this.content += response.data.Data.content
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
created() {
this.getTemplate()
this.getDocGroup();
if (this.$route.query['id'] !== undefined) {
// query
//todo
let url = '/article/' + this.$route.query['id'];
axios.get(url, {
withCredentials: true
}).then(
resp => {
this.docType = resp.data.Data.type;
this.title = resp.data.Data.title;
this.author = resp.data.Data.author;
this.content = resp.data.Data.content;
this.btnSave = '更新';
if (resp.data.Data.is_public == 1) {
this.is_public = true;
} else {
this.is_public = false;
}
}
).catch(
reason => {
Message.error(reason)
}
)
}
this.userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
},
beforeCreate() {
axios.get("doc_types", {
withCredentials: true
}).then(
resp => {
this.doc_types = resp.data.Data;
}
).catch(
reason => {
Message.error(reason)
}
)
}
};
</script>
<style>
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,47 +0,0 @@
<template>
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
</template>
<script>
import Message from "element-ui/lib/message";
export default {
name: "filemanager",
data() {
return {
fileList: [
{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'},
{name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleExceed(files, fileList) {
Message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
beforeRemove(file, fileList) {
return Message.confirm(`确定移除 ${ file.name }`);
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,170 +0,0 @@
<template>
<div style="display: block">
<el-row>
<el-col :span="1" style="text-align:center; text-align: left; display:table;">
<p class="md-text1">硬件名字:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="硬件名字" v-model="title"></el-input>
</el-col>
</el-row>
<el-row :span = "3">
<el-col :span="1" style="text-align:center; text-align: left; display:table;">
<p class="md-text1">简介:</p>
</el-col>
<el-col :span="10">
<el-input type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="desc"></el-input>
</el-col>
</el-row>
<el-row :span = "3" style=" margin-top:10px;">
<el-col :span="1" style="text-align: left; display:table;">
<p class="md-text1">详细参数:</p>
</el-col>
<el-col :span="10">
<el-input type="textarea"
:rows="10"
placeholder="请输入内容"
v-model="content"></el-input>
</el-col>
</el-row>
<el-row :span = "3" style=" margin-top:10px;">
<el-col :span="2" style=" text-align: left; display:table;">
<p class="md-text1">购入时间:</p>
</el-col>
<el-col :span="1" style="margin-top: 5px;">
<el-date-picker
v-model="buy_date"
type="date"
placeholder="选择日期">
</el-date-picker>
</el-col>
</el-row>
<el-row :span = "3" style="margin-top: 10px;">
<el-col :span="2" style="text-align: left; display:table;">
<p class="md-text1">图片上传:</p>
</el-col>
</el-row>
<el-row :span = "3" style="margin-top: 10px;margin-left: 10px; text-align: left;">
<el-col :span="4" style="text-align:center; display:table;">
<el-upload
class="upload-demo"
action="http://127.0.0.1:4596/api/image_upload"
:on-remove="handleRemove"
:file-list="fileList"
:on-success = "handleResponse"
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png/gif文件</div>
</el-upload>
</el-col>
</el-row>
<el-row :span = "3" style="margin-top: 10px;margin-left: 10px; text-align: left;">
<el-button type="primary" @click="onSubmit"></el-button>
</el-row>
</div>
</template>
<script>
import Message from "element-ui/lib/message";
import axios from "@/api/ajax.js";
export default {
name: "hardwareAdd",
components: {
},
data: () => {
return {
buy_date:"",
baseurl:"",
title:"",
desc:"",
content:"",
fileList: [
],
responsefile:[]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleResponse(response, file, fileList){
let fileUrl = this.baseurl + "/" + response.url;
console.log(fileUrl)
this.responsefile.push(fileUrl)
//this.fileList.push({name: "image", url: fileUrl})
},
onSubmit(){
if (this.title == ""){
Message.error("硬件名字为空");
return
}
if(this.desc == ""){
Message.error("简述不能为空");
return
}
if(this.content == ""){
Message.error("内容不能为空");
return
}
if(this.buy_date == ""){
Message.error("购入时间不能为空");
return
}
let pic = "";
let first = 0;
this.responsefile.forEach(v => {
pic = pic + v +",";
})
axios.post("hardware",{
name:this.title,
buy_date:this.buy_date,
desc:this.desc,
doc:this.content,
pic:pic,
}).then(response=> {
console.log(response);
if (response.data.Status === 0)
{
Message.success("添加成功");
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
mounted() {
this.baseurl = process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_download':'https://www.testingcloud.club/sapi/api/image_upload';
console.log(this.baseurl)
}
}
</script>
<style scoped>
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,164 +0,0 @@
<template>
<div style="display: block">
<el-row>
<el-col :span="6">
<el-form ref="formInline" :model="formInline" :rules="ruleInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="文章名字" style="float: left"></el-input>
</el-form-item>
<el-form-item style="float: left">
<el-button @click="getArticles" style="float: left;margin-left: 10px;" type="primary">查询</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-table
:data="data1"
border
style="width: 100%;text-aligin:center">
<el-table-column
type="index"
width="50">
</el-table-column>
<el-table-column
prop="name"
label="名称"
width="120">
</el-table-column>
<el-table-column
prop="desc"
label="描述"
width="120">
</el-table-column>
<el-table-column
prop="pic"
label="缩略图"
width="120"
>
</el-table-column>
<el-table-column
prop="doc"
label="详细资料"
>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150">
<template slot-scope="scope">
<el-button type="text" @click="handleClick(scope)" size="small">查看</el-button>
<el-button type="text" @click="handleEdit(scope)" size="small">编辑</el-button>
<el-button type="text" @click="handleDelete(scope)" size="small">刪除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
layout="prev, pager, next"
:total="hardwareCount"
>
</el-pagination>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Message from "element-ui/lib/message";
import axios from "@/api/ajax.js";
import Cookie from "js-cookie";
import Const from "@/const.js";
export default {
name: "hardware_manager",
components: {
},
data: () => {
return {
hardwareCount:0,
data1:[],
data2:[],
formInline: {
dockname: '',
type: ''
},
limit:10,
offset :0,
is_public: 0,
};
},
methods: {
handleDelete(row) {
console.log(row);
axios.delete('hardware?name=' + row.row.name, {}).then(
result => {
if (result.data.Status === 0){
Message.success("删除成功");
}
}
)
},
getHardwares(){
axios.get('/hardware?limit=' + this.limit + '&offset=' + this.offset,{
}).then(response=> {
this.data1 = [];
if (response.data.Status === 0)
{
let j = 0;
if(response.data.Data != null){
for(let len= response.data.Data.length; j < len; j++) {
console.log(j,response.data.Data[j])
this.data2.push(response.data.Data[j]);
this.data1.push(response.data.Data[j]);
}
}
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
created() {
this.getHardwares();
},
beforeCreate() {
}
};
</script>
<style >
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,315 +0,0 @@
<template>
<div style="display: block">
<el-row>
<el-col :span="10">
<el-form ref="formInline" :model="formInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="备忘录标题" style="float: left"></el-input>
</el-form-item>
<el-form-item style="float: left">
<el-button @click="getMemos" type="primary" style="float: left;margin-left: 10px; ">查询1</el-button>
<el-button @click="drawer = true" type="primary" style="float: left;margin-left: 10px; ">新建</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-table
:data="memos"
border
style="width: 100%;text-aligin:center">
<el-table-column
prop="id"
label="id"
width="120" >
</el-table-column>
<el-table-column
prop="title"
label="标题"
width="120" >
</el-table-column>
<el-table-column
prop="create_time"
label="时间"
width="160">
</el-table-column>
<el-table-column
prop="content"
label="内容"
>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150">
<template slot-scope="scope">
<el-button type="text" @click="handleClick(scope)" size="small">查看</el-button>
<el-button type="text" @click="handleEdit(scope)" size="small">编辑</el-button>
<el-button type="text" @click="handleDelete(scope)" size="small">刪除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
layout="prev, pager, next"
:total="articleCount"
@current-change="handleChangePage"
>
</el-pagination>
</div>
<el-drawer
title="新增备忘"
:visible.sync="drawer"
:with-header="false"
:size=1256
:before-close="handleCloseDraw"
>
<div class="container">
<el-row style="margin-top: 10px;">
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">标题:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="标题" v-model="title"></el-input>
</el-col>
</el-row>
<el-row style="margin-top:30px;">
<mavon-editor style="height: 600px;margin-left: 4px;" v-model="memocontent" :subfield=this.subfield
:editable=this.editable ref="md" @imgAdd="$imgAdd" />
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addOrUpdateMemo">{{btnSave}}</el-button>
</el-col>
</el-row>
</div>
</el-drawer>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import utils from '@/util/times.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Drawer from 'element-ui/lib/drawer'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Drawer);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "tes",
data:()=>{
return{
editid:-1,
memos:[],
title:"",
btnSave:"保存",
drawer: false,
memocontent: "",
limit:10,
offset :0,
formInline: {
dockname: '',
type: ''
},
memoCount:0,
isupdate:false,
preview:false,
subfield:true,
editable:true,
value: new Date(),
articleCount:0
}
},
methods: {
$imgAdd(pos, $file){
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_upload':'https://www.testingcloud.club/sapi/api/image_upload',
method: 'post',
data: formdata,
headers: { 'Content-Type': 'multipart/form-data'},
}).then((url) => {
var url1 = process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_download/':'https://www.testingcloud.club/sapi/api/image_download/' + url.data.url;
this.$refs.md.$img2Url(pos, url1);
})
},
addOrUpdateMemo(){
if(this.isupdate === false){
axios.put('/memo',{
"title":this.title,
"content":this.memocontent,
"create_time": utils.getDateFormat(),
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("成功");
this.getMemos()
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}else{
axios.post('/memo',{
"id": this.editid,
"title":this.title,
"content":this.memocontent,
"create_time": utils.getDateFormat(),
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("更新成功")
this.getMemos()
}
})
}
},
handlerShow(done) {
Message.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleChangePage(page){
this.memos = [];
axios.post('/memos?limit=' + this.limit + '&offset=' + (page-1)*this.limit,{
}).then(response=> {
if (response.data.Status === 0)
{
let j = 0;
for(let len= response.data.Data.length; j < len; j++) {
this.memos.push(response.data.Data[j]);
}
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleClick(row){
this.title = row.row.title;
this.memocontent = row.row.content;
this.editid = row.row.id;
this.drawer = true;
this.preview=false,
this.subfield=false,
this.editable=false
},
handleEdit(row){
this.editable=true
this.title = row.row.title;
this.memocontent = row.row.content;
this.editid = row.row.id;
this.drawer = true;
this.isupdate = true;
},
handleCloseDraw(done) {
MessageBox.confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleDelete(row){
axios.post('/delmemo',{
"id":row.row.id
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("删除成功")
this.getMemos()
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getMemos(){
axios.post('/memos?limit=' + this.limit + '&offset=' + this.offset ,{
"title":"",
}).then(response=> {
this.memos = [];
if (response.data.Status === 0)
{
let j = 0;
for(let len= response.data.Data.length; j < len; j++) {
this.memos.push(response.data.Data[j]);
}
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getArticleCount(){
axios.get('/memocnt').then(response=> {
if (response.data.Status === 0)
{
console.log(response.data.Data)
this.articleCount = response.data.Data;
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
},
created(){
this.getMemos();
},
mounted() {
this.getArticleCount();
},
beforeCreate() {
}
}
</script>
<style scoped>
.el-button--primary:focus, .el-button--primary:hover{
background: lightblue;
}
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,198 +0,0 @@
<template>
<div class="container">
<el-row>
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">标dfs题:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="标题" v-model="title"></el-input>
</el-col>
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">分类:</p>
</el-col>
<el-col :span="3">
<el-select v-model="docType" placeholder="请选择" :value-key="docKey" >
<el-option
v-for="item in this.doc_types"
:key="item.Id"
:label="item.TypeName"
:value="item.Id"
>
</el-option>
</el-select>
</el-col>
<el-col :span="1" style="text-align:center; display:table; margin-top: 10px; font-size: 15px;">
<el-checkbox v-model="is_public"></el-checkbox>
</el-col>
</el-row>
<el-row style="margin-top:30px;">
<mavon-editor style="height: 600px" v-model="content" ref="md" @imgAdd="$imgAdd" />
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addArticle">{{btnSave}}</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
import Message from "element-ui/lib/message";
import axios from "@/api/ajax.js";
import Cookie from "js-cookie";
import Const from "@/const.js";
export default {
name: "editor",
components: {
},
data: () => {
return {
userInfo: {},
content: "",
title: "",
btnSave:"提交",
anchorAttrs: {
target: "_blank",
rel: "noopener noreferrer nofollow"
},
docKey: 0,
docType:1,
doc_types:[{Id:"1",TypeName:"fdsafd"}],
is_public:false,
};
},
methods: {
// @imgAdd event
$imgAdd(pos, $file){
// ..
var formdata = new FormData();
console.log($file);
formdata.append('image', $file);
axios({
url: process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_upload':'https://www.testingcloud.club/sapi/api/image_upload',
method: 'post',
data: formdata,
headers: { 'Content-Type': 'multipart/form-data'},
}).then((url) => {
console.log(url);
var url1 = process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_download/':'https://www.testingcloud.club/sapi/api/image_download/' + url.data.url;
// .url![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后`$vm``mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>`$vm``this.$refs.md`
*/
this.$refs.md.$img2Url(pos, url1);
})
},
changeType(){
},
addArticle() {
var x
if(this.btnSave == '提交'){
for (x in this.doc_types){
if(this.doc_types[x].Id === this.type){
this.docType = x;
}
//console.log(this.doc_types[x]);
//console.log(typeof (this.doc_types));
}
axios.put("/article", {
title: this.title,
content: this.content,
author: this.userInfo.DisplayName,
type: Number(this.docType),
author: this.userInfo.DisplayName,
is_public: this.is_public?1:0,
})
.then(response => {
if (response.data.Status === 0) {
Message.success("新增文章成功");
}
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
}else{
axios.post("/article_update", {
title: this.title,
content: this.content,
author: this.userInfo.DisplayName,
type: this.docType,
id: new Number(this.$route.query['id']),
is_public: this.is_public?1:0,
}).then(response => {
if (response.data.Status === 0) {
Message.success("更新文章成功");
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
}
}
},
created() {
if (this.$route.query['id'] != undefined ) {
console.log("query para is ",this.$route.query['id']);
// query
//todo
let url = '/article/' + this.$route.query['id'];
axios.get(url,{withCredentials:true}).then(
resp => {
console.log(resp.data.Data.type);
this.docType = resp.data.Data.type;
this.title = resp.data.Data.title;
this.author = resp.data.Data.author;
this.content = resp.data.Data.content;
this.btnSave = '更新';
if(resp.data.Data.is_public == 1){
this.is_public = true;
}else{
this.is_public = false;
}
}
).catch(
reason => {
Message.error(reason)
}
)
}
this.userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
},
beforeCreate() {
axios.get("doc_types",{withCredentials:true}).then(
resp => {
this.doc_types = resp.data.Data;
console.log(this.doc_types);
}
).catch(
reason => {
Message.error(reason)
}
)
}
};
</script>
<style >
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,321 +0,0 @@
<template>
<div style="display: block;background: white;">
<el-row>
<el-col :span="8">
<el-calendar v-model="value" style="color: #2c3e50;" >
<!-- 这里使用的是 2.5 slot 语法对于新项目请使用 2.6 slot 语法-->
<template
slot="dateCell"
slot-scope="{date, data}" @click="testclick">
<p :class="data.isSelected ? 'is-selected' : ''" @click="testclick">
{{ data.day.split('-').slice(1).join('-') }} {{monthdays.includes(data.day)? '✔️' : ''}}
</p>
</template>
</el-calendar>
</el-col>
<el-col :span="5" style="color: #2c3e50; margin-top:30px;">
<el-timeline >
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp">
{{activity.content}} {{ getTypeName(parseInt(activity.type))}}
</el-timeline-item>
</el-timeline>
</el-col>
<el-col :span="10" style="color: #2c3e50;margin-top:30px;">
<el-time-select
placeholder="起始时间"
v-model="startTime"
:picker-options="{
start: '07:00',
step: '00:10',
end: '18:30'
}" style=" width:100px;">
</el-time-select>
<el-time-select
placeholder="结束时间"
v-model="endTime"
:picker-options="{
start: '07:00',
step: '00:10',
end: '18:30',
minTime: startTime
}" style="margin-left: 5px; width:100px;">
</el-time-select>
<el-select v-model="selectType" placeholder="计划类型" style="margin-left: 10px;width: 120px;">
<el-option
v-for="item in types"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button style="margin-left: 5px;" @click="this.addPlan"></el-button>
<el-input
type="textarea"
:rows="10"
placeholder="请输入内容"
v-model="plan"
style="margin-left: 5px; margin-top: 30px; "
>
</el-input>
<p style="margin-top: 200px; font-size: 20px;">今日已计划 {{this.planhours}} 小时 {{this.planminutes}} 分钟,{{this.activities.length - 1}} 个计划</p>
</el-col>
</el-row>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import utils from '@/util/times.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Drawer from 'element-ui/lib/drawer'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Drawer);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "planManager",
computed:{
},
data:()=>{
return{
date: new Date,
data:{},
value: new Date(),
activities: [
],
endTime:"18:30",
startTime :"07:00",
plan:"",
monthdays: [],
planhours : 0,
planminutes : 0,
types: [],
selectType:""
}
},
methods: {
getTypeName(typeid){
if(this.types[typeid] != undefined)
return "[" + this.types[typeid].label + "]";
else
return ""
},
dateFormat(fmt, date) {
let ret;
const opt = {
"Y+": date.getFullYear().toString(), //
"m+": (date.getMonth() + 1).toString(), //
"d+": date.getDate().toString(), //
"H+": date.getHours().toString(), //
"M+": date.getMinutes().toString(), //
"S+": date.getSeconds().toString() //
//
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
},
getMonthPlans(monthdate){
console.log("shit3",monthdate)
let date = this.dateFormat("YYYY-mm-dd HH:MM", monthdate)
console.log("shit4",date)
axios.post('/plan_days', {
date: date
}).then(response => {
if (response.data.Status === 0) {
this.monthdays = []
for (let i = 0;i < response.data.Data.length;i ++){
this.monthdays.push(response.data.Data[i].date)
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
testclick(t){
this.timer = setTimeout(()=>{
this.getPlans(this.dateFormat("YYYY-mm-dd", this.value))
}, 300);
console.log(t)
},
timeAfter(t1, t2){
let hour1 = t1.split(":")
let hour2 = t2.split(":")
if(parseInt(hour1[0]) > parseInt(hour2[0])){
return true
}else if(parseInt(hour1[0]) === parseInt(hour2[0])){
if(parseInt(hour1[1]) > parseInt(hour2[1])){
return true
}else{
return false
}
}else {
return false
}
},
addPlan(){
if(!this.timeAfter(this.endTime,this.startTime)){
Message.error("开始时间必须小于结束时间")
return
}
if(this.plan == ""){
Message.error("请输入内容")
return
}
if(this.selectType === ""){
Message.error("请选择计划类型")
return
}
for (let i = 0;i < this.activities.length; i ++){
if((this.timeAfter(this.activities[i].startTime,this.startTime) != this.timeAfter(this.activities[i].timestamp, this.startTime))){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突1");
return;
}
if((this.timeAfter(this.activities[i].startTime,this.endTime) != this.timeAfter(this.activities[i].timestamp, this.endTime))){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突2");
return;
}
if((this.timeAfter(this.startTime,this.activities[i].startTime) != this.timeAfter(this.startTime,this.activities[i].timestamp))){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突3");
return;
}
if((this.timeAfter(this.endTime,this.activities[i].startTime) != this.timeAfter(this.endTime,this.activities[i].timestamp))){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突4");
return;
}
if((!this.timeAfter(this.startTime,this.activities[i].startTime)) && this.timeAfter(this.endTime,this.activities[i].timestamp)){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突5");
return;
}
if(!this.timeAfter(this.endTime,this.activities[i].startTime) && this.timeAfter(this.endTime,this.activities[i].timestamp)){
Message.error("时间和 " + this.activities[i]['content'] + " 冲突6");
return;
}
}
axios.put('/plan', {
date: this.dateFormat("YYYY-mm-dd", this.value),
content:this.plan,
start_time: this.dateFormat("YYYY-mm-dd", this.value) + " " + this.startTime + ":00",
end_time: this.dateFormat("YYYY-mm-dd", this.value) + " " + this.endTime + ":00",
type:this.selectType
}).then(response => {
if (response.data.Status === 0) {
this.activities.push({'content':this.plan,'timestamp':this.endTime,'startTime':this.startTime})
Message.success("添加计划: " + this.plan + " 成功");
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
calcMinutes(t1,t2){
let tmp1 = t1.split(":")
let tmp2 = t2.split(":")
let hour1 = parseInt(tmp1[0])
let hour2 = parseInt(tmp2[0])
let minute1 = parseInt(tmp1[1])
let minute2 = parseInt(tmp1[1])
let minute1all = hour1 * 60 + minute1
let minute2all = hour2 * 60 + minute2
return minute1all - minute2all
},
getPlayType(){
axios.get('/plan_types').then(response => {
if (response.data.Status === 0) {
for(let i = 0;i < response.data.Data.length; i ++){
this.types.push({
value: response.data.Data[i].id,
label: response.data.Data[i].type_name
})
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getPlans(date){
this.activities = [{
content: '起床',
timestamp: '07:30',
startTime:'07:20',
}
];
axios.post('/get_plans', {
date: this.dateFormat("YYYY-mm-dd", this.value),
}).then(response => {
let minutes = 0;
if (response.data.Status === 0) {
for (let i = 0;i < response.data.Data.length;i ++){
response.data.Data[i].startTime = this.dateFormat("HH:MM", new Date(response.data.Data[i].start_time))
response.data.Data[i].timestamp = this.dateFormat("HH:MM", new Date(response.data.Data[i].end_time))
this.activities.push(response.data.Data[i])
minutes += this.calcMinutes(response.data.Data[i].timestamp,response.data.Data[i].startTime)
}
this.planhours = minutes / 60
this.planminutes = minutes % 60
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
}
},
created(){
this.getPlayType()
},
mounted() {
this.$nextTick(() => {
//
let prevBtn = document.querySelector(
'.el-calendar__button-group .el-button-group>button:nth-child(1)');
prevBtn.addEventListener('click', () => {
this.getPlans(this.dateFormat("YYYY-mm-dd",new Date(this.value)));
this.getMonthPlans(new Date(this.value));
})
})
this.$nextTick(() => {
//
let prevBtn = document.querySelector(
'.el-calendar__button-group .el-button-group>button:last-child');
prevBtn.addEventListener('click', () => {
this.getPlans(this.dateFormat("YYYY-mm-dd",new Date(this.value)));
this.getMonthPlans(new Date(this.value));
})
})
this.getPlans(this.dateFormat("YYYY-mm-dd", new Date));
this.getMonthPlans(new Date);
},
beforeCreate() {
}
}
</script>
<style scoped>
.is-selected {
color: #1989FA;
}
</style>

View File

@ -1,29 +0,0 @@
<template>
<div style="display: block">
</div>
</template>
<script>
export default {
name: "template",
data:()=>{
return{
}
},
methods: {
},
created(){
},
mounted() {
},
beforeCreate() {
}
}
</script>
<style scoped>
</style>

View File

@ -1,280 +0,0 @@
<template>
<div style="display: block">
<el-row>
<el-col :span="10">
<el-form ref="formInline" :model="formInline" style="float: left">
<el-form-item style="float: left">
<el-button @click="drawer = true" type="primary" style="float: left;margin-left: 10px; ">新建文章模板</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-table
:data="memos"
border
style="width: 100%;text-aligin:center">
<el-table-column
prop="id"
label="id"
width="120" >
</el-table-column>
<el-table-column
prop="name"
label="模板"
width="120" >
</el-table-column>
<el-table-column
prop="content"
label="内容"
>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150">
<template slot-scope="scope">
<el-button type="text" @click="handleClick(scope)" size="small">查看</el-button>
<el-button type="text" @click="handleEdit(scope)" size="small">编辑</el-button>
<el-button type="text" @click="handleDelete(scope)" size="small">刪除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
layout="prev, pager, next"
:total="articleCount"
@current-change="handleChangePage"
>
</el-pagination>
</div>
<el-drawer
title="新增模板"
:visible.sync="drawer"
:with-header="false"
:size=50
:before-close="handleCloseDraw"
>
<div class="container">
<el-row style="margin-top: 10px;">
<el-col :span="1" style="text-align:center; display:table;">
<p class="md-text1">模板:</p>
</el-col>
<el-col :span="3">
<el-input placeholder="模板" v-model="title"></el-input>
</el-col>
</el-row>
<el-row style="margin-top:30px;">
<mavon-editor style="height: 600px;margin-left: 4px;" v-model="memocontent" :subfield=this.subfield :defaultOpen=this.preview
:editable=this.editable ref="md" @imgAdd="$imgAdd" />
</el-row>
<el-row>
<el-col :span="24" style="margin-top: 20px">
<el-button @click="addOrUpdateMemo">{{btnSave}}</el-button>
</el-col>
</el-row>
</div>
</el-drawer>
</div>
</template>
<script>
import axios from '@/api/ajax.js'
import utils from '@/util/times.js'
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Vue from "vue/dist/vue.js";
import Pagination from 'element-ui/lib/pagination';
import Message from 'element-ui/lib/message'
import Drawer from 'element-ui/lib/drawer'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Drawer);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
export default {
name: "tes",
data:()=>{
return{
editid:-1,
memos:[],
title:"",
btnSave:"保存",
drawer: false,
memocontent: "",
limit:10,
offset :0,
formInline: {
dockname: '',
type: ''
},
memoCount:0,
isupdate:false,
preview:false,
subfield:true,
editable:true,
value: new Date(),
articleCount:0
}
},
methods: {
$imgAdd(pos, $file){
// ..
var formdata = new FormData();
formdata.append('image', $file);
axios({
url: process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_upload':'https://www.testingcloud.club/sapi/api/image_upload',
method: 'post',
data: formdata,
headers: { 'Content-Type': 'multipart/form-data'},
}).then((url) => {
var url1 = process.env.NODE_ENV === 'development'?'http://127.0.0.1:4596/api/image_download/':'https://www.testingcloud.club/sapi/api/image_download/' + url.data.url;
this.$refs.md.$img2Url(pos, url1);
})
},
addOrUpdateMemo(){
if(this.isupdate === false){
axios.put('/doc_template',{
"content":this.memocontent,
"name": this.title,
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("成功");
this.getMemos()
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
}else{
axios.post('/doc_template',{
"id": this.editid,
"name":this.title,
"content":this.memocontent,
}).then(response=> {
if (response.data.Status === 0)
{
Message.success("更新成功")
this.getMemos()
}
})
}
},
handlerShow(done) {
Message.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleChangePage(page){
this.memos = [];
axios.post('/get_doc_template?limit=' + this.limit + '&offset=' + (page-1)*this.limit,{
}).then(response=> {
if (response.data.Status === 0)
{
let j = 0;
for(let len= response.data.Data.length; j < len; j++) {
this.memos.push(response.data.Data[j]);
}
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleClick(row){
this.title = row.row.name;
this.memocontent = row.row.content;
this.editid = row.row.id;
this.drawer = true;
this.preview=false,
this.subfield=false,
this.editable=false
},
handleEdit(row){
this.editable=true
this.title = row.row.name;
this.memocontent = row.row.content;
this.editid = row.row.id;
this.drawer = true;
this.isupdate = true;
},
handleCloseDraw(done) {
MessageBox.confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
handleDelete(row){
axios.delete('/doc_template/' + row.row.id).then(response=> {
if (response.data.Status === 0)
{
Message.success("删除成功")
this.getMemos()
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
getMemos(){
axios.post('/get_doc_template?limit=' + this.limit + '&offset=' + this.offset ,{
"title":"",
}).then(response=> {
this.memos = [];
if (response.data.Status === 0)
{
this.memos = response.data.Data
}
}
).catch(reason => {
Message.error("网络错误:" + reason);
});
},
},
created(){
this.getMemos();
},
mounted() {
},
beforeCreate() {
}
}
</script>
<style scoped>
.el-button--primary:focus, .el-button--primary:hover{
background: lightblue;
}
.container {
width: 100%;
}
.md-text {
font-size: 12px;
width: 100%;
}
.md-body {
width: 100%;
margin-left: 20px;
}
.md-text1 {
font-size: 15px;
margin-top: 10px;
}
.mavonEditor {
width: 100%;
height: 800px;
}
</style>

View File

@ -1,29 +0,0 @@
<template>
<div style="display: block">
</div>
</template>
<script>
export default {
name: "template",
data:()=>{
return{
}
},
methods: {
},
created(){
},
mounted() {
},
beforeCreate() {
}
}
</script>
<style scoped>
</style>

View File

@ -1,314 +0,0 @@
<template>
<div style="display: inline-block;width: 100%;float: left;height: 100%;">
<el-col :span="10" style="height: 100%;margin-right: 50px;">
<el-tree
:data="this.data"
node-key="id"
:expand-on-click-node="false"
default-expand-all
style="height: 90%;overflow-x: scroll; overflow-x: scroll;font-size: 12px;"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<el-button
type="text"
size="mini"
@click="() => append(data)" style="font-size: 12px;">
添加计划
</el-button>
<el-button
type="text"
size="mini"
@click="() => remove(node, data)" style="font-size: 12px;">
删除计划
</el-button>
<el-button
type="text"
size="mini"
@click="() => finish(node, data)">
完成计划
</el-button>
</span>
</span>
</el-tree>
</el-col>
<el-col :span="2" style=""></el-col>
<el-col :span="10" style="height: 100%">
<el-tree
:data="this.done_data"
node-key="id"
default-expand-all
:expand-on-click-node="false"
style="height: 90%;overflow-x: scroll;font-size: 12px;"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span style="overflow-x: scroll;">{{ node.label }}</span>
<span>
<el-button
type="text"
size="mini"
@click="() => unfinish(node, data)">
移到未完成
</el-button>
</span>
</span>
</el-tree>
</el-col>
<el-dialog
title="完成事项"
:visible.sync="this.dialogVisible"
width="30%"
>
<el-form label-width="80px" :model="formLabelAlign">
<el-form-item label="完成事项:">
<el-input v-model="formLabelAlign.name"></el-input>
</el-form-item>
<el-form-item label="类型:">
<el-select v-model="selectType" placeholder="计划类型" style="margin-left: -50%;width: 120px;">
<el-option
v-for="item in types"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="this.addUndo"></el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Message from "element-ui/lib/message";
import axios from "@/api/ajax";
export default {
name: "undo_data",
data:() => {
return{
dialogVisible : false,
done_data:[],
data : [],
currentNode:{},
formLabelAlign: {
name: '',
id: 0,
type: ''
},
types:[],
selectType:"",
mapundo : {},
mapDone : {},
}
},
methods: {
getUndos(){
axios.get('/undo').then(response => {
this.data = []
this.mapundo = {}
this.mapDone = {}
this.done_data = []
if (response.data.Status === 0) {
if(response.data.Data.length === 0 ){
axios.put('/undo', {
"content":"待办事项",
"parent":0,
"type":0
}).then(response => {
if (response.data.Status === 0) {
Message.success("新增待办事项:")
}
}).catch(reason => {
Message.error("网络错误:" + reason)
})
}
//
for(let i = 0;i < (response.data.Data.length) ; i ++){
let obj = {
id: response.data.Data[i].id,
label:response.data.Data[i].content + " : " + response.data.Data[i].create_time.substring(0,10),
children: []
}
if(response.data.Data[i].parent === 0){
if(response.data.Data[i].done == 1)
continue
this.data.push(obj)
}
this.mapundo[response.data.Data[i].id] = obj
}
for(let i = 0;i < (response.data.Data.length) ; i ++){
if(response.data.Data[i].parent === 0){
}else{
if(this.mapundo[response.data.Data[i].parent] != null){
if(response.data.Data[i].done == 1)
continue
this.mapundo[response.data.Data[i].parent].children.push(this.mapundo[response.data.Data[i].id])
}
}
}
let root = {}
for(let i = 0;i < (response.data.Data.length) ; i ++){
let obj = {
id: response.data.Data[i].id,
label:response.data.Data[i].content + " : " + response.data.Data[i].finish_time.substring(0,10),
children: []
}
this.mapDone[response.data.Data[i].id] = obj
if(response.data.Data[i].parent === 0)
root = obj
}
console.log(this.mapDone)
try{
for(let i = 0;i < (response.data.Data.length) ; i ++) {
if(response.data.Data[i].done === 1) {
let fors = response.data.Data[i]
while(fors.parent !== 0){
let parent = this.mapDone[fors.parent]
let obj = this.mapDone[fors.id]
let found = 0
if (parent == undefined){
console.log("12312312",fors.parent)
break
}
if(parent.children == undefined){
console.log("fsdfasdfasd")
}
for(let i = 0;i < (parent.children.length); i++) {
console.log(parent.children[i])
if(parent.children[i].id == obj.id){
found = 1
break
}
}
if(found === 0){
parent.children.push(obj)
}
for(let i = 0;i < (response.data.Data.length) ; i ++) {
if(fors.parent == response.data.Data[i].id){
fors = response.data.Data[i]
}
}
}
}
}
}catch(e ){
console.log(e)
}
root.label = "完成事项"
this.done_data.push(root)
}
}).catch(reason => {
Message.error("网络错误:" + reason)
})
},
addUndo(){
if(this.formLabelAlign.name === ""){
Message.error("内容为空")
return
}
axios.put('/undo', {
"content":this.formLabelAlign.name,
"parent":this.currentNode.id,
"type":this.selectType
}).then(response => {
if (response.data.Status === 0) {
console.log(this.currentNode)
Message.success("添加成功")
const newChild = { id: response.data.Data, label: this.formLabelAlign.name, children: [] }
this.currentNode.children.push(newChild)
}
}).catch(reason => {
Message.error("网络错误:" + reason)
})
this.dialogVisible = false
console.log(this.data)
},
append(data) {
this.dialogVisible = true
if (!data.children) {
this.$set(data, 'children', [])
}
this.currentNode = data
},
remove(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id)
if(data.children.length > 0){
Message.error("请先删除子项")
return
}
axios.delete('/undo/' + data.id).then(response => {
console.log(response.data)
Message.success("删除成功:")
this.getUndos()
}).catch(reason => {
Message.error("网络错误:" + reason)
})
children.splice(index, 1)
},
finish(node,data){
if(data.children.length > 0){
Message.error("请先完成子项")
return
}
axios.post('/undo_finish/' + data.id).then(response => {
if (response.data.Status === 0) {
Message.success("完成" + data.label)
this.getUndos()
}
}).catch(reason => {
Message.error("网络错误:" + reason)
})
}
,
unfinish(node,data){
if(data.children.length > 0){
Message.error("请先完成子项")
return
}
axios.post('/undo_unfinish/' + data.id).then(response => {
if (response.data.Status === 0) {
Message.success("完成" + data.label)
this.getUndos()
}
}).catch(reason => {
Message.error("网络错误:" + reason)
})
},
},
created(){
this.types = this.Global.planTypes
this.getUndos()
},
mounted() {
},
beforeCreate() {
}
}
</script>
<style scoped>
.custom-tree-node {
justify-content: space-around;
display:block;
padding-right: 8px;
overflow-x: auto;
overflow-y: auto;
margin-top: 10px;
}
</style>

View File

@ -1,129 +0,0 @@
<template>
<div style="display: block">
<el-form ref="formInline" :model="formInline" :rules="ruleInline" style="float: left">
<el-form-item prop="user" style="float: left">
<el-input type="text" v-model="formInline.user" placeholder="用户名" style="float: left"></el-input>
</el-form-item>
<el-form-item style="float: left">
<el-button type="primary" @click="searchUsers" style="float: left;margin-left: 10px;">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="data1"
stripe
style="width: 100%">
<el-table-column
prop="id"
label="用户id"
width="180">
</el-table-column>
<el-table-column
prop="user_name"
label="用户名字"
width="180">
</el-table-column>
<el-table-column
prop="tel"
label="用户手机">
</el-table-column>
<el-table-column
prop="email_address"
label="邮件">
</el-table-column>
<el-table-column
prop="avatar"
label="头像">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="100">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
//
import axios from '@/api/ajax.js'
import store from '@/store/index.js'
import Cookie from 'js-cookie'
import Const from '@/const.js'
import Table from 'element-ui/lib/table'
import TableColumn from 'element-ui/lib/table-column'
import Vue from "vue/dist/vue.js";
Vue.use(Table);
Vue.use(TableColumn);
import { userInfo } from 'os';
export default {
name: "tes",
data:() => {
return{
limit:10,
offset :0,
formInline: {
user: '',
type: ''
},
ruleInline: {
user: [
{ message: 'Please fill in the user name', trigger: 'blur' }
],
password: [
{ message: 'Please fill in the password.', trigger: 'blur' },
{ type: 'string'}
]
},
data1: [
]
}
},
methods: {
searchUsers(){
let userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
axios.post('/search_users?limit=' + this.limit + '&offset=' + this.offset+ '&userid='
+ userInfo['ID'] + '&token=' + userInfo['SocketToken'],{
username:this.formInline.user
}).then(response=> {
console.log(response.data);
if (response.data.Status === 0)
{
this.data1 = [];
this.data1.push(response.data.Data.users[0])
}
}
).catch(reason => {
//this.$Message(":" + reason);
});
}
},
created(){
console.log(Cookie.get("sess_store"))
let userInfo = JSON.parse(Cookie.get(Const.KEY_USER_INFO));
let url = '/users?limit=' + this.limit + '&offset=' + this.offset + '&userid='
+ userInfo['ID'] + '&token=' + userInfo['SocketToken'] ;
axios.get(url)
.then(response=> {
console.log(response.data);
if (response.data.Status === 0){
this.data1.push(response.data.Data.users[0])
}
else {
this.$router.push("/login");
}
}
)
},
activated() {
console.log("activated");
}
}
</script>
<style scoped>
</style>

View File

@ -1,5 +0,0 @@
import Cookie from 'js-cookie'
export default {
KEY_USER_INFO: "userInfo",
}

View File

@ -1,11 +0,0 @@
/*
Write your variables here. All available variables can be
found in element-ui/packages/theme-chalk/src/common/var.scss.
For example, to overwrite the theme color:
*/
$--color-primary: rgb(0, 109, 222);
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";

View File

@ -1,92 +0,0 @@
/*
* @Author: your name
* @Date: 2019-05-25 02:08:04
* @LastEditTime: 2021-11-06 17:04:29
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \background-front\src\main.js
*/
import Vue from 'vue';
import Button from "element-ui/lib/button";
import Dialog from "element-ui/lib/dialog";
import Form from "element-ui/lib/form";
import FormItem from "element-ui/lib/form-item";
import Input from "element-ui/lib/input";
import CheckBox from "element-ui/lib/checkbox";
import Card from "element-ui/lib/card"
import Select from "element-ui/lib/select"
import Table from 'element-ui/lib/table';
import ELTableColumn from 'element-ui/lib/table-column';
import BreadCrumb from 'element-ui/lib/breadcrumb'
import Options from "element-ui/lib/option"
import Radio from "element-ui/lib/radio"
import Upload from "element-ui/lib/upload"
import DatePicker from "element-ui/lib/date-picker"
import Drawer from "element-ui/lib/drawer"
import Message from "element-ui/lib/message"
import MessageBox from "element-ui/lib/message-box"
import Pagination from "element-ui/lib/pagination"
import Calendar from "element-ui/lib/calendar"
import TimeLine from "element-ui/lib/timeline"
import TimeLineItem from "element-ui/lib/timeline-item"
import TimeSelect from "element-ui/lib/time-select"
import Tree from "element-ui/lib/tree"
import "element-ui/lib/theme-chalk/index.css";
import "./plugins/axios";
import App from "./App.vue";
import router from "./router";
import Router from "vue-router";
import Axios from "axios";
import store from "./store/index.js";
import "mavon-editor/dist/css/index.css";
import MavonEditor from 'mavon-editor'
import global from "@/store/global";
console.log(MavonEditor)
Vue.use(Tree);
Vue.use(TimeSelect);
Vue.use(TimeLineItem);
Vue.use(TimeLine);
Vue.use(Calendar);
Vue.use(Message);
Vue.use(MessageBox);
Vue.use(Drawer);
Vue.use(BreadCrumb);
Vue.use(ELTableColumn);
Vue.use(Upload);
Vue.use(Table);
Vue.use(Pagination);
Vue.use(Select);
Vue.use(Options);
Vue.use(Radio);
Vue.use(DatePicker);
Vue.use(MavonEditor);
Vue.use(Input);
Vue.use(CheckBox);
Vue.use(Button);
Vue.use(Dialog);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Router);
Vue.use(Axios);
Vue.use(Card);
Vue.prototype.Global = global
router.beforeEach((to,from,next)=>{
window.addEventListener('load',function () {
let x = from.hash.replace(to.hash,"")
x = x.replace("#","")
router.push(x)
})
next();
})
new Vue({
render: h => h(App),
el: "#app",
store: store,
router: router
}).$mount("#app");

View File

@ -1,61 +0,0 @@
"use strict";
import Vue from 'vue';
import axios from "axios";
// Full config: https://github.com/axios/axios#request-config
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let config = {
// baseURL: process.env.baseURL || process.env.apiUrl || ""
// timeout: 60 * 1000, // Timeout
// withCredentials: true, // Check cross-site Access-Control
};
const _axios = axios.create(config);
_axios.interceptors.request.use(
function(config) {
// Do something before request is sent
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
// Add a response interceptor
_axios.interceptors.response.use(
function(response) {
// Do something with response data
return response;
},
function(error) {
// Do something with response error
return Promise.reject(error);
}
);
Plugin.install = function(Vue, options) {
Vue.axios = _axios;
window.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
}
},
$axios: {
get() {
return _axios;
}
},
});
};
Vue.use(Plugin)
export default Plugin;

View File

@ -1,5 +0,0 @@
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element)

View File

@ -1,6 +0,0 @@
import Vue from 'vue'
import iView from 'iview'
Vue.use(iView)
import '../iview-variables.less'

View File

@ -1,157 +0,0 @@
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router);
/* eslint-disable */
export default new Router({
mode: 'history',
base: process.env.NODE_ENV === 'production'? "/dist/admin/index.html#":'/',
routes: [
{
path:'/login',
name:'login',
component: (resolve) => require(['./views/Login'],resolve),
},
{
path: '/BarIview',
name: '基础功能',
component: (resolve) => require(['./views/SideBarView.vue'],resolve),
children:[
{
path: "template_manager",
name: "模板管理",
component: (resolve) => require(['./components/templateManager'], resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path: "memo_manager",
name: "备忘录管理",
component: (resolve) => require(['./components/memoManage'], resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path: "plan_manager",
name: "计划管理",
component: (resolve) => require(['./components/planManager'], resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path: "todo_read",
name: "办事必先看",
component: (resolve) => require(['./components/todo_read'], resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path: "undo_project",
name: "代办事项",
component: (resolve) => require(['./components/undo'], resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path: "articleManageTree",
name: "文章树管理",
component: (resolve) => require(['./components/articleManageTree.vue'], resolve)
}
],
meta: {
keepAlive: true ,// 此组件需要被缓存
isBack: false
}
},
{
path: '/BarIview',
name: '二期功能',
component: (resolve) => require(['./views/SideBarView.vue'],resolve),
children:[
{
path:"bugManager",
name:"bug管理",
component: (resolve) => require(['./components/bug_manager.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"hardwareManager",
name:"硬件查询",
component: (resolve) => require(['./components/hardware_manager.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"hardwareAdd",
name:"添加硬件",
component: (resolve) => require(['./components/hardwareAdd.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"needsAdd",
name:"需求管理",
component: (resolve) => require(['./components/bugAdd.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"fileManager",
name:"文件管理",
component: (resolve) => require(['./components/filemanager.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"bookManager",
name:"书籍管理",
component: (resolve) => require(['./components/template.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
},
{
path:"study_manager",
name:"学习管理",
component: (resolve) => require(['./components/book.vue'],resolve),
meta:
{
keepAlive: true, //此组件不需要被缓存
}
}
]
},
{
path: "/article/:id",
name: "articleShow",
component: (resolve) => require(['./views/articleShow.vue'],resolve),
meta: {
keepAlive: true, //此组件不需要被缓存
}
},
{
path:'/monitor',
name:'monitor',
component: (resolve) => require(['./views/VideoPlayer'],resolve),
},
]
})

View File

@ -1,38 +0,0 @@
<!--
* @Author: your name
* @Date: 2021-03-06 17:30:16
* @LastEditTime: 2021-08-27 00:00:39
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \background-front\src\store\global.vue
-->
<template></template>
<script type="text/javascript">
import axios from "@/api/ajax";
import Message from "element-ui/lib/message";
export default {
planTypes:[],
ws:{},
Set_plan_type(planType){
this.planTypes = planType
},
SetWebsocket(ws){
this.ws = ws
},
mounted() {
axios.get('/plan_types').then(response => {
if (response.data.Status === 0) {
for(let i = 0;i < response.data.Data.length; i ++){
this.planTypes.push({
value: response.data.Data[i].id,
label: response.data.Data[i].type_name
})
}
}
}).catch(reason => {
Message.error("网络错误:" + reason);
});
},
}
</script>

View File

@ -1,30 +0,0 @@
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
namespace:false,
state: {
account:{},
count:0,
},
mutations: {
increament: state => {
state.count ++
},
decrement: state => {
state.count --
},
setAccount (state,account){
state.account = account
}
},
actions: {
},
getters:{
userInfo: state =>{
return state.account;
}
}
});
export default store;

View File

@ -1,35 +0,0 @@
let utils = {}
utils.getDateFormat = function () {
var date = new Date();
//年
var year= date.getFullYear();
//月
var month = date.getMonth()+1;
if(month < 10){
month = "0" + month
}
//日
var day = date.getDate();
if(day < 10){
day = "0" + day
}
//时
var hh = date.getHours();
if(hh < 10){
hh = "0" + hh
}
//分
var mm = date.getMinutes();
if(mm < 10){
mm = "0" + mm
}
//秒
var ss = date.getSeconds();
if(ss < 10){
ss = "0" + ss
}
var rq = year + "-" + month + "-" + day + " "+ hh + ":" + mm + ":"+ss;
return rq;
}
export default utils;

View File

@ -1,277 +0,0 @@
<template>
<div>
<el-dialog title="用户注册" :visible.sync="modallogin" :closable="true" :mask-closable="false" style="width: 50%;margin-left: 25%">
<p slot="header" style="color:#84a1ff;text-align:center">
<span>用户注册</span>
</p>
<el-form :model="ruleForm1" :rules="rules1" ref="ruleForm1" label-position="left" label-width="20%">
<el-form-item prop="account" style="width: 70%; margin-left: 10%" auto-complete="off" label="账号">
<el-input type="text" v-model="ruleForm1.account" auto-complete="off" placeholder="账号">
</el-input>
</el-form-item>
<el-form-item prop="nickname" style="width: 70%;margin-left: 10%" label="昵称">
<el-input type="text" v-model="ruleForm1.nickname" placeholder="昵称"></el-input>
</el-form-item>
<el-form-item prop="checkPass" style="width: 70%;margin-left: 10%" label="密码">
<el-input type="password" v-model="ruleForm1.checkPass" auto-complete="off" placeholder="密码"></el-input>
</el-form-item>
<el-form-item prop="checkPass1" style="width: 70%;margin-left: 10%" label="重复密码">
<el-input type="password" v-model="ruleForm1.checkPass1" auto-complete="off" placeholder="再次输入密码"></el-input>
</el-form-item>
<el-form-item prop="email" style="width: 70%;margin-left: 10%" label="邮箱">
<el-input type="text" v-model="ruleForm1.email" auto-complete="off" placeholder="邮箱">
</el-input>
</el-form-item>
<el-form-item prop="verify" style="width:70%;margin-left: 10%" label="验证码">
<el-input type="text" style="width: 50%;float: left;font-size: 8px" v-model="ruleForm1.verify" auto-complete="off" placeholder="验证码"></el-input>
<el-button type="primary" style="margin-left:10%; font-size:7px;width:39%;" @click.native.prevent="handleVerify" :loading="logining">发送验证码</el-button>
</el-form-item>
<el-form-item style="width:30%;margin-left: 35%">
<el-button type="primary" @click.native.prevent="handleRegister" :loading="logining">注册</el-button>
</el-form-item>
</el-form>
<div slot="footer"></div>
</el-dialog>
<el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left" label-width="0px" class="demo-ruleForm login-container">
<h3 class="title">系统登录</h3>
<el-form-item prop="account">
<el-input type="text" v-model="ruleForm2.account" auto-complete="off" placeholder="账号"></el-input>
</el-form-item>
<el-form-item prop="checkPass">
<el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off" placeholder="密码"></el-input>
</el-form-item>
<el-checkbox v-model="checked" checked class="remember" style="float: left;"></el-checkbox>
<el-form-item style="width:100%;">
<el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit2" :loading="logining">登录</el-button>
</el-form-item>
<el-form-item style="width:100%;height: 10px">
<a style="float: right" @click="modallogin = true">注册</a>
</el-form-item>
</el-form>
</div>
</template>
<script>
import ajax from "../api/ajax";
import store from "../store/index";
import Cookie from "js-cookie";
import Const from "@/const.js";
import Message from 'element-ui/lib/message'
export default {
name: "login",
store: store,
data() {
const validateEmail = (rule, value, callback) => {
if (value === "") {
console.log("value is " + value);
callback("请输入邮箱");
} else {
let reg = new RegExp(
"^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$"
);
if (!reg.test(value)) {
callback("邮箱格式错误");
} else {
callback();
}
}
};
const validatePassword = (rule, value, callback) => {
if (value === "") {
callback("请再次输入密码");
} else {
if (typeof value == "string") {
let pattern = /^[\w_-]{6,16}$/;
if (pattern.test(value)) {
callback();
} else {
callback("密码不合规最短6位最长16位,");
}
}
}
};
return {
validatePassCheck: (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.formCustom.passwd) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
},
modallogin: false,
logining: false,
ruleForm1: {
account: "",
checkPass: "",
checkPass1: "",
verify: "",
email: "",
nickname: ""
},
ruleForm2: {
account: "admin",
checkPass: "123456"
},
rules1: {
account: [{
required: true,
message: "请输入账号",
min: 6,
trigger: "blur"
}
//{ validator: validaePass }
],
nickname: [{
required: true,
message: "请输入昵称",
min: 6,
trigger: "blur"
}
//{ validator: validaePass }
],
checkPass: [{
validator: validatePassword,
trigger: "blur"
}],
checkPass1: [{
validator: validatePassword,
trigger: "blur"
}],
email: [{
validator: validateEmail,
trigger: "blur"
}]
},
rules2: {
account: [{
required: true,
message: "请输入账号",
trigger: "blur"
}
//{ validator: validaePass }
],
checkPass: [{
required: true,
message: "请输入密码",
trigger: "blur"
}
//{ validator: validaePass2 }
]
},
checked: true
};
},
computed: {},
methods: {
handleReset2() {
this.$refs.ruleForm2.resetFields();
},
handleVerify() {
this.$refs.ruleForm1.validate(valid => {
if (valid) {
let url = "/verify";
ajax
.post(url, {
email_address: this.ruleForm1.email
})
.then(resp => {
Message("ok");
})
.catch(reason => {
Message("网络错误:" + reason);
});
}
});
},
handleRegister() {
this.$refs.ruleForm1.validate(valid => {
if (valid) {
let url = "/register";
ajax
.post(url, {
remember_me: this.ruleForm1.checked ? 1 : 0,
user_name: this.ruleForm1.account,
user_pwd: this.ruleForm1.checkPass,
email_address: this.ruleForm1.email,
email_code: this.ruleForm1.verify
})
.then(resp => {
Message.info("网络错误:" + resp.data.Msg);
})
.catch(reason => {
Message.error("网络错误:" + reason);
});
}
});
},
handleSubmit2() {
this.$refs.ruleForm2.validate(valid => {
if (valid) {
let url = "/login";
ajax
.post(url, {
remember_me: this.ruleForm2.checked ? 1 : 0,
user_name: this.ruleForm2.account,
user_pwd: this.ruleForm2.checkPass
})
.then(resp => {
console.log(store);
if (resp.data.Status === 0) {
let getUserUrl = "/user?";
let objUser = JSON.parse(resp.data.Data);
console.log(objUser)
getUserUrl += "token=" + objUser.SocketToken;
getUserUrl += "&userid=" + objUser.ID;
ajax.get(getUserUrl).then(resp => {
if (resp.data.Data !== undefined) {
Cookie.set(Const.KEY_USER_INFO, resp.data.Data);
store.commit("setAccount", resp.data.Data);
console.log(resp.data.Data);
this.$router.push("/BarIview");
Message.success("登錄成功");
} else {
Message("网络错误");
}
})
.catch(reason => {
Message(reason);
});
}
})
.catch(reason => {
console.log(reason);
});
}
});
}
},
created() {}
};
</script>
<style>
.login-container {
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
background-clip: padding-box;
margin: 180px auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
}
.title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
.remember {
margin: 0px 0px 35px 0px;
}
</style>

View File

@ -1,279 +0,0 @@
<style scoped>
.layout {
background:#505458;
color: white;
position: relative;
overflow: hidden;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
height: 100%;
}
.el-header {
background-color: #505458;
line-height: 60px;
}
</style>
<template>
<div class="layout">
<el-container :style="'height:' + height + 'px;'">
<el-aside width="200px" style="background-color:black;height: 100%">
<el-menu
default-active="0-1"
theme="dark"
background-color="black"
text-color="#fff"
active-text-color="#ffd04b"
v-bind:router="true"
@open="opentab"
:unique-opened="true"
>
<el-submenu :index="menu.index" v-for="(menu,index) in menus">
<template slot="title">
<i class="el-icon-menu"></i>
{{menu.name}}
</template>
<el-menu-item-group v-bind:route="index" v-bind:index="index">
<el-menu-item
v-bind:route="submenus.href"
v-bind:index="index + '-' + index2" v-for="(submenus,index2) in menu.submenu">
{{submenus.name}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="height: 56px;line-height: 60px;background-color: black; ">
<el-row style="height: 56px">
<el-col :span="4" style="height:56px">
<el-breadcrumb separator="/">
<el-breadcrumb-item
style="float:left;margin-top: 25px;color: white"
v-for="(item,index) in levelListComputed"
v-if="item.name"
>
<a :href="item.url">{{item.name}}</a>
</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
<el-col :span="20" style="text-align: right; font-size: 12px;height:56px">
<el-dropdown @command="handleClickUserDropdown">
<span class="el-dropdown-link">
管理员
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ownSpace">个人中心</el-dropdown-item>
<el-dropdown-item command="loginout" divided>退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>{{userInfo.UserName}}</span>
<i class="el-icon-user-solid"></i>
</el-col>
</el-row>
</el-header>
<el-main style="background:#303133">
<router-view ></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import Vue from 'vue';
import axios from "@/api/ajax";
import Cookie from "js-cookie";
import Const from "@/const";
import Menu from "element-ui/lib/menu";
import MenuItem from "element-ui/lib/menu-item";
import MenuGroup from "element-ui/lib/menu-item-group";
import DropDown from "element-ui/lib/dropdown";
import DropDownMenu from "element-ui/lib/dropdown-menu";
import DropDownItem from "element-ui/lib/dropdown-item";
import Container from "element-ui/lib/container";
import Aside from "element-ui/lib/aside";
import Header from "element-ui/lib/header";
import Row from "element-ui/lib/row";
import Col from "element-ui/lib/col";
import Main from "element-ui/lib/main";
import BreadThumb from "element-ui/lib/breadcrumb";
import BreadThumbItem from "element-ui/lib/breadcrumb-item";
import Submenu from "element-ui/lib/submenu";
import VueMavonEditor from "mavon-editor";
import Message from "element-ui/lib/message"
Vue.use(Message);
import "mavon-editor/dist/css/index.css";
Vue.use(VueMavonEditor);
Vue.use(Container);
Vue.use(Aside);
Vue.use(Col);
Vue.use(MenuGroup);
Vue.use(Submenu);
Vue.use(BreadThumb);
Vue.use(Main);
Vue.use(Row);
Vue.use(Menu);
Vue.use(MenuItem);
Vue.use(DropDownMenu);
Vue.use(Header);
Vue.use(DropDown);
Vue.use(BreadThumbItem);
Vue.use(DropDownItem);
export default {
components: {
Container,
Aside,
Message,
Col,
MenuGroup,
Submenu,
BreadThumb,
BreadThumbItem,
Main,
Row,
Menu,
DropDownItem,
MenuItem,
DropDownMenu,
Header,
DropDown,
},
computed: {
levelListComputed: function() {
let matched = this.$route.matched.filter(item => item.name);
return matched;
}
},
data: function() {
return {
curIndex:0,
timer: null,
items: [],
userInfo: {},
levelList: null,
current: {},
iter: 1,
width : 1024,
height : 800,
menus: [
{
name: "基础功能",
icon: "",
index: "0",
submenu: []
},
{
name: "二期功能",
icon: "",
index:"1",
submenu: []
}
]
};
},
name: "SideBarView",
mounted(){
this.height = this.findDimensions().height;
},
watch:{
fullHeight(val) {
if(!this.timer){
this.height = val
this.timer = true
let that = this
setTimeout(function () {
this.timer = false
},400)
}
}
},
created() {
this.$router.options.routes[1].children.forEach(route => {
this.menus[0].submenu.push({
name: route.name,
href: "/BarIView/" + route.path.split("/:", 2)[0]
});
});
this.$router.options.routes[2].children.forEach(route => {
this.menus[1].submenu.push({
name: route.name,
href: "/BarIView/" + route.path.split("/:", 2)[0]
});
});
if (userInfo === undefined) {
this.$router.push("/login");
} else {
this.userInfo = userInfo;
//console.log(userInfo);
}
},
methods: {
opentab(index,indexPath){
console.log(index,indexPath)
},
findDimensions() //
{
var point = {};
//
window.innerWidth && (point.width = window.innerWidth);
window.innerHeight && (point.height = window.innerHeight);
return point;
},
handleClickUserDropdown(name) {
if (name === "loginout") {
let url = "/logout";
let userInfo = Cookie.get("userInfo");
let obk = JSON.parse(userInfo);
console.log(obk['SocketToken']);
axios
.get(url+"/"+obk['SocketToken'])
.then(function(resp) {
Cookie.remove(Const.KEY_USER_INFO);
})
.catch(reason => {
Message.error(reason);
});
this.$router.push("/login");
}
},
getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name);
const first = matched[0];
this.levelList = matched;
}
}
};
</script>
<style scoped>
.el-aside {
background-color: #d3dce6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-breadcrumb__inner a {
color: white;
}
.el-breadcrumb__inner .is-link {
color: white;
}
.el-dropdown {
color: white;
}
.el-breadcrumb__item:last-child .el-breadcrumb__inner,
.el-breadcrumb__item:last-child .el-breadcrumb__inner a,
.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,
.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover {
color: white;
}
</style>

View File

@ -1,99 +0,0 @@
<template>
<div>
<br />
<div id="video"
style="width:98%;height:300px;background-color:#000000;margin:auto"></div>
<br />
<div style="text-align:center; margin:auto;">
<input id="path1"
type="text"
value="http://192.168.100.14:8080/live/hello.m3u8"
placeholder="请输入视频地址支持mp4/flv格式" />
<button onclick="$this.playVideo1">播放</button>
<br />
<input id="path2"
type="text"
value="rtmp://192.168.100.14:1935/stream"
placeholder="请输入视频地址支持rtmp直播" />
<button onclick="$this.playVideo2">直播</button>
</div>
<div id="pp"
class="button"
onclick="ppVideo()">播放</div>
</div>
</template>
<script>
export default {
data () {
return {
bstart: false,
pusher: null
}
},
created () {
document.addEventListener('plusready', this.plusReady, false);
},
methods: {
plusReady () {
//
video = new plus.video.VideoPlayer('video', {
src: 'http://192.168.100.14:8080/live/hello.m3u8'
});
video.addEventListener('play', function () {
updatePlaying(true);
}, false);
video.addEventListener('pause', function () {
updatePlaying(false);
}, false);
},
//
playVideo1 () {
var path = document.getElementById('path1').value;
if (path && path.length > 0) {
video.setOptions({ src: path });
video.play();
}
}
,playVideo2 () {
var path = document.getElementById('path2').value;
if (path && path.length > 0) {
video.setOptions({ src: path });
video.play();
}
},
//
updatePlaying (play) {
playing = play;
document.getElementById('pp').innerText = playing ? '暂停' : '播放';
},
// /
ppVideo () {
playing ? video.pause() : video.play();
}
}
}
</script>
<style scoped>
input {
width: 70%;
font-size: 16px;
padding: 0.2em 0.2em;
border: 1px solid #00b100;
-webkit-user-select: text;
}
button,
.button {
width: 20%;
margin: 6px 0 6px 6px;
font-size: 16px;
color: #fff;
background-color: #00cc00;
border: 1px solid #00b100;
padding: 0.2em 0em;
-webkit-border-radius: 5px;
border-radius: 5px;
}
</style>

View File

@ -1,61 +0,0 @@
<!--
* @Author: your name
* @Date: 2019-06-30 19:42:26
* @LastEditTime: 2021-11-29 00:38:27
* @LastEditors: your name
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \background-front\src\views\articleShow.vue
-->
<template>
<el-card class="box-card">
<div slot="header" class="clearfix" style="font-family:BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size: 20px">
<span>{{title}}</span>
<span style="float: right;width: 300px;" > 作者: 郑才育</span>
</div>
<div class="text item">
<mavon-editor :navigation=true :subfield=false style="height: 900px" v-model="content" />
</div>
</el-card>
</template>
<style scoped>
.box-card{
width: 70%;
margin-left: 15%;
}
</style>
<script>
import Cookie from 'js-cookie'
import ajax from "../api/ajax";
export default {
name: "articleShow",
data() {
return {
id : this.$route.params['id'],
title: "",
author: "",
time: "",
content: ""
}
},
methods: {
},
created(){
console.log("article",this.$route.params.id);
let url = '/article/' + this.id;
ajax.get(url).then(
resp => {
console.log(resp.data.Data);
this.title = resp.data.Data.title;
this.author = resp.data.Data.author;
this.content = resp.data.Data.content;
}
).catch(
reason => {
//this.$message.info(reason)
}
)
}
}
</script>

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