Repository: CrazyRocks/goadmin Branch: master Commit: 49f7fb610c73 Files: 196 Total size: 3.6 MB Directory structure: gitextract_q1xzow4c/ ├── .gitattributes ├── .idea/ │ ├── .gitignore │ ├── goadmin.iml │ ├── misc.xml │ └── modules.xml ├── License ├── README.en.md ├── README.md ├── boot/ │ ├── boot.go │ └── module.go ├── config/ │ └── config.toml ├── go.mod ├── go.sum ├── main.go ├── middleware/ │ └── rtoken/ │ ├── rtoken.go │ ├── rtoken_cache.go │ └── rtoken_resp.go ├── module/ │ ├── home/ │ │ ├── config/ │ │ │ └── router.go │ │ ├── controller/ │ │ │ └── dashboard_controller.go │ │ └── module.go │ ├── public/ │ │ ├── config/ │ │ │ └── router.go │ │ ├── controller/ │ │ │ └── login_controller.go │ │ ├── model/ │ │ │ └── sys_login_user_model.go │ │ └── module.go │ └── sys/ │ ├── config/ │ │ └── router.go │ ├── controller/ │ │ ├── sys_config_controller.go │ │ ├── sys_oss_controller.go │ │ └── sys_user_controller.go │ ├── model/ │ │ ├── sys_config_model.go │ │ ├── sys_oss_cloud.go │ │ ├── sys_oss_model.go │ │ └── sys_user_model.go │ └── module.go ├── public/ │ ├── modules/ │ │ ├── common.js │ │ └── sys/ │ │ ├── config.js │ │ ├── oss.js │ │ └── user.js │ ├── plugins/ │ │ ├── ajaxupload/ │ │ │ └── ajaxupload.js │ │ └── table/ │ │ ├── bootstrap-table-locale-all.js │ │ ├── bootstrap-table-vue.esm.js │ │ ├── bootstrap-table-vue.js │ │ ├── bootstrap-table.css │ │ ├── bootstrap-table.js │ │ ├── extensions/ │ │ │ ├── accent-neutralise/ │ │ │ │ └── bootstrap-table-accent-neutralise.js │ │ │ ├── addrbar/ │ │ │ │ └── bootstrap-table-addrbar.js │ │ │ ├── auto-refresh/ │ │ │ │ └── bootstrap-table-auto-refresh.js │ │ │ ├── cell-input/ │ │ │ │ ├── bootstrap-table-cell-input.css │ │ │ │ └── bootstrap-table-cell-input.js │ │ │ ├── cookie/ │ │ │ │ └── bootstrap-table-cookie.js │ │ │ ├── copy-rows/ │ │ │ │ └── bootstrap-table-copy-rows.js │ │ │ ├── defer-url/ │ │ │ │ └── bootstrap-table-defer-url.js │ │ │ ├── editable/ │ │ │ │ └── bootstrap-table-editable.js │ │ │ ├── export/ │ │ │ │ └── bootstrap-table-export.js │ │ │ ├── filter-control/ │ │ │ │ ├── bootstrap-table-filter-control.css │ │ │ │ └── bootstrap-table-filter-control.js │ │ │ ├── fixed-columns/ │ │ │ │ ├── bootstrap-table-fixed-columns.css │ │ │ │ └── bootstrap-table-fixed-columns.js │ │ │ ├── group-by-v2/ │ │ │ │ ├── bootstrap-table-group-by.css │ │ │ │ └── bootstrap-table-group-by.js │ │ │ ├── i18n-enhance/ │ │ │ │ └── bootstrap-table-i18n-enhance.js │ │ │ ├── key-events/ │ │ │ │ └── bootstrap-table-key-events.js │ │ │ ├── mobile/ │ │ │ │ └── bootstrap-table-mobile.js │ │ │ ├── multiple-sort/ │ │ │ │ └── bootstrap-table-multiple-sort.js │ │ │ ├── natural-sorting/ │ │ │ │ └── bootstrap-table-natural-sorting.js │ │ │ ├── page-jump-to/ │ │ │ │ ├── bootstrap-table-page-jump-to.css │ │ │ │ └── bootstrap-table-page-jump-to.js │ │ │ ├── pipeline/ │ │ │ │ └── bootstrap-table-pipeline.js │ │ │ ├── print/ │ │ │ │ └── bootstrap-table-print.js │ │ │ ├── reorder-columns/ │ │ │ │ └── bootstrap-table-reorder-columns.js │ │ │ ├── reorder-rows/ │ │ │ │ ├── bootstrap-table-reorder-rows.css │ │ │ │ └── bootstrap-table-reorder-rows.js │ │ │ ├── resizable/ │ │ │ │ └── bootstrap-table-resizable.js │ │ │ ├── sticky-header/ │ │ │ │ ├── bootstrap-table-sticky-header.css │ │ │ │ └── bootstrap-table-sticky-header.js │ │ │ ├── toolbar/ │ │ │ │ └── bootstrap-table-toolbar.js │ │ │ └── treegrid/ │ │ │ └── bootstrap-table-treegrid.js │ │ ├── locale/ │ │ │ ├── bootstrap-table-af-ZA.js │ │ │ ├── bootstrap-table-ar-SA.js │ │ │ ├── bootstrap-table-ca-ES.js │ │ │ ├── bootstrap-table-cs-CZ.js │ │ │ ├── bootstrap-table-da-DK.js │ │ │ ├── bootstrap-table-de-DE.js │ │ │ ├── bootstrap-table-el-GR.js │ │ │ ├── bootstrap-table-en-US.js │ │ │ ├── bootstrap-table-es-AR.js │ │ │ ├── bootstrap-table-es-CL.js │ │ │ ├── bootstrap-table-es-CR.js │ │ │ ├── bootstrap-table-es-ES.js │ │ │ ├── bootstrap-table-es-MX.js │ │ │ ├── bootstrap-table-es-NI.js │ │ │ ├── bootstrap-table-es-SP.js │ │ │ ├── bootstrap-table-et-EE.js │ │ │ ├── bootstrap-table-eu-EU.js │ │ │ ├── bootstrap-table-fa-IR.js │ │ │ ├── bootstrap-table-fi-FI.js │ │ │ ├── bootstrap-table-fr-BE.js │ │ │ ├── bootstrap-table-fr-CH.js │ │ │ ├── bootstrap-table-fr-FR.js │ │ │ ├── bootstrap-table-fr-LU.js │ │ │ ├── bootstrap-table-he-IL.js │ │ │ ├── bootstrap-table-hr-HR.js │ │ │ ├── bootstrap-table-hu-HU.js │ │ │ ├── bootstrap-table-id-ID.js │ │ │ ├── bootstrap-table-it-IT.js │ │ │ ├── bootstrap-table-ja-JP.js │ │ │ ├── bootstrap-table-ka-GE.js │ │ │ ├── bootstrap-table-ko-KR.js │ │ │ ├── bootstrap-table-ms-MY.js │ │ │ ├── bootstrap-table-nb-NO.js │ │ │ ├── bootstrap-table-nl-BE.js │ │ │ ├── bootstrap-table-nl-NL.js │ │ │ ├── bootstrap-table-pl-PL.js │ │ │ ├── bootstrap-table-pt-BR.js │ │ │ ├── bootstrap-table-pt-PT.js │ │ │ ├── bootstrap-table-ro-RO.js │ │ │ ├── bootstrap-table-ru-RU.js │ │ │ ├── bootstrap-table-sk-SK.js │ │ │ ├── bootstrap-table-sr-Cyrl-RS.js │ │ │ ├── bootstrap-table-sr-Latn-RS.js │ │ │ ├── bootstrap-table-sv-SE.js │ │ │ ├── bootstrap-table-th-TH.js │ │ │ ├── bootstrap-table-tr-TR.js │ │ │ ├── bootstrap-table-uk-UA.js │ │ │ ├── bootstrap-table-ur-PK.js │ │ │ ├── bootstrap-table-uz-Latn-UZ.js │ │ │ ├── bootstrap-table-vi-VN.js │ │ │ ├── bootstrap-table-zh-CN.js │ │ │ └── bootstrap-table-zh-TW.js │ │ └── themes/ │ │ ├── bulma/ │ │ │ ├── bootstrap-table-bulma.css │ │ │ └── bootstrap-table-bulma.js │ │ ├── foundation/ │ │ │ ├── bootstrap-table-foundation.css │ │ │ └── bootstrap-table-foundation.js │ │ ├── materialize/ │ │ │ ├── bootstrap-table-materialize.css │ │ │ └── bootstrap-table-materialize.js │ │ └── semantic/ │ │ ├── bootstrap-table-semantic.css │ │ └── bootstrap-table-semantic.js │ └── stisla/ │ ├── css/ │ │ ├── components.css │ │ ├── custom.css │ │ ├── reverse.css │ │ ├── rtl.css │ │ ├── skins/ │ │ │ └── reverse.css │ │ └── style.css │ ├── fonts/ │ │ └── vazir/ │ │ ├── LICENSE │ │ └── font-face.css │ └── js/ │ ├── custom.js │ ├── page/ │ │ ├── auth-register.js │ │ ├── bootstrap-modal.js │ │ ├── components-chat-box.js │ │ ├── components-multiple-upload.js │ │ ├── components-statistic.js │ │ ├── components-table.js │ │ ├── components-user.js │ │ ├── features-post-create.js │ │ ├── features-posts.js │ │ ├── features-setting-detail.js │ │ ├── forms-advanced-forms.js │ │ ├── gmaps-advanced-route.js │ │ ├── gmaps-draggable-marker.js │ │ ├── gmaps-geocoding.js │ │ ├── gmaps-geolocation.js │ │ ├── gmaps-marker.js │ │ ├── gmaps-multiple-marker.js │ │ ├── gmaps-route.js │ │ ├── gmaps-simple.js │ │ ├── index-0.js │ │ ├── index.js │ │ ├── modules-calendar.js │ │ ├── modules-chartjs.js │ │ ├── modules-datatables.js │ │ ├── modules-ion-icons.js │ │ ├── modules-slider.js │ │ ├── modules-sparkline.js │ │ ├── modules-sweetalert.js │ │ ├── modules-toastr.js │ │ ├── modules-vector-map.js │ │ └── utilities-contact.js │ ├── scripts.js │ └── stisla.js ├── sql/ │ └── goadmin.sql ├── template/ │ ├── home/ │ │ └── index.html │ ├── layout/ │ │ ├── footer.html │ │ ├── header.html │ │ └── nav.html │ ├── public/ │ │ └── login.html │ └── sys/ │ ├── config.html │ ├── oss.html │ └── user.html └── utils/ ├── base/ │ ├── baseForm.go │ ├── baseModel.go │ └── baseRouter.go ├── bean/ │ └── SessionUser.go ├── cloud/ │ └── oss.go ├── resp/ │ └── resp.go ├── time.go └── tools/ ├── gid.go └── redis.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.js linguist-language=GO *.css linguist-language=GO *.html linguist-language=GO ================================================ FILE: .idea/.gitignore ================================================ # Default ignored files /workspace.xml ================================================ FILE: .idea/goadmin.iml ================================================ ================================================ FILE: .idea/misc.xml ================================================ ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: License ================================================ MIT License Copyright (c) 2020 CrazyRocks Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.en.md ================================================ ================================================ FILE: README.md ================================================ # GoAdim 底层框架:GF
前端模板:stisla
数据库:mysql
缓存:redis
权限:token
安装:
1:数据库在:sql文件夹下
2:修改config文件下的config
3:请打开redis
4: go run main.go
5:账号:admin 密码:admin#1314
打包等细节:查看gf手册
配套工具 全自动生成脚手架:https://github.com/CrazyRocks/autocreate
1: 生成了model
2: 生成了controller
3: 生成了router
4: 生成了moudle
5: 生成了html模式下的模板(html,js)
6: 生成了vue模式下的vue
7: 自动生成了权限menu.sql
原来需要写一天,现在只需1分钟搞定
![输入图片说明](https://images.gitee.com/uploads/images/2019/1225/172725_0759aafc_1927330.jpeg "3.jpg")
项目说明: 1: 底层使用超级爽的:gf框架(爽到爆)
2: 该系统是一个golang admin(就是为了快)
3: 系统采用了token验证,所以全端一键生成API
5: 碾压的超级美观界面
![输入图片说明](https://images.gitee.com/uploads/images/2019/1225/172744_38454fdb_1927330.jpeg "5.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2019/1225/172758_27d955f0_1927330.jpeg "6.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2019/1225/172818_dd46545a_1927330.jpeg "7.jpg")
**关注我,带你们技术搞流量,技术搞流量,轻松百万流量**
1:独家分享独立开发者1000万用户的操作
2:独家分享日活20万用户的全套代码
3:独家分享如果用技术短时间获取百万用户
开源:
1:全套视频APP,上线3个月日活5万+ [https://gitee.com/rocks/zhanglubao](https://gitee.com/rocks/zhanglubao)
2: 全自动全栈代码生成器:[https://gitee.com/crazyrocks/goadmin](https://gitee.com/crazyrocks/goadmin)
3: 即将分享1个月打造日活10万+微信小程序
4: 关于安卓市场,快速上榜工具
**全是野路子**
![输入图片说明](https://images.gitee.com/uploads/images/2020/0109/151918_f6733481_620187.jpeg "qrcode_for_gh_221095e67f12_1280.jpg")
关于百度:
1:如何做到1个月百度流量破万
2:如何做到1个月小程序日活20万
![输入图片说明](https://images.gitee.com/uploads/images/2020/0109/155739_ee8bdd72_1927330.png "1.png")
关于Google,直接上图
![输入图片说明](https://images.gitee.com/uploads/images/2020/0109/155759_10726b97_1927330.png "3.png")

感谢大佬
| Name | Channel | Amount | Comment
|---|---|--- | ---
|李超|wechat|¥66.00 |
================================================ FILE: boot/boot.go ================================================ package boot import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/os/gsession" "goadmin/middleware/rtoken" "goadmin/module/public/controller" "goadmin/utils/base" "time" ) func init() { InitConfig() InitModules() // 启动rtoken base.Token = &rtoken.RfToken{ Timeout: 100 * 1000, CacheMode: 2, LoginPath: "/login/submit", LoginBeforeFunc: controller.LoginSubmit, LoginAfterFunc: controller.LoginAfter, LogoutPath: "/user/logout", LogoutBeforeFunc: controller.LogoutBefore, AuthPaths: g.SliceStr{"/dashboard", "/sys/*"}, } base.Token.Start() } // 用于应用初始化。 func InitConfig() { c := g.Config() s := g.Server() v := g.View() //session存内存 _ = s.SetConfigWithMap(g.Map{ "SessionMaxAge": time.Minute, "SessionStorage": gsession.NewStorageMemory(), }) // 配置对象及视图对象配置 _ = c.AddPath("config") v.SetDelimiters("${", "}") _ = v.AddPath("template") s.SetServerRoot("public") // glog配置 logpath := c.GetString("setting.logpath") _ = glog.SetPath(logpath) glog.SetStdoutPrint(true) s.SetLogPath(logpath) s.SetErrorLogEnabled(true) s.SetAccessLogEnabled(false) s.EnableAdmin() s.SetPort(8192) } ================================================ FILE: boot/module.go ================================================ package boot import ( "goadmin/module/home" "goadmin/module/public" "goadmin/module/sys" ) func InitModules() { public.InitModule() home.InitModule() sys.InitModule() } ================================================ FILE: config/config.toml ================================================ url-path = "" # 应用系统设置 [setting] logpath = "/logs" assest="" domain="" # 数据库连接 [database] [[database.center]] host = "localhost" port = "3306" user = "root" pass = "" name = "goadmin" type = "mysql" role = "master" charset = "utf8" priority = "1" debug = "false" # 缓存模式 1 gcache 2 gredis cache-mode = 2 # Redis数据库配置 [redis] default = "127.0.0.1:6379,0" cache = "127.0.0.1:6379,1?idleTimeout=600" ================================================ FILE: go.mod ================================================ module goadmin require github.com/gogf/gf v1.10.0 require ( github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect github.com/kr/pretty v0.1.0 // indirect github.com/satori/go.uuid v1.2.0 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect google.golang.org/appengine v1.6.5 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) go 1.13 ================================================ FILE: go.sum ================================================ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible h1:EaK5256H3ELiyaq5O/Zwd6fnghD6DqmZDQmmzzJklUU= github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gf-third/mysql v1.4.2 h1:f1M5CNFUG3WkE07UOomtu4o0n/KJKeuUUf5Nc9ZFXs4= github.com/gf-third/mysql v1.4.2/go.mod h1:+dd90V663ppI2fV5uQ6+rHk0u8KCyU6FkG8Um8Cx3ms= github.com/gf-third/yaml v1.0.1 h1:pqD4ix+65DqGphU1MDnToPZfGYk0tuuwRzuTSl3g0d0= github.com/gf-third/yaml v1.0.1/go.mod h1:t443vj0txEw3+E0MOtkr83kt+PrZg2I8SRuYfn85NM0= github.com/gogf/gf v1.10.0 h1:O6QwrdlQ06Nq/mp3EMwGckPA6xnWg2L+k5u+mYCiges= github.com/gogf/gf v1.10.0/go.mod h1:/37gncPmuM06D4YSqiDze9GsasDtF2QnWkUfKeiGW/Q= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA= github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e h1:9vRrk9YW2BTzLP0VCB9ZDjU4cPqkg+IDWL7XgxA1yxQ= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= ================================================ FILE: main.go ================================================ package main import ( "github.com/gogf/gf/frame/g" _ "goadmin/boot" ) func main() { g.Server().Run() } ================================================ FILE: middleware/rtoken/rtoken.go ================================================ package rtoken import ( "fmt" "github.com/gogf/gf/crypto/gaes" "github.com/gogf/gf/crypto/gmd5" "github.com/gogf/gf/encoding/gbase64" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/util/grand" "strings" ) const ( CacheModeCache = 1 CacheModeRedis = 2 ) // RfToken rtoken结构体 type RfToken struct { // 缓存模式 1 gcache 2 gredis 默认1 CacheMode int8 // 缓存key CacheKey string // 超时时间 默认10天 Timeout int // 缓存刷新时间 默认为超时时间的一半 MaxRefresh int // Token分隔符 TokenDelimiter string // Token加密key EncryptKey []byte // 认证失败中文提示 AuthFailMsg string // 登录路径 LoginPath string // 登录验证方法 return userKey 用户标识 如果userKey为空,结束执行 LoginBeforeFunc func(r *ghttp.Request) (string, interface{}) // 登录返回方法 LoginAfterFunc func(r *ghttp.Request, respData Resp) // 登出地址 LogoutPath string // 登出验证方法 return true 继续执行,否则结束执行 LogoutBeforeFunc func(r *ghttp.Request) bool // 登出返回方法 LogoutAfterFunc func(r *ghttp.Request, respData Resp) // 拦截地址 AuthPaths g.SliceStr // 认证验证方法 return true 继续执行,否则结束执行 AuthBeforeFunc func(r *ghttp.Request) bool // 认证返回方法 AuthAfterFunc func(r *ghttp.Request, respData Resp) } // Init 初始化 func (m *RfToken) Init() bool { if m.CacheMode == 0 { m.CacheMode = CacheModeCache } if m.CacheKey == "" { m.CacheKey = "RToken:" } if m.Timeout == 0 { m.Timeout = 10 * 24 * 60 * 60 * 1000 } if m.MaxRefresh == 0 { m.MaxRefresh = m.Timeout / 2 } if m.TokenDelimiter == "" { m.TokenDelimiter = "_" } if len(m.EncryptKey) == 0 { m.EncryptKey = []byte("12345678912345678912345678912345") } if m.AuthFailMsg == "" { m.AuthFailMsg = "请求错误或登录超时" } if m.LoginAfterFunc == nil { m.LoginAfterFunc = func(r *ghttp.Request, respData Resp) { if !respData.Success() { r.Response.WriteJson(respData) } else { r.Response.WriteJson(Succ(g.Map{ "token": respData.GetString("token"), })) } } } if m.LogoutBeforeFunc == nil { m.LogoutBeforeFunc = func(r *ghttp.Request) bool { return true } } if m.LogoutAfterFunc == nil { m.LogoutAfterFunc = func(r *ghttp.Request, respData Resp) { if respData.Success() { r.Response.WriteJson(Succ("Logout success")) } else { r.Response.WriteJson(respData) } } } if m.AuthBeforeFunc == nil { m.AuthBeforeFunc = func(r *ghttp.Request) bool { // 静态页面不拦截 if r.IsFileRequest() { return false } return true } } if m.AuthAfterFunc == nil { m.AuthAfterFunc = func(r *ghttp.Request, respData Resp) { if respData.Success() { r.Middleware.Next() } else { var params map[string]interface{} if r.Method == "GET" { params = r.GetQueryMap() } else if r.Method == "POST" { params = r.GetPostMap() } else { r.Response.Writeln("Request Method is ERROR! ") return } no := gconv.String(gtime.Millisecond()) glog.Info(fmt.Sprintf("[AUTH_%s][url:%s][params:%s][data:%s]", no, r.URL.Path, params, respData.Json())) respData.Msg = m.AuthFailMsg r.Response.WriteJson(respData) r.ExitAll() } } } return true } // Start 启动 func (m *RfToken) Start() bool { if !m.Init() { return false } glog.Info("[RToken][params:" + m.String() + "]start... ") s := g.Server() // 缓存模式 if m.CacheMode > CacheModeRedis { glog.Error("[RToken]CacheMode set error") return false } // 认证拦截器 if m.AuthPaths == nil { glog.Error("[RToken]HookPathList not set") return false } for _, authPath := range m.AuthPaths { if strings.HasSuffix(authPath, "/*") { s.BindMiddleware(authPath, m.AuthMiddleware) } else { s.BindMiddleware(authPath+"/*", m.AuthMiddleware) } } // 登录 if m.LoginPath == "" || m.LoginBeforeFunc == nil { glog.Error("[RToken]LoginPath or LoginBeforeFunc not set") return false } s.BindHandler(m.LoginPath, m.Login) // 登出 if m.LogoutPath == "" { glog.Error("[RToken]LogoutPath or LogoutFunc not set") return false } s.BindHandler(m.LogoutPath, m.Logout) return true } // Start 结束 func (m *RfToken) Stop() bool { glog.Info("[RToken]stop. ") return true } // GetTokenData 通过token获取对象 func (m *RfToken) GetTokenData(r *ghttp.Request) Resp { respData := m.getRequestToken(r) if respData.Success() { // 验证token respData = m.validToken(respData.DataString()) } return respData } // Login 登录 func (m *RfToken) Login(r *ghttp.Request) { userKey, data := m.LoginBeforeFunc(r) if userKey != "" { // 生成token respToken := m.genToken(userKey, data) m.LoginAfterFunc(r, respToken) } } // Logout 登出 func (m *RfToken) Logout(r *ghttp.Request) { if m.LogoutBeforeFunc(r) { // 获取请求token respData := m.getRequestToken(r) if respData.Success() { // 删除token m.removeToken(respData.DataString()) } m.LogoutAfterFunc(r, respData) } } // AuthMiddleware 认证拦截 func (m *RfToken) AuthMiddleware(r *ghttp.Request) { // 不需要认证,直接下一步 if !m.AuthBeforeFunc(r) { r.Middleware.Next() return } // 获取请求token tokenResp := m.getRequestToken(r) if tokenResp.Success() { // 验证token tokenResp = m.validToken(tokenResp.DataString()) } m.AuthAfterFunc(r, tokenResp) } // getRequestToken 返回请求Token func (m *RfToken) getRequestToken(r *ghttp.Request) Resp { authHeader := r.Header.Get("Authorization") if authHeader != "" { parts := strings.SplitN(authHeader, " ", 2) if !(len(parts) == 2 && parts[0] == "Bearer") { glog.Warning("[RToken]authHeader:" + authHeader + " get token key fail") return Unauthorized("get token key fail", "") } else if parts[1] == "" { glog.Warning("[RToken]authHeader:" + authHeader + " get token fail") return Unauthorized("get token fail", "") } return Succ(parts[1]) } token := r.Cookie.Get("token", "") if token != "" { return Succ(token) } authHeader = r.GetPostString("token") if authHeader == "" { return Unauthorized("query token fail", "") } return Succ(authHeader) } // genToken 生成Token func (m *RfToken) genToken(userKey string, data interface{}) Resp { token := m.EncryptToken(userKey) if !token.Success() { return token } cacheKey := m.CacheKey + userKey userCache := g.Map{ "userKey": userKey, "uuid": token.GetString("uuid"), "data": data, "createTime": gtime.Now().Millisecond(), "refreshTime": gtime.Now().Millisecond() + gconv.Int64(m.MaxRefresh), } cacheResp := m.setCache(cacheKey, userCache) if !cacheResp.Success() { return cacheResp } return token } // validToken 验证Token func (m *RfToken) validToken(token string) Resp { if token == "" { return Unauthorized("valid token empty", "") } decryptToken := m.DecryptToken(token) if !decryptToken.Success() { return decryptToken } userKey := decryptToken.GetString("userKey") uuid := decryptToken.GetString("uuid") cacheKey := m.CacheKey + userKey userCacheResp := m.getCache(cacheKey) if !userCacheResp.Success() { return userCacheResp } userCache := gconv.Map(userCacheResp.Data) if uuid != userCache["uuid"] { glog.Error("[RToken]user auth error, decryptToken:" + decryptToken.Json() + " cacheValue:" + gconv.String(userCache)) return Unauthorized("user auth error", "") } nowTime := gtime.Now().Millisecond() refreshTime := userCache["refreshTime"] // 需要进行缓存超时时间刷新 if gconv.Int64(refreshTime) == 0 || nowTime > gconv.Int64(refreshTime) { userCache["createTime"] = gtime.Now().Millisecond() userCache["refreshTime"] = gtime.Now().Millisecond() + gconv.Int64(m.MaxRefresh) glog.Debug("[RToken]refreshToken:" + gconv.String(userCache)) return m.setCache(cacheKey, userCache) } return Succ(userCache) } // removeToken 删除Token func (m *RfToken) removeToken(token string) Resp { decryptToken := m.DecryptToken(token) if !decryptToken.Success() { return decryptToken } cacheKey := m.CacheKey + decryptToken.GetString("userKey") return m.removeCache(cacheKey) } // EncryptToken token加密方法 func (m *RfToken) EncryptToken(userKey string) Resp { if userKey == "" { return Fail("encrypt userKey empty") } uuid, err := gmd5.Encrypt(grand.Str(10)) if err != nil { glog.Error("[RToken]uuid error", err) return Error("uuid error") } tokenStr := userKey + m.TokenDelimiter + uuid token, err := gaes.Encrypt([]byte(tokenStr), m.EncryptKey) if err != nil { glog.Error("[RToken]encrypt error", err) return Error("encrypt error") } return Succ(g.Map{ "userKey": userKey, "uuid": uuid, "token": gbase64.Encode(token), }) } // DecryptToken token解密方法 func (m *RfToken) DecryptToken(token string) Resp { if token == "" { return Fail("decrypt token empty") } token64, err := gbase64.Decode([]byte(token)) if err != nil { glog.Error("[RToken]decode error", err) return Error("decode error") } decryptToken, err2 := gaes.Decrypt([]byte(token64), m.EncryptKey) if err2 != nil { glog.Error("[RToken]decrypt error", err2) return Error("decrypt error") } tokenArray := gstr.Split(string(decryptToken), m.TokenDelimiter) if len(tokenArray) < 2 { glog.Error("[RToken]token len error") return Error("token len error") } return Succ(g.Map{ "userKey": tokenArray[0], "uuid": tokenArray[1], }) } // String token解密方法 func (m *RfToken) String() string { return gconv.String(g.Map{ // 缓存模式 1 gcache 2 gredis 默认1 "CacheMode": m.CacheMode, "CacheKey": m.CacheKey, "Timeout": m.Timeout, "TokenDelimiter": m.TokenDelimiter, "EncryptKey": string(m.EncryptKey), "LoginPath": m.LoginPath, "LogoutPath": m.LogoutPath, "AuthPaths": gconv.String(m.AuthPaths), }) } ================================================ FILE: middleware/rtoken/rtoken_cache.go ================================================ package rtoken import ( "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/gcache" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "time" ) // setCache 设置缓存 func (m *RfToken) setCache(cacheKey string, userCache g.Map) Resp { switch m.CacheMode { case CacheModeCache: gcache.Set(cacheKey, userCache, gconv.Duration(m.Timeout)*time.Millisecond) case CacheModeRedis: cacheValueJson, err1 := gjson.Encode(userCache) if err1 != nil { glog.Error("[GToken]cache json encode error", err1) return Error("cache json encode error") } _, err := g.Redis().Do("SETEX", cacheKey, m.Timeout, cacheValueJson) if err != nil { glog.Error("[GToken]cache set error", err) return Error("cache set error") } default: return Error("cache model error") } return Succ(userCache) } // getCache 获取缓存 func (m *RfToken) getCache(cacheKey string) Resp { var userCache g.Map switch m.CacheMode { case CacheModeCache: userCacheValue := gcache.Get(cacheKey) if userCacheValue == nil { return Unauthorized("login timeout or not login", "") } userCache = gconv.Map(userCacheValue) case CacheModeRedis: userCacheJson, err := g.Redis().Do("GET", cacheKey) if err != nil { glog.Error("[GToken]cache get error", err) return Error("cache get error") } if userCacheJson == nil { return Unauthorized("login timeout or not login", "") } err = gjson.DecodeTo(userCacheJson, &userCache) if err != nil { glog.Error("[GToken]cache get json error", err) return Error("cache get json error") } default: return Error("cache model error") } return Succ(userCache) } // removeCache 删除缓存 func (m *RfToken) removeCache(cacheKey string) Resp { switch m.CacheMode { case CacheModeCache: gcache.Remove(cacheKey) case CacheModeRedis: var err error _, err = g.Redis().Do("DEL", cacheKey) if err != nil { glog.Error("[GToken]cache remove error", err) return Error("cache remove error") } default: return Error("cache model error") } return Succ("") } ================================================ FILE: middleware/rtoken/rtoken_resp.go ================================================ package rtoken import ( "encoding/json" "github.com/gogf/gf/util/gconv" ) const ( SUCCESS = 0 FAIL = -1 ERROR = -99 UNAUTHORIZED = -401 //配置 TypeConfig = 1 // 字典 TypeDict = 2 ) type Resp struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } // 获取Data值转字符串 func (resp Resp) Success() bool { return resp.Code == SUCCESS } // 获取Data转字符串 func (resp Resp) DataString() string { return gconv.String(resp.Data) } // 获取Data转Int func (resp Resp) DataInt() int { return gconv.Int(resp.Data) } // 获取Data值转字符串 func (resp Resp) GetString(key string) string { return gconv.String(resp.Get(key)) } // 获取Data值转Int func (resp Resp) GetInt(key string) int { return gconv.Int(resp.Get(key)) } // 获取Data值 func (resp Resp) Get(key string) interface{} { m := gconv.Map(resp.Data) if m == nil { return "" } return m[key] } func (resp Resp) Json() string { str, _ := json.Marshal(resp) return string(str) } // 成功 func Succ(data interface{}) Resp { return Resp{SUCCESS, "success", data} } // 失败 func Fail(msg string) Resp { return Resp{FAIL, msg, ""} } // 失败设置Data func FailData(msg string, data interface{}) Resp { return Resp{FAIL, msg, data} } // 错误 func Error(msg string) Resp { return Resp{ERROR, msg, ""} } // 错误设置Data func ErrorData(msg string, data interface{}) Resp { return Resp{ERROR, msg, data} } // 认证失败 func Unauthorized(msg string, data interface{}) Resp { return Resp{UNAUTHORIZED, msg, data} } ================================================ FILE: module/home/config/router.go ================================================ package config import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "goadmin/module/home/controller" ) func InitRouter() { urlPath := g.Config().GetString("url-path") s := g.Server() s.Group(urlPath+"/dashboard", func(g *ghttp.RouterGroup) { // 首页展示 dashboardController := new(controller.DashboardController) g.ALL("dashboard", dashboardController) g.GET("/", dashboardController.Index) }) } ================================================ FILE: module/home/controller/dashboard_controller.go ================================================ package controller import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "goadmin/utils/base" ) type DashboardController struct { base.BaseRouter } func (controller *DashboardController) Index(r *ghttp.Request) { base.WriteTpl(r, "home/index.html", g.Map{}) } ================================================ FILE: module/home/module.go ================================================ package home import "goadmin/module/home/config" func InitModule() { config.InitRouter() } ================================================ FILE: module/public/config/router.go ================================================ package config import ( "github.com/gogf/gf/frame/g" "goadmin/module/public/controller" ) func InitRouter() { urlPath := g.Config().GetString("url-path") s := g.Server() // 首页 s.BindHandler(urlPath+"/", controller.Login) } ================================================ FILE: module/public/controller/login_controller.go ================================================ package controller import ( "github.com/gogf/gf/crypto/gmd5" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/glog" "goadmin/middleware/rtoken" "goadmin/module/public/model" "goadmin/utils/base" "goadmin/utils/bean" ) // Login 登录页面 func Login(r *ghttp.Request) { err := r.Response.WriteTpl("public/login.html", g.Map{}) if err != nil { glog.Error(err) } } // LoginSubmit 登录认证 func LoginSubmit(r *ghttp.Request) (string, interface{}) { mobile := r.GetString("mobile") password := r.GetString("password") if mobile == "" || password == "" { base.Fail(r, "手机号或者密码错误") } sysLoginUser := model.SysLoginUser{Mobile: mobile}.GetUserByMobile() if sysLoginUser.Id <= 0 { base.Fail(r, "手机号或者密码错误:"+mobile) } if sysLoginUser.Status <= 0 { base.Fail(r, "账号状态异常,请联系管理员") } reqPassword, err := gmd5.Encrypt(password + sysLoginUser.Salt) if err != nil { glog.Error("login password encrypt error", err) base.Error(r, "login password encrypt error") } if reqPassword != sysLoginUser.Password { base.Fail(r, "用户名或者密码错误:"+mobile) } sessionUser := bean.SessionUser{ Id: sysLoginUser.Id, Username: sysLoginUser.Username, Mobile: sysLoginUser.Mobile, } return mobile, sessionUser } func LoginAfter(r *ghttp.Request, respData rtoken.Resp) { r.Cookie.Set("token", respData.GetString("token")) if !respData.Success() { r.Response.WriteJson(respData) } else { r.Response.WriteJson(rtoken.Succ(g.Map{ "token": respData.GetString("token"), })) } } // 登出 func LogoutBefore(r *ghttp.Request) bool { mobile := base.GetUser(r).Mobile sysLoginUser := model.SysLoginUser{Mobile: mobile}.GetUserByMobile() if sysLoginUser.Mobile != mobile { // 登出用户不存在 glog.Warning("logout mobile error", mobile) return false } r.Cookie.Remove("token") return true } ================================================ FILE: module/public/model/sys_login_user_model.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_user_model * @Version: 1.0.0 * @Date: 2019-11-04 */ package model import ( "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" ) import ( "github.com/gogf/gf/os/gtime" ) type SysLoginUser struct { Id int `orm:"id,primary" json:"Id" gconv:"Id,omitempty"` Username string `orm:"username,unique" json:"Username" gconv:"Username,omitempty"` Password string `orm:"password" json:"Password" gconv:"Password,omitempty"` Salt string `orm:"salt" json:"Salt" gconv:"Salt,omitempty"` Mobile string `orm:"mobile" json:"Mobile" gconv:"Mobile,omitempty"` CreateTime *gtime.Time `orm:"create_time" json:"CreateTime" gconv:"CreateTime,omitempty"` UpdateTime *gtime.Time `orm:"update_time" json:"UpdateTime" gconv:"UpdateTime,omitempty"` Status int `orm:"status" json:"Status" gconv:"Status,omitempty"` } //根据手机号查询系统用户 func (model SysLoginUser) GetUserByMobile() SysLoginUser { var resData SysLoginUser err := model.dbModel("t").Where("mobile = ?", model.Mobile).Fields(model.columns()).Struct(&resData) if err != nil { glog.Error(model.TableName()+" get one error", err) return SysLoginUser{} } return resData } //返回数据库SysUser func (model SysLoginUser) dbModel(alias ...string) *gdb.Model { var tmpAlias string if len(alias) > 0 { tmpAlias = " " + alias[0] } tableModel := g.DB("center").Table(model.TableName() + tmpAlias).Safe() return tableModel } //返回主键SysUser func (model SysLoginUser) PkVal() int { return model.Id } //表名SysUser func (model SysLoginUser) TableName() string { return "sys_user" } //列名SysUser func (model SysLoginUser) columns() string { sqlColumns := "t.id as Id,t.username as Username,t.password as Password,t.salt as Salt,t.mobile as Mobile,t.create_time as CreateTime,t.update_time as UpdateTime,t.status as Status" return sqlColumns } ================================================ FILE: module/public/module.go ================================================ package public import "goadmin/module/public/config" func InitModule() { config.InitRouter() } ================================================ FILE: module/sys/config/router.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: router * @Version: 1.0.0 * @Date: 2019-11-17 */ package config import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "goadmin/module/sys/controller" ) func InitRouter() { urlPath := g.Config().GetString("url-path") s := g.Server() s.Group(urlPath+"/sys", func(g *ghttp.RouterGroup) { sysConfigController := new(controller.SysConfigController) g.ALL("/config", sysConfigController) g.POST("/config/page", sysConfigController.Page) g.GET("/config/get/{id}", sysConfigController.Get) g.POST("/config/save", sysConfigController.Save) g.POST("/config/update", sysConfigController.Update) g.POST("/config/delete", sysConfigController.Delete) sysOssController := new(controller.SysOssController) g.ALL("/oss", sysOssController) g.POST("/oss/page", sysOssController.Page) g.GET("/oss/get/{id}", sysOssController.Get) g.POST("/oss/save", sysOssController.Save) g.POST("/oss/update", sysOssController.Update) g.POST("/oss/delete", sysOssController.Delete) g.GET("/oss/config/get", sysOssController.GetConfig) g.POST("/oss/config/save", sysOssController.SaveConfig) g.GET("/oss/upload", sysOssController.Upload) sysUserController := new(controller.SysUserController) g.ALL("/user", sysUserController) g.POST("/user/page", sysUserController.Page) g.GET("/user/get/{id}", sysUserController.Get) g.POST("/user/save", sysUserController.Save) g.POST("/user/update", sysUserController.Update) g.POST("/user/delete", sysUserController.Delete) }) } ================================================ FILE: module/sys/controller/sys_config_controller.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_config_controller * @Version: 1.0.0 * @Date: 2019-11-17 */ package controller import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/module/sys/model" "goadmin/utils/base" ) type SysConfigController struct { base.BaseRouter } var ( controllerNameSysConfig = "SysConfigController" ) //SysConfig页面信息 func (controller *SysConfigController) Index(r *ghttp.Request) { base.WriteTpl(r, "sys/config.html", g.Map{}) } //获取SysConfig单条信息 func (controller *SysConfigController) Get(r *ghttp.Request) { id := r.GetInt("id") model := model.SysConfig{Id: id}.Get() if model.Id <= 0 { base.Fail(r, controllerNameSysConfig+" get fail") } base.Succ(r, model) } //根据id或者ids删除{.TplModelName} func (controller *SysConfigController) Delete(r *ghttp.Request) { ids := r.GetInts("ids") for _, id := range ids { model := model.SysConfig{Id: id} model.Delete() } base.Succ(r, "") } //创建一条{.TplModelName} func (controller *SysConfigController) Save(r *ghttp.Request) { model := model.SysConfig{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysConfig+" save struct error", err) base.Error(r, "save error") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysConfig+" save fail") } base.Succ(r, "") } //更新一条{.TplModelName} func (controller *SysConfigController) Update(r *ghttp.Request) { model := model.SysConfig{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysConfig+" save struct error", err) base.Error(r, "save error") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysConfig+" save fail") } base.Succ(r, "") } //分页列表{.TplModelName} func (controller *SysConfigController) Page(r *ghttp.Request) { form := base.NewForm(r.GetQueryMap()) model := model.SysConfig{} page := model.Page(&form) base.Succ(r, g.Map{"list": page, "form": form}) } ================================================ FILE: module/sys/controller/sys_oss_controller.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_oss_controller * @Version: 1.0.0 * @Date: 2019-11-17 */ package controller import ( "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/gfile" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/module/sys/model" "goadmin/utils/base" "goadmin/utils/tools" ) type SysOssController struct { base.BaseRouter } var ( controllerNameSysOss = "SysOssController" ossConfigKey = "CLOUD_STORAGE_CONFIG_KEY" ) //SysOss页面信息 func (controller *SysOssController) Index(r *ghttp.Request) { base.WriteTpl(r, "sys/oss.html", g.Map{}) } //获取SysOss单条信息 func (controller *SysOssController) Get(r *ghttp.Request) { id := r.GetInt("id") model := model.SysOss{Id: id}.Get() if model.Id <= 0 { base.Fail(r, controllerNameSysOss+" get fail") } base.Succ(r, model) } //根据id或者ids删除{.TplModelName} func (controller *SysOssController) Delete(r *ghttp.Request) { ids := r.GetInts("ids") for _, id := range ids { model := model.SysOss{Id: id} model.Delete() } base.Succ(r, "") } //创建一条{.TplModelName} func (controller *SysOssController) Save(r *ghttp.Request) { model := model.SysOss{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysOss+" save struct error", err) base.Error(r, "save error") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysOss+" save fail") } base.Succ(r, "") } //更新一条{.TplModelName} func (controller *SysOssController) Update(r *ghttp.Request) { model := model.SysOss{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysOss+" save struct error", err) base.Error(r, "save error") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysOss+" save fail") } base.Succ(r, "") } //分页列表{.TplModelName} func (controller *SysOssController) Page(r *ghttp.Request) { form := base.NewForm(r.GetQueryMap()) model := model.SysOss{} page := model.Page(&form) base.Succ(r, g.Map{"list": page, "form": form}) } //获取OSS的Config func (controller *SysOssController) GetConfig(r *ghttp.Request) { model := model.SysConfig{ParamKey: ossConfigKey}.GetByKey() if model.Id <= 0 { base.Fail(r, controllerNameSysConfig+" get fail") } base.Succ(r, model) } //保存OSS的Config func (controller *SysOssController) SaveConfig(r *ghttp.Request) { model := model.SysConfig{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysOss+" save struct error", err) base.Error(r, "save error") } model.ParamKey = ossConfigKey model.Remark = "云存储配置信息" model.Status = 0 var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.UpdateByKey() } if num <= 0 { base.Fail(r, controllerNameSysConfig+" save fail") } base.Succ(r, "") } //上传文件 func (controller *SysOssController) Upload(r *ghttp.Request) { if f, h, e := r.FormFile("upload-file"); e == nil { defer f.Close() ossConfig := tools.GetCache(ossConfigKey) if ossConfig == nil || ossConfig == "" { model := model.SysConfig{ParamKey: ossConfigKey}.GetByKey() if model.Id <= 0 { base.Fail(r, controllerNameSysConfig+" get fail") } ossConfig = model.ParamValue } configModel := model.SysOssCloud{} err := gjson.DecodeTo(ossConfig, &configModel) if err != nil { base.Fail(r, "解析错误") } client, err := oss.New(configModel.AliyunEndPoint, configModel.AliyunAccessKeyId, configModel.AliyunAccessKeySecret) if err != nil { base.Fail(r, "上传配置错误") } bucket, err := client.Bucket(configModel.AliyunBucketName) if err != nil { base.Fail(r, "选择bucket错误") } name := "file" + gfile.Separator + gconv.String(tools.GetId(2)) + "." + gfile.ExtName(h.Filename) err = bucket.PutObject(name, f) if err != nil { base.Fail(r, "存储错误") } model := model.SysOss{} model.Url = g.Config().GetString("setting.cdn") + name var num int64 num = model.Insert() if num <= 0 { base.Fail(r, "存入数据库失败") } base.Succ(r, model) } else { r.Response.Write(e.Error()) } } ================================================ FILE: module/sys/controller/sys_user_controller.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_user_controller * @Version: 1.0.0 * @Date: 2019-11-17 */ package controller import ( "github.com/gogf/gf/crypto/gmd5" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/module/sys/model" "goadmin/utils/base" "goadmin/utils/tools" ) type SysUserController struct { base.BaseRouter } var ( controllerNameSysUser = "SysUserController" ) //SysUser页面信息 func (controller *SysUserController) Index(r *ghttp.Request) { base.WriteTpl(r, "sys/user.html", g.Map{}) } //获取SysUser单条信息 func (controller *SysUserController) Get(r *ghttp.Request) { id := r.GetInt("id") model := model.SysUser{Id: id}.Get() if model.Id <= 0 { base.Fail(r, controllerNameSysUser+" get fail") } base.Succ(r, model) } //根据id或者ids删除{.TplModelName} func (controller *SysUserController) Delete(r *ghttp.Request) { ids := r.GetInts("ids") for _, id := range ids { model := model.SysUser{Id: id} model.Delete() } base.Succ(r, "") } //创建一条{.TplModelName} func (controller *SysUserController) Save(r *ghttp.Request) { model := model.SysUser{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysUser+" save struct error", err) base.Error(r, "save error") } model.Salt = gconv.String(tools.GetId(1)) if model.Password == "" { base.Error(r, "请输入密码") } model.Password, err = gmd5.Encrypt(model.Password + model.Salt) if err != nil { glog.Error(controllerNameSysUser+" save struct error", err) base.Error(r, "加密错误") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysUser+" save fail") } base.Succ(r, "") } //更新一条{.TplModelName} func (controller *SysUserController) Update(r *ghttp.Request) { model := model.SysUser{} err := gconv.Struct(r.GetPostMap(), &model) if err != nil { glog.Error(controllerNameSysUser+" save struct error", err) base.Error(r, "save error") } model.Salt = gconv.String(tools.GetId(1)) if model.Password == "" { base.Error(r, "请输入密码") } model.Password, err = gmd5.Encrypt(model.Password + model.Salt) if err != nil { glog.Error(controllerNameSysUser+" save struct error", err) base.Error(r, "加密错误") } var num int64 if model.Id <= 0 { num = model.Insert() } else { num = model.Update() } if num <= 0 { base.Fail(r, controllerNameSysUser+" save fail") } base.Succ(r, "") } //分页列表{.TplModelName} func (controller *SysUserController) Page(r *ghttp.Request) { form := base.NewForm(r.GetQueryMap()) model := model.SysUser{} page := model.Page(&form) base.Succ(r, g.Map{"list": page, "form": form}) } ================================================ FILE: module/sys/model/sys_config_model.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_config_model * @Version: 1.0.0 * @Date: 2019-11-17 */ package model import ( "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/utils/base" "goadmin/utils/tools" ) import ( "github.com/gogf/gf/os/gtime" ) type SysConfig struct { Id int `orm:"id,primary" json:"Id" gconv:"Id,omitempty"` ParamKey string `orm:"param_key,unique" json:"ParamKey" gconv:"ParamKey,omitempty"` ParamValue string `orm:"param_value" json:"ParamValue" gconv:"ParamValue,omitempty"` Remark string `orm:"remark" json:"Remark" gconv:"Remark,omitempty"` CreateTime *gtime.Time `orm:"create_time" json:"CreateTime" gconv:"CreateTime,omitempty"` UpdateTime *gtime.Time `orm:"update_time" json:"UpdateTime" gconv:"UpdateTime,omitempty"` Status int `orm:"status" json:"Status" gconv:"Status,omitempty"` } //创建mSysConfig func (model *SysConfig) Insert() int64 { model.CreateTime = gtime.Now() model.UpdateTime = gtime.Now() model.Status = 1 r, err := model.dbModel().Data(model).Insert() if err != nil { glog.Error(model.TableName()+" insert error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" insert res error", err2) return 0 } else if res > 0 { lastId, err2 := r.LastInsertId() if err2 != nil { glog.Error(model.TableName()+" LastInsertId res error", err2) return 0 } else { model.Id = gconv.Int(lastId) } } tools.SetCache(model.ParamKey, model.ParamValue) return res } //删除SysConfig func (model SysConfig) Delete() int64 { if model.Id <= 0 { glog.Error(model.TableName() + " delete id error") return 0 } r, err := model.dbModel().Where(" id = ?", model.Id).Delete() if err != nil { glog.Error(model.TableName()+" delete error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" delete res error", err2) return 0 } tools.DelCache(model.ParamKey) return res } //更新SysConfig func (model *SysConfig) Update() int64 { model.UpdateTime = gtime.Now() r, err := model.dbModel().Data(model).Where(" id = ?", model.Id).Update() if err != nil { glog.Error(model.TableName()+" update error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" update res error", err2) return 0 } tools.SetCache(model.ParamKey, model.ParamValue) return res } func (model *SysConfig) UpdateByKey() int64 { model.UpdateTime = gtime.Now() r, err := model.dbModel().Data(model).Where(" param_key = ?", model.ParamKey).Update() if err != nil { glog.Error(model.TableName()+" update error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" update res error", err2) return 0 } tools.SetCache(model.ParamKey, model.ParamValue) return res } //根据Key查询SysConfig func (model SysConfig) GetByKey() SysConfig { if model.ParamKey == "" { glog.Error("根据KEY获取配置失败") return SysConfig{} } var resData SysConfig err := model.dbModel("t").Where(" param_key = ?", model.ParamKey).Fields(model.columns()).Struct(&resData) if err != nil { glog.Error(model.TableName()+" get one error", err) return SysConfig{} } return resData } //根据ID查询SysConfig func (model SysConfig) Get() SysConfig { if model.Id <= 0 { glog.Error(model.TableName() + " get id error") return SysConfig{} } var resData SysConfig err := model.dbModel("t").Where(" id = ? and status=1", model.Id).Fields(model.columns()).Struct(&resData) if err != nil { glog.Error(model.TableName()+" get one error", err) return SysConfig{} } return resData } //分页查询SysConfig func (model SysConfig) Page(form *base.BaseForm) []SysConfig { if form.Page <= 0 || form.Rows <= 0 { glog.Error(model.TableName()+" page param error", form.Page, form.Rows) return []SysConfig{} } where := " status = 1 " var params []interface{} if form.Params != nil && form.Params["name"] != "" { where += " and name like ? " params = append(params, "%"+form.Params["name"]+"%") } num, err := model.dbModel("t").Where(where, params).Count() form.TotalSize = num form.TotalPage = num / form.Rows // 没有数据直接返回 if num == 0 { form.TotalPage = 0 form.TotalSize = 0 return []SysConfig{} } var resData []SysConfig pageNum, pageSize := (form.Page-1)*form.Rows, form.Rows dbModel := model.dbModel("t").Fields(model.columns()).Fields(model.columns()) err = dbModel.Where(where, params).Limit(pageNum, pageSize).OrderBy(form.OrderBy).Structs(&resData) if err != nil { glog.Error(model.TableName()+" page list error", err) return []SysConfig{} } return resData } //返回数据库SysConfig func (model SysConfig) dbModel(alias ...string) *gdb.Model { var tmpAlias string if len(alias) > 0 { tmpAlias = " " + alias[0] } tableModel := g.DB("center").Table(model.TableName() + tmpAlias).Safe() return tableModel } //返回主键SysConfig func (model SysConfig) PkVal() int { return model.Id } //表名SysConfig func (model SysConfig) TableName() string { return "sys_config" } //列名SysConfig func (model SysConfig) columns() string { sqlColumns := "t.create_time as CreateTime,t.update_time as UpdateTime,t.status as Status,t.id as Id,t.param_key as ParamKey,t.param_value as ParamValue,t.remark as Remark" return sqlColumns } ================================================ FILE: module/sys/model/sys_oss_cloud.go ================================================ package model type SysOssCloud struct { AliyunDomain string `json:"aliyunDomain" gconv:"AliyunDomain,omitempty"` AliyunEndPoint string `json:"aliyunEndPoint" gconv:"AliyunEndPoint,omitempty"` AliyunAccessKeyId string `json:"aliyunAccessKeyId" gconv:"AliyunAccessKeyId,omitempty"` AliyunAccessKeySecret string `json:"aliyunAccessKeySecret" gconv:"AliyunAccessKeySecret,omitempty"` AliyunBucketName string `json:"aliyunBucketName" gconv:"AliyunBucketName,omitempty"` } ================================================ FILE: module/sys/model/sys_oss_model.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_oss_model * @Version: 1.0.0 * @Date: 2019-11-17 */ package model import ( "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/utils/base" ) import ( "github.com/gogf/gf/os/gtime" ) type SysOss struct { Id int `orm:"id,primary" json:"Id" gconv:"Id,omitempty"` Url string `orm:"url" json:"Url" gconv:"Url,omitempty"` CreateTime *gtime.Time `orm:"create_time" json:"CreateTime" gconv:"CreateTime,omitempty"` UpdateTime *gtime.Time `orm:"update_time" json:"UpdateTime" gconv:"UpdateTime,omitempty"` Status int `orm:"status" json:"Status" gconv:"Status,omitempty"` } //创建mSysOss func (model *SysOss) Insert() int64 { model.CreateTime = gtime.Now() model.UpdateTime = gtime.Now() model.Status = 1 r, err := model.dbModel().Data(model).Insert() if err != nil { glog.Error(model.TableName()+" insert error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" insert res error", err2) return 0 } else if res > 0 { lastId, err2 := r.LastInsertId() if err2 != nil { glog.Error(model.TableName()+" LastInsertId res error", err2) return 0 } else { model.Id = gconv.Int(lastId) } } return res } //删除SysOss func (model SysOss) Delete() int64 { if model.Id <= 0 { glog.Error(model.TableName() + " delete id error") return 0 } r, err := model.dbModel().Where(" id = ?", model.Id).Delete() if err != nil { glog.Error(model.TableName()+" delete error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" delete res error", err2) return 0 } return res } //更新SysOss func (model *SysOss) Update() int64 { model.UpdateTime = gtime.Now() r, err := model.dbModel().Data(model).Where(" id = ?", model.Id).Update() if err != nil { glog.Error(model.TableName()+" update error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" update res error", err2) return 0 } return res } //根据ID查询SysOss func (model SysOss) Get() SysOss { if model.Id <= 0 { glog.Error(model.TableName() + " get id error") return SysOss{} } var resData SysOss err := model.dbModel("t").Where(" id = ? and status=1", model.Id).Fields(model.columns()).Struct(&resData) if err != nil { glog.Error(model.TableName()+" get one error", err) return SysOss{} } return resData } //分页查询SysOss func (model SysOss) Page(form *base.BaseForm) []SysOss { if form.Page <= 0 || form.Rows <= 0 { glog.Error(model.TableName()+" page param error", form.Page, form.Rows) return []SysOss{} } where := " status= 1 " var params []interface{} if form.Params != nil && form.Params["name"] != "" { where += " and name like ? " params = append(params, "%"+form.Params["name"]+"%") } num, err := model.dbModel("t").Where(where, params).Count() form.TotalSize = num form.TotalPage = num / form.Rows // 没有数据直接返回 if num == 0 { form.TotalPage = 0 form.TotalSize = 0 return []SysOss{} } var resData []SysOss pageNum, pageSize := (form.Page-1)*form.Rows, form.Rows dbModel := model.dbModel("t").Fields(model.columns()).Fields(model.columns()) err = dbModel.Where(where, params).Limit(pageNum, pageSize).OrderBy(form.OrderBy).Structs(&resData) if err != nil { glog.Error(model.TableName()+" page list error", err) return []SysOss{} } return resData } //返回数据库SysOss func (model SysOss) dbModel(alias ...string) *gdb.Model { var tmpAlias string if len(alias) > 0 { tmpAlias = " " + alias[0] } tableModel := g.DB("center").Table(model.TableName() + tmpAlias).Safe() return tableModel } //返回主键SysOss func (model SysOss) PkVal() int { return model.Id } //表名SysOss func (model SysOss) TableName() string { return "sys_oss" } //列名SysOss func (model SysOss) columns() string { sqlColumns := "t.id as Id,t.url as Url,t.create_time as CreateTime,t.update_time as UpdateTime,t.status as Status" return sqlColumns } ================================================ FILE: module/sys/model/sys_user_model.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: sys_user_model * @Version: 1.0.0 * @Date: 2019-11-17 */ package model import ( "fmt" "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/glog" "github.com/gogf/gf/util/gconv" "goadmin/utils/base" ) import ( "github.com/gogf/gf/os/gtime" ) type SysUser struct { Id int `orm:"id,primary" json:"Id" gconv:"Id,omitempty"` Username string `orm:"username,unique" json:"Username" gconv:"Username,omitempty"` Password string `orm:"password" json:"Password" gconv:"Password,omitempty"` Salt string `orm:"salt" json:"Salt" gconv:"Salt,omitempty"` Mobile string `orm:"mobile" json:"Mobile" gconv:"Mobile,omitempty"` CreateTime *gtime.Time `orm:"create_time" json:"CreateTime" gconv:"CreateTime,omitempty"` UpdateTime *gtime.Time `orm:"update_time" json:"UpdateTime" gconv:"UpdateTime,omitempty"` Status int `orm:"status" json:"Status" gconv:"Status,omitempty"` } //创建mSysUser func (model *SysUser) Insert() int64 { model.CreateTime = gtime.Now() model.UpdateTime = gtime.Now() model.Status = 1 r, err := model.dbModel().Data(model).Insert() if err != nil { glog.Error(model.TableName()+" insert error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" insert res error", err2) return 0 } else if res > 0 { lastId, err2 := r.LastInsertId() if err2 != nil { glog.Error(model.TableName()+" LastInsertId res error", err2) return 0 } else { model.Id = gconv.Int(lastId) } } return res } //删除SysUser func (model SysUser) Delete() int64 { if model.Id <= 0 { glog.Error(model.TableName() + " delete id error") return 0 } r, err := model.dbModel().Where(" id = ?", model.Id).Delete() if err != nil { glog.Error(model.TableName()+" delete error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" delete res error", err2) return 0 } return res } //更新SysUser func (model *SysUser) Update() int64 { model.UpdateTime = gtime.Now() r, err := model.dbModel().Data(model).Where(" id = ?", model.Id).Update() if err != nil { glog.Error(model.TableName()+" update error", err) return 0 } res, err2 := r.RowsAffected() if err2 != nil { glog.Error(model.TableName()+" update res error", err2) return 0 } return res } //根据ID查询SysUser func (model SysUser) Get() SysUser { if model.Id <= 0 { glog.Error(model.TableName() + " get id error") return SysUser{} } var resData SysUser err := model.dbModel("t").Where(" id = ? and status=1", model.Id).Fields(model.columns()).Struct(&resData) if err != nil { glog.Error(model.TableName()+" get one error", err) return SysUser{} } return resData } //分页查询SysUser func (model SysUser) Page(form *base.BaseForm) []SysUser { if form.Page <= 0 || form.Rows <= 0 { glog.Error(model.TableName()+" page param error", form.Page, form.Rows) return []SysUser{} } where := " status = 1 " var params []interface{} if form.Params != nil && form.Params["name"] != "" { where += " and name like ? " params = append(params, "%"+form.Params["name"]+"%") } num, err := model.dbModel("t").Where(where, params).Count() form.TotalSize = num form.TotalPage = num / form.Rows // 没有数据直接返回 if num == 0 { form.TotalPage = 0 form.TotalSize = 0 return []SysUser{} } var resData []SysUser fmt.Println("当前排序:%s", form.OrderBy) pageNum, pageSize := (form.Page-1)*form.Rows, form.Rows dbModel := model.dbModel("t").Fields(model.columns()).Fields(model.columns()) err = dbModel.Where(where, params).Limit(pageNum, pageSize).OrderBy(form.OrderBy).Structs(&resData) if err != nil { glog.Error(model.TableName()+" page list error", err) return []SysUser{} } return resData } //返回数据库SysUser func (model SysUser) dbModel(alias ...string) *gdb.Model { var tmpAlias string if len(alias) > 0 { tmpAlias = " " + alias[0] } tableModel := g.DB("center").Table(model.TableName() + tmpAlias).Safe() return tableModel } //返回主键SysUser func (model SysUser) PkVal() int { return model.Id } //表名SysUser func (model SysUser) TableName() string { return "sys_user" } //列名SysUser func (model SysUser) columns() string { sqlColumns := "t.id as Id,t.username as Username,t.password as Password,t.salt as Salt,t.mobile as Mobile,t.create_time as CreateTime,t.update_time as UpdateTime,t.status as Status" return sqlColumns } ================================================ FILE: module/sys/module.go ================================================ /** * @Author: Rocks * @Email: 451360994@qq.com * @Description: * @File: module * @Version: 1.0.0 * @Date: 2019-11-17 */ package sys import "goadmin/module/sys/config" func InitModule() { config.InitRouter() } ================================================ FILE: public/modules/common.js ================================================ //bootstrap-table配置 var baseURL = "http://localhost:8192/"; //工具集合Tools window.T = {}; // 获取请求参数 // 使用示例 // location.href = http://localhost:8080/index.html?id=123 // T.p('id') --> 123; var url = function (name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; }; T.p = url; //全局配置 $.ajaxSetup({ dataType: "json", cache: false }); //重写alert window.alert = function (msg, callback) { top.swal({ text: msg, icon: "error", buttons: false, timer:2000, }).then((isConfirm) => { if (isConfirm) { if (typeof (callback) === "function") { callback("ok"); } } }); } //重写confirm式样框 window.confirm = function (msg, callback) { top.swal({ text: msg, icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { if (typeof (callback) === "function") { callback("ok"); } } }); } //选择一条记录 function getSelectedRow() { var grid = $("#table"); var rowKey = grid.getGridParam("selrow"); if (!rowKey) { alert("请选择一条记录"); return; } var selectedIDs = grid.getGridParam("selarrrow"); if (selectedIDs.length > 1) { alert("只能选择一条记录"); return; } return selectedIDs[0]; } //选择多条记录 //选择多条记录 function getSelectedRows() { var selected = $("#table").bootstrapTable('getSelections'); var ids = new Array(); for (var i = 0; i < selected.length; i++) { ids[i] = selected[i].Id; } if (ids.length == 0) { alert("请选择记录"); } console.log(ids); return ids; } //判断是否为空 function isBlank(value) { return !value || !/\S/.test(value) } ================================================ FILE: public/modules/sys/config.js ================================================ $(function () { function addButtonFunc(value, row, index) { return [ '
编辑
', '
删除
', ].join(''); } window.operateEvents = { 'click #editButton': function (e, value, row, index) { vm.update(row.Id); }, 'click #deleteButton': function (e, value, row, index) { vm.del(row.Id); } }; $('#table').bootstrapTable({ url: baseURL + 'sys/config/page', method: "GET", striped: true, cache: false, pagination: true, pageList: [20, 40, 60, 100], pageSize: 20, pageNumber: 1, sortName: "id", sortOrder: "desc", sidePagination: 'server', search: false, uniqueId: "Id", silent: true, classes: "table table-hover", paginationHAlign: "left", paginationDetailHAlign: "right", queryParams: queryParams, responseHandler: function (res) { return { "total": res.data.form.TotalSize, "rows": res.data.list }; }, onLoadSuccess: function () { }, onLoadError: function () { alert("数据加载失败!"); }, columns: [{ checkbox: true, visible: true }, { field: 'Id', title: 'ID' }, { field: 'ParamKey', title: '参数名' }, { field: 'ParamValue', title: '参数值' }, { field: 'Remark', title: '备注' }, { field: 'operate', title: '操作', events: operateEvents, formatter: addButtonFunc  } ] }); function queryParams(params) { var temp = { offset: params.offset, limit: params.limit, search: $(".search-input").val(), rows: params.limit, page: (params.offset / params.limit) + 1, sort: params.sort, sortOrder: params.order }; return temp; }; $("#search-btn").click(function () { $('#table').bootstrapTable('refresh'); }); }); var vm = new Vue({ el: '#rrapp', data: { showList: true, title: null, sysconfig:{ } }, methods: { query: function () { vm.reload(); }, add: function () { vm.showList = false; vm.title = "新增"; vm.sysconfig= {}; }, update: function (Id) { if (Id == null) { return; } vm.showList = false; vm.title = "修改"; vm.getInfo(Id) }, saveOrUpdate: function (event) { $('#btnSaveOrUpdate').button('loading').delay(1000).queue(function () { var url = vm.sysconfig.Id ==null ? "sys/config/save" : "sys/config/update"; $.ajax({ type: "POST", url: baseURL + url, data: vm.sysconfig, success: function (r) { if (r.code === 0) { swal({ text: "操作成功", icon: "success", buttons: false, timer: 2000, }); vm.reload(); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } } }) ; }); }, del: function (Id) { var Ids = [Id]; var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/config/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } }else { top.swal.close(); } }); }, bulkdel: function (event) { var Ids = getSelectedRows(); if (Ids == null || Ids.length == 0) { return; } var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/config/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } }else { top.swal.close(); } }); }, getInfo: function (Id) { $.get(baseURL + "sys/config/get/" +Id, function (r) { vm.sysconfig= r.data; }); }, reload: function (event) { vm.showList = true; $('#table').bootstrapTable('refresh'); } } }) ; ================================================ FILE: public/modules/sys/oss.js ================================================ $(function () { function addButtonFunc(value, row, index) { return '
删除
'; } window.operateEvents = { 'click #deleteButton': function (e, value, row, index) { vm.del(row.Id); } }; $('#table').bootstrapTable({ url: baseURL + 'sys/oss/page', method: "GET", striped: true, cache: false, pagination: true, pageList: [20, 40, 60, 100], pageSize: 20, pageNumber: 1, sortName: "id", sortOrder: "desc", sidePagination: 'server', search: false, uniqueId: "Id", silent: true, classes: "table table-hover", paginationHAlign: "left", paginationDetailHAlign: "right", queryParams: queryParams, responseHandler: function (res) { return { "total": res.data.form.TotalSize, "rows": res.data.list }; }, onLoadSuccess: function () { }, onLoadError: function () { alert("数据加载失败!"); }, columns: [{ checkbox: true, visible: true }, { field: 'Id', title: 'ID' }, { field: 'Url', title: '地址' }, { field: 'operate', title: '操作', events: operateEvents, formatter: addButtonFunc } ] }); function queryParams(params) { var temp = { offset: params.offset, limit: params.limit, search: $(".search-input").val(), rows: params.limit, page: (params.offset / params.limit) + 1, sort: params.sort, sortOrder: params.order }; return temp; }; $("#search-btn").click(function () { $('#table').bootstrapTable('refresh'); }); new AjaxUpload('#upload', { action: baseURL + "sys/oss/upload", name: 'upload-file', autoSubmit: true, responseType: "json", onSubmit: function (file, extension) { if (vm.ParamValue == null) { alert("云存储配置未配置"); return false; } if (!(extension && /^(jpg|jpeg|png|gif)$/.test(extension.toLowerCase()))) { alert('只支持jpg、png、gif格式的图片!'); return false; } }, onComplete: function (file, r) { if (r.code == 0) { vm.reload(); } else { alert(r.msg); } } }); }); var vm = new Vue({ el: '#rrapp', data: { showList: true, title: null, sysoss: {}, config: { ParamValue: {}, }, ParamValue: {} }, created: function () { this.getConfig(); }, methods: { query: function () { vm.reload(); }, edit: function () { vm.showList = false; vm.title = "修改配置"; vm.config = {}; vm.getConfig() }, upload: function () { vm.title = "修改配置"; }, saveConfig: function (event) { $('#btnSaveOrUpdate').button('loading').delay(1000).queue(function () { var url = "sys/oss/config/save"; vm.config.ParamValue = JSON.stringify(vm.ParamValue) $.ajax({ type: "POST", url: baseURL + url, data: vm.config, success: function (r) { if (r.code === 0) { swal({ text: "操作成功", icon: "success", buttons: false, timer: 2000, }); vm.reload(); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } } }) ; }); }, del: function (Id) { var Ids = [Id]; var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/oss/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } } else { top.swal.close(); } }); }, bulkdel: function (event) { var Ids = getSelectedRows(); if (Ids == null || Ids.length == 0) { return; } var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/oss/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } } else { top.swal.close(); } }); }, getConfig: function () { $.get(baseURL + "sys/oss/config/get", function (r) { vm.config = r.data vm.ParamValue = JSON.parse(r.data.ParamValue); }); }, reload: function (event) { vm.showList = true; $('#table').bootstrapTable('refresh'); } } }) ; ================================================ FILE: public/modules/sys/user.js ================================================ $(function () { function addButtonFunc(value, row, index) { return [ '
编辑
', '
删除
', ].join(''); } window.operateEvents = { 'click #editButton': function (e, value, row, index) { vm.update(row.Id); }, 'click #deleteButton': function (e, value, row, index) { vm.del(row.Id); } }; $('#table').bootstrapTable({ url: baseURL + 'sys/user/page', method: "GET", striped: true, cache: false, pagination: true, pageList: [20, 40, 60, 100], pageSize: 20, pageNumber: 1, sortName: "id", sortOrder: "desc", sidePagination: 'server', search: false, uniqueId: "Id", silent: true, classes: "table table-hover", paginationHAlign: "left", paginationDetailHAlign: "right", queryParams: queryParams, responseHandler: function (res) { return { "total": res.data.form.TotalSize, "rows": res.data.list }; }, onLoadSuccess: function () { }, onLoadError: function () { alert("数据加载失败!"); }, columns: [{ checkbox: true, visible: true }, { field: 'Id', title: 'ID' }, { field: 'Username', title: '用户名' }, { field: 'Mobile', title: '手机号' }, { field: 'operate', title: '操作', events: operateEvents, formatter: addButtonFunc  } ] }); function queryParams(params) { var temp = { offset: params.offset, limit: params.limit, search: $(".search-input").val(), rows: params.limit, page: (params.offset / params.limit) + 1, sort: params.sort, sortOrder: params.order }; return temp; }; $("#search-btn").click(function () { $('#table').bootstrapTable('refresh'); }); }); var vm = new Vue({ el: '#rrapp', data: { showList: true, title: null, sysuser:{ } }, methods: { query: function () { vm.reload(); }, add: function () { vm.showList = false; vm.title = "新增"; vm.sysuser= {}; }, update: function (Id) { if (Id == null) { return; } vm.showList = false; vm.title = "修改"; vm.getInfo(Id) }, saveOrUpdate: function (event) { $('#btnSaveOrUpdate').button('loading').delay(1000).queue(function () { var url = vm.sysuser.Id ==null ? "sys/user/save" : "sys/user/update"; $.ajax({ type: "POST", url: baseURL + url, data: vm.sysuser, success: function (r) { if (r.code === 0) { swal({ text: "操作成功", icon: "success", buttons: false, timer: 2000, }); vm.reload(); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); $('#btnSaveOrUpdate').button('reset'); $('#btnSaveOrUpdate').dequeue(); } } }) ; }); }, del: function (Id) { var Ids = [Id]; var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/user/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } }else { top.swal.close(); } }); }, bulkdel: function (event) { var Ids = getSelectedRows(); if (Ids == null || Ids.length == 0) { return; } var lock = false; top.swal({ title: "确定要删除该记录?", icon: "warning", buttons: ["取消", "确定"], closeModal: true, }).then((isConfirm) => { if (isConfirm) { top.swal.close(); if (!lock) { lock = true; $.ajax({ type: "POST", url: baseURL + "sys/user/delete", data: {ids: Ids}, success: function (r) { if (r.code == 0) { swal({ text: "删除成功", icon: "success", buttons: false, timer: 2000, }); $('#table').bootstrapTable('refresh'); } else { swal({ text: r.msg, icon: "error", buttons: false, timer: 2000, }); } } }); } }else { top.swal.close(); } }); }, getInfo: function (Id) { $.get(baseURL + "sys/user/get/" +Id, function (r) { vm.sysuser= r.data; vm.sysuser.Password = null; }); }, reload: function (event) { vm.showList = true; $('#table').bootstrapTable('refresh'); } } }) ; ================================================ FILE: public/plugins/ajaxupload/ajaxupload.js ================================================ /** * AJAX Upload ( http://valums.com/ajax-upload/ ) * Copyright (c) Andris Valums * Licensed under the MIT license ( http://valums.com/mit-license/ ) * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions */ (function () { /* global window */ /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */ /** * Wrapper for FireBug's console.log */ function log(){ if (typeof(console) != 'undefined' && typeof(console.log) == 'function'){ Array.prototype.unshift.call(arguments, '[Ajax Upload]'); console.log( Array.prototype.join.call(arguments, ' ')); } } /** * Attaches event to a dom element. * @param {Element} el * @param type event name * @param fn callback This refers to the passed element */ function addEvent(el, type, fn){ if (el.addEventListener) { el.addEventListener(type, fn, false); } else if (el.attachEvent) { el.attachEvent('on' + type, function(){ fn.call(el); }); } else { throw new Error('not supported or DOM not loaded'); } } /** * Attaches resize event to a window, limiting * number of event fired. Fires only when encounteres * delay of 100 after series of events. * * Some browsers fire event multiple times when resizing * http://www.quirksmode.org/dom/events/resize.html * * @param fn callback This refers to the passed element */ function addResizeEvent(fn){ var timeout; addEvent(window, 'resize', function(){ if (timeout){ clearTimeout(timeout); } timeout = setTimeout(fn, 100); }); } // Needs more testing, will be rewriten for next version // getOffset function copied from jQuery lib (http://jquery.com/) if (document.documentElement.getBoundingClientRect){ // Get Offset using getBoundingClientRect // http://ejohn.org/blog/getboundingclientrect-is-awesome/ var getOffset = function(el){ var box = el.getBoundingClientRect(); var doc = el.ownerDocument; var body = doc.body; var docElem = doc.documentElement; // for ie var clientTop = docElem.clientTop || body.clientTop || 0; var clientLeft = docElem.clientLeft || body.clientLeft || 0; // In Internet Explorer 7 getBoundingClientRect property is treated as physical, // while others are logical. Make all logical, like in IE8. var zoom = 1; if (body.getBoundingClientRect) { var bound = body.getBoundingClientRect(); zoom = (bound.right - bound.left) / body.clientWidth; } if (zoom > 1) { clientTop = 0; clientLeft = 0; } var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop, left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft; return { top: top, left: left }; }; } else { // Get offset adding all offsets var getOffset = function(el){ var top = 0, left = 0; do { top += el.offsetTop || 0; left += el.offsetLeft || 0; el = el.offsetParent; } while (el); return { left: left, top: top }; }; } /** * Returns left, top, right and bottom properties describing the border-box, * in pixels, with the top-left relative to the body * @param {Element} el * @return {Object} Contains left, top, right,bottom */ function getBox(el){ var left, right, top, bottom; var offset = getOffset(el); left = offset.left; top = offset.top; right = left + el.offsetWidth; bottom = top + el.offsetHeight; return { left: left, right: right, top: top, bottom: bottom }; } /** * Helper that takes object literal * and add all properties to element.style * @param {Element} el * @param {Object} styles */ function addStyles(el, styles){ for (var name in styles) { if (styles.hasOwnProperty(name)) { el.style[name] = styles[name]; } } } /** * Function places an absolutely positioned * element on top of the specified element * copying position and dimentions. * @param {Element} from * @param {Element} to */ function copyLayout(from, to){ var box = getBox(from); addStyles(to, { position: 'absolute', left : box.left + 'px', top : box.top + 'px', width : from.offsetWidth + 'px', height : from.offsetHeight + 'px' }); } /** * Creates and returns element from html chunk * Uses innerHTML to create an element */ var toElement = (function(){ var div = document.createElement('div'); return function(html){ div.innerHTML = html; var el = div.firstChild; return div.removeChild(el); }; })(); /** * Function generates unique id * @return unique id */ var getUID = (function(){ var id = 0; return function(){ return 'ValumsAjaxUpload' + id++; }; })(); /** * Get file name from path * @param {String} file path to file * @return filename */ function fileFromPath(file){ return file.replace(/.*(\/|\\)/, ""); } /** * Get file extension lowercase * @param {String} file name * @return file extenstion */ function getExt(file){ return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : ''; } function hasClass(el, name){ var re = new RegExp('\\b' + name + '\\b'); return re.test(el.className); } function addClass(el, name){ if ( ! hasClass(el, name)){ el.className += ' ' + name; } } function removeClass(el, name){ var re = new RegExp('\\b' + name + '\\b'); el.className = el.className.replace(re, ''); } function removeNode(el){ el.parentNode.removeChild(el); } /** * Easy styling and uploading * @constructor * @param button An element you want convert to * upload button. Tested dimentions up to 500x500px * @param {Object} options See defaults below. */ window.AjaxUpload = function(button, options){ this._settings = { // Location of the server-side upload script action: 'upload.php', // File upload name name: 'userfile', // Additional data to send data: {}, // Submit file as soon as it's selected autoSubmit: true, // The type of data that you're expecting back from the server. // html and xml are detected automatically. // Only useful when you are using json data as a response. // Set to "json" in that case. responseType: false, // Class applied to button when mouse is hovered hoverClass: 'hover', // Class applied to button when AU is disabled disabledClass: 'disabled', // When user selects a file, useful with autoSubmit disabled // You can return false to cancel upload onChange: function(file, extension){ }, // Callback to fire before file is uploaded // You can return false to cancel upload onSubmit: function(file, extension){ }, // Fired when file upload is completed // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE! onComplete: function(file, response){ } }; // Merge the users options with our defaults for (var i in options) { if (options.hasOwnProperty(i)){ this._settings[i] = options[i]; } } // button isn't necessary a dom element if (button.jquery){ // jQuery object was passed button = button[0]; } else if (typeof button == "string") { if (/^#.*/.test(button)){ // If jQuery user passes #elementId don't break it button = button.slice(1); } button = document.getElementById(button); } if ( ! button || button.nodeType !== 1){ throw new Error("Please make sure that you're passing a valid element"); } if ( button.nodeName.toUpperCase() == 'A'){ // disable link addEvent(button, 'click', function(e){ if (e && e.preventDefault){ e.preventDefault(); } else if (window.event){ window.event.returnValue = false; } }); } // DOM element this._button = button; // DOM element this._input = null; // If disabled clicking on button won't do anything this._disabled = false; // if the button was disabled before refresh if will remain // disabled in FireFox, let's fix it this.enable(); this._rerouteClicks(); }; // assigning methods to our class AjaxUpload.prototype = { setData: function(data){ this._settings.data = data; }, disable: function(){ addClass(this._button, this._settings.disabledClass); this._disabled = true; var nodeName = this._button.nodeName.toUpperCase(); if (nodeName == 'INPUT' || nodeName == 'BUTTON'){ this._button.setAttribute('disabled', 'disabled'); } // hide input if (this._input){ // We use visibility instead of display to fix problem with Safari 4 // The problem is that the value of input doesn't change if it // has display none when user selects a file this._input.parentNode.style.visibility = 'hidden'; } }, enable: function(){ removeClass(this._button, this._settings.disabledClass); this._button.removeAttribute('disabled'); this._disabled = false; }, /** * Creates invisible file input * that will hover above the button *
*/ _createInput: function(){ var self = this; var input = document.createElement("input"); input.setAttribute('type', 'file'); input.setAttribute('name', this._settings.name); addStyles(input, { 'position' : 'absolute', // in Opera only 'browse' button // is clickable and it is located at // the right side of the input 'right' : 0, 'margin' : 0, 'padding' : 0, 'fontSize' : '480px', 'cursor' : 'pointer' }); var div = document.createElement("div"); addStyles(div, { 'display' : 'block', 'position' : 'absolute', 'overflow' : 'hidden', 'margin' : 0, 'padding' : 0, 'opacity' : 0, // Make sure browse button is in the right side // in Internet Explorer 'direction' : 'ltr', //Max zIndex supported by Opera 9.0-9.2 'zIndex': 2147483583 }); // Make sure that element opacity exists. // Otherwise use IE filter if ( div.style.opacity !== "0") { if (typeof(div.filters) == 'undefined'){ throw new Error('Opacity not supported by the browser'); } div.style.filter = "alpha(opacity=0)"; } addEvent(input, 'change', function(){ if ( ! input || input.value === ''){ return; } // Get filename from input, required // as some browsers have path instead of it var file = fileFromPath(input.value); if (false === self._settings.onChange.call(self, file, getExt(file))){ self._clearInput(); return; } // Submit form when value is changed if (self._settings.autoSubmit) { self.submit(); } }); addEvent(input, 'mouseover', function(){ addClass(self._button, self._settings.hoverClass); }); addEvent(input, 'mouseout', function(){ removeClass(self._button, self._settings.hoverClass); // We use visibility instead of display to fix problem with Safari 4 // The problem is that the value of input doesn't change if it // has display none when user selects a file input.parentNode.style.visibility = 'hidden'; }); div.appendChild(input); document.body.appendChild(div); this._input = input; }, _clearInput : function(){ if (!this._input){ return; } // this._input.value = ''; Doesn't work in IE6 removeNode(this._input.parentNode); this._input = null; this._createInput(); removeClass(this._button, this._settings.hoverClass); }, /** * Function makes sure that when user clicks upload button, * the this._input is clicked instead */ _rerouteClicks: function(){ var self = this; // IE will later display 'access denied' error // if you use using self._input.click() // other browsers just ignore click() addEvent(self._button, 'mouseover', function(){ if (self._disabled){ return; } if ( ! self._input){ self._createInput(); } var div = self._input.parentNode; copyLayout(self._button, div); div.style.visibility = 'visible'; }); // commented because we now hide input on mouseleave /** * When the window is resized the elements * can be misaligned if button position depends * on window size */ //addResizeEvent(function(){ // if (self._input){ // copyLayout(self._button, self._input.parentNode); // } //}); }, /** * Creates iframe with unique name * @return {Element} iframe */ _createIframe: function(){ // We can't use getTime, because it sometimes return // same value in safari :( var id = getUID(); // We can't use following code as the name attribute // won't be properly registered in IE6, and new window // on form submit will open // var iframe = document.createElement('iframe'); // iframe.setAttribute('name', id); var iframe = toElement('