├── .air.conf
├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
└── workflows
│ └── go.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── apis
├── dashboard
│ └── dashboard.go
├── log
│ └── loginLog.go
├── monitor
│ └── server.go
├── process
│ ├── classify.go
│ ├── process.go
│ ├── task.go
│ ├── tpl.go
│ └── workOrder.go
├── public
│ └── file.go
├── system
│ ├── captcha.go
│ ├── dept.go
│ ├── index.go
│ ├── info.go
│ ├── menu.go
│ ├── post.go
│ ├── role.go
│ ├── rolemenu.go
│ ├── settings.go
│ └── sysuser.go
└── tpl
│ └── tpl.go
├── build.sh
├── cmd
├── api
│ └── server.go
├── cobra.go
└── migrate
│ └── server.go
├── config
├── db.sql
├── ferry.sql
├── rbac_model.conf
├── settings.dev.yml
└── settings.yml
├── database
├── initialize.go
├── interface.go
└── mysql.go
├── deploy
├── deploy.md
├── helm
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── templates
│ │ ├── NOTES.txt
│ │ ├── _helpers.tpl
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ ├── mysql
│ │ │ ├── persistentvolumeclaim.yaml
│ │ │ ├── service.yaml
│ │ │ ├── sql
│ │ │ │ ├── db.sql
│ │ │ │ └── ferry.sql
│ │ │ └── statefulset.yaml
│ │ ├── persistentvolumeclaim.yaml
│ │ ├── redis
│ │ │ ├── deployment.yaml
│ │ │ ├── persistentvolumeclaim.yaml
│ │ │ └── service.yaml
│ │ ├── secret.yaml
│ │ └── service.yaml
│ └── values.yaml
└── kubernetes
│ ├── config.yaml
│ ├── deploy.yaml
│ ├── mysql.yaml
│ ├── redis.yaml
│ ├── secret.yaml
│ └── sql
│ ├── db.sql
│ └── ferry.sql
├── docker-compose.yml
├── docker
└── entrypoint.sh
├── global
└── orm
│ └── db.go
├── go.mod
├── go.sum
├── handler
├── auth.go
├── httpshandler.go
└── ping.go
├── main.go
├── middleware
├── auth.go
├── customerror.go
├── header.go
├── init.go
├── logger.go
├── permission.go
└── requestid.go
├── models
├── base
│ └── base.go
├── gorm
│ └── gorm.go
├── process
│ ├── circulationHistory.go
│ ├── classify.go
│ ├── history.go
│ ├── process.go
│ ├── task.go
│ ├── tpl.go
│ ├── tplData.go
│ └── workOrder.go
└── system
│ ├── casbinrule.go
│ ├── dept.go
│ ├── initdb.go
│ ├── login.go
│ ├── loginlog.go
│ ├── menu.go
│ ├── model.go
│ ├── post.go
│ ├── role.go
│ ├── roledept.go
│ ├── rolemenu.go
│ ├── settings.go
│ └── sysuser.go
├── pkg
├── casbin
│ └── mycasbin.go
├── jsonTime
│ └── JSONTime.go
├── jwtauth
│ └── jwtauth.go
├── ldap
│ ├── connection.go
│ ├── ldapFieldsMap.go
│ ├── login.go
│ ├── search.go
│ └── updatePwd.go
├── logger
│ └── logger.go
├── notify
│ ├── dingtalk
│ │ └── dingtalk.go
│ ├── email
│ │ └── email.go
│ └── send.go
├── pagination
│ ├── pagination.go
│ └── params.go
├── service
│ ├── createWorkOrder.go
│ ├── dashboard.go
│ ├── getPrincipal.go
│ ├── getState.go
│ ├── getVariableValue.go
│ ├── handle.go
│ ├── process.go
│ ├── task.go
│ ├── userAuthority.go
│ └── workOrderList.go
├── settings
│ └── get_content.go
├── task
│ ├── send.go
│ ├── server.go
│ └── worker
│ │ ├── tasks.go
│ │ └── worker.go
└── utils
│ └── file.go
├── router
├── dashboard
│ └── dashboard.go
├── init_router.go
├── process
│ ├── classify.go
│ ├── process.go
│ ├── task.go
│ ├── tpl.go
│ └── workOrder.go
├── router.go
└── system
│ └── sys_router.go
├── static
├── scripts
│ ├── echo_test-4171bc7f4a05-admin.sh
│ └── print_hello_world-d266ee2a8029-admin.py
├── template
│ └── email.html
└── web
│ ├── 00280aae09f2a71c1ab46c7cfb9f491c.js
│ ├── 02703e133100c3be64cfec414d4db706.js
│ ├── 03276b6288c255cf1682f53ec11bb5a2.js
│ ├── 036680d9c1d332cf478c5823cd2a47db.js
│ ├── 0536af8c74f6fdf2d45e5e8990ee60cc.js
│ ├── 06d453ace473034cd357edb758d539ab.js
│ ├── 0768225f873adf5f103dcb714f17783d.js
│ ├── 07c0a60b390501dfbb57219d5c8fbc1a.js
│ ├── 07c26a67fe6aa27f701c6fb03a7bbafd.js
│ ├── 0870bcf868f8d64dc9a6226a6c8b341d.js
│ ├── 09195a75bcf8a7ac579281ac2ed5954a.js
│ ├── 0a4b12234fd7cba4d7c62207e4835f4c.js
│ ├── 0a5adf8110dfa37b8a75edf8cafb1dd7.js
│ ├── 0ab67a107deacf1d9b22eb0b706486db.js
│ ├── 0b56e82ae05b7ec2022e1cb35b8b6e10.js
│ ├── 0bd6d25a3183a767309cd45cd8b8f347.js
│ ├── 0c125a87d8efb9ce303b6b91783eb165.js
│ ├── 0c2b3b3b66a73e289e2ca47cf22ef150.js
│ ├── 0cab51dee983721ec757e7e209a67c1d.js
│ ├── 0cbaf3ecc6b20dbc83c2164e9a1eac02.js
│ ├── 0dc486b4415f7cbd7ddde8f32b6f12f1.js
│ ├── 0dd0f45c3dde9af3fcf9706e6a2a1edd.js
│ ├── 0e7164b2216605b024f4dc8d910ac5e8.js
│ ├── 0ebc6c9681e409f2bf3bb6d8ce64e28e.js
│ ├── 100f9b1846c1e1ecae19e0ca2fc8224c.js
│ ├── 1084edaced97872890c9d87a9944cdcd.js
│ ├── 10bc79414b62df132421027bbf5e5c3e.js
│ ├── 117389396b5ae8131c2a299bfc802c7a.js
│ ├── 119d8ff08e82b0f391f59f1fe657130f.js
│ ├── 1295d4470d348d3ff8ea442b1dcef3d3.js
│ ├── 1365ff3d277ebdab408e6aeec886cf08.js
│ ├── 13b157cfddcb9a76ae0800b47a8f0122.js
│ ├── 142d258626093a8c3187029538e32bbc.js
│ ├── 144991c48dbba89bfe10e886aaaed32a.js
│ ├── 155500be4d3113e94dca99f997defb7a.js
│ ├── 1570e695c448e6a4f3a6bdf0372b58f0.js
│ ├── 15abe309c5ecbc579dccc79beb041fd8.js
│ ├── 167a62ec377adafbeb4bbb1cef73250d.js
│ ├── 17c85759d562794da4d2ff11f1b9b3bd.js
│ ├── 1840080076c4078d157a5b05d0d95551.js
│ ├── 18a893070398343ab529fdb7b62f1b6d.js
│ ├── 19573d26f286762809b86f935516c1ac.js
│ ├── 19a2b55271f405d0b97fad53c9d5ec2d.js
│ ├── 1afbeca385b131cfc3ae515b89e552c7.js
│ ├── 1afe87852eca4b28294075c659ff8c45.js
│ ├── 1c9874850164cfdaa7e1d212d09124a7.js
│ ├── 1cb8df3a3416707163473b1ee9268faf.js
│ ├── 1d837e2c9de35cbb09a85208da4a0d8a.js
│ ├── 1e33cb44dfab039b4a7e88a3ee1bbfe7.js
│ ├── 1f03c9a69a8b9f79bcb7a338963f80c8.js
│ ├── 1f1abd5e247cf6b2e9a3db6303277572.js
│ ├── 2031467f3d02be43b638c5e3ccba3996.js
│ ├── 20642f73792092d3c71a4f1f4290430b.js
│ ├── 20f8061729d26f9786679bbf7af0b87a.js
│ ├── 214a729dcea91ee8a56f8ef43e17243a.js
│ ├── 21dca974f7343f200597e43a55766c6e.js
│ ├── 21fab653998af15bced8d4890e41bebc.js
│ ├── 2208705283adad817bb4a5af647f77ab.js
│ ├── 223593fe8dd78b83f22808f9aad86ae9.js
│ ├── 22812e27a1f54c0a4ff744a444a32d6c.js
│ ├── 22b1c8bf4c2bdd7e438f832b888c75e4.js
│ ├── 22d4f336d4fbe548273812e6e4cd345e.js
│ ├── 242fb5a92733d151e9ca303fcd3ae7ff.js
│ ├── 243d8101969c933d25388b5287bb3425.js
│ ├── 2487e54390024553d757b9bd73dd1647.js
│ ├── 2681042a598b029b51d51f7669b81c4d.js
│ ├── 280ba139ff95428f262adbf81b77aeb4.js
│ ├── 2839e845bd0cf60f35f3a8ca90a5ee22.js
│ ├── 28f7c5b28bbad7b0bac0cc3cc5b89bad.js
│ ├── 294fbc5b00264d6215dd8ff838dc2999.js
│ ├── 29a4e3548d286388c4d5e8f0670a4381.js
│ ├── 2a7b2ac7dc47105609001b93c25190b8.js
│ ├── 2ac58492ad5a1b5244deb0fef1e5a773.js
│ ├── 2bba99eb717e1aa22e45284a964ca73f.js
│ ├── 2dea096a03cd8f864db5f06e9f0113e5.js
│ ├── 2f6f1f6753d430190cb38411a9112f08.js
│ ├── 2fe13737434324ed67582ac97d484c54.js
│ ├── 30314e1b4a51b1aed3766eadecde2a42.js
│ ├── 3045404d52d03253c81822bdf760cfd1.js
│ ├── 30f5b57295dfda4eafc7f8c098160582.js
│ ├── 31459a657ac30dcaa54765c6d76d8c81.js
│ ├── 318f90759f2ff0d2a437350e87578172.js
│ ├── 31bcb02e59d84ce2e38b85616a0b44db.js
│ ├── 31f3f1c32b27587832d28b634351325c.js
│ ├── 330543be2120b9dcc9bec41ba5e05805.js
│ ├── 34f05dc84111ffe37a1d5b5aacff7488.js
│ ├── 35858a47038a7be957df49854e8e5eea.js
│ ├── 35dc4119f9e28cb9baba1475537460bb.js
│ ├── 37bc2ca46b9a9d40678a3cd05d50e397.js
│ ├── 37e37aa178d97ffcd94eeee1e1a25967.js
│ ├── 37f7ac1ef289fe8cd4f522a14df1f007.js
│ ├── 38528de2a5c097da375fd0a076667441.js
│ ├── 38a696bcfe6021b6442e70b6d3017b93.js
│ ├── 3a9544afd4e48fd7c2ad5839ea48beb6.js
│ ├── 3a969f15f742add3d383e55d0ceb3d25.js
│ ├── 3b5b61cdd5efaaa85816fbf4ac68207e.js
│ ├── 3baeab62d681338ba3287f0a50e5dad1.js
│ ├── 3c0ec12aff6e148d235875bfed4ca421.js
│ ├── 3c58f68d787710c79906a2cd6d248295.js
│ ├── 3cab7110c6a090f72c540dcc1cfbe3b5.js
│ ├── 3cce0c7e1a8e1148f97de59a4b1ee73f.js
│ ├── 3cd86defa6e36c165ae673afab6b5eab.js
│ ├── 3cf64ec91a700bfa1dece0957c49c7dc.js
│ ├── 3e6808cd6eefd1be1040403985581374.js
│ ├── 3e6cde7f6a3d84c5cff5127be1c019f3.js
│ ├── 3f9e3ae9d4ee540b9fb067b6fd29d529.js
│ ├── 400622a60e8e3194e3d666d073e3c7db.js
│ ├── 4037e6d4b18e3e286dec455cc63c1d17.js
│ ├── 40505d6c2f34fc08502d3e596573c7f8.js
│ ├── 40ba797ae7e4433f9847cd2c68bfbdf7.js
│ ├── 413ec783ae29da56e8bdabae45457f91.js
│ ├── 4190490a8257bdfcce6e2bd4f0634086.js
│ ├── 41f85ea0c545f0539b6ae2753eb1f79c.js
│ ├── 4263ed179f5b2268965e1157074583e8.js
│ ├── 42837f940cb1b7ef3aacf38a45916320.js
│ ├── 434a5902436fc0f4bac913f7ae1471c6.js
│ ├── 43a9bcfc200d80676bc68fe9a3c8ab6d.js
│ ├── 43bd62d6b50d1253f782c9ae5be1593d.js
│ ├── 43dab3876e6402fc9ae359a033683cc4.js
│ ├── 4474c9775d04684871043fae3501ec66.js
│ ├── 44b4462224957b51234691dacc5dd4c8.js
│ ├── 44e6d883ecccba28d8adf592cb83e01b.js
│ ├── 451c3753fb6dfc1f2de25cb7524f4bb2.js
│ ├── 46bac1e89f220258537c533035a6e263.js
│ ├── 4705b919138245a5b454d25f8e418435.js
│ ├── 4750f0ff62cbd59f35aac31b996194e6.js
│ ├── 476880245318ad211000fa55cb15d83f.js
│ ├── 47cd5c7d174e6b624e55510c4e503600.js
│ ├── 47ecd829f86e48857a05b2189ee9c097.js
│ ├── 4ab6dffb1b7255cc39ef77a35eb53293.js
│ ├── 4cbd6f8a4f52821c1d3476139078797d.js
│ ├── 4cf2f8563b2e07e643af9cc19cd44a2e.js
│ ├── 4d694d41a0c1b3eaad752a8352c5661c.js
│ ├── 4e4d407bd6bf0ce7bfc869f7eb6e93d3.js
│ ├── 4e9e0e943cacfdf9d350ba0c59bfb53b.js
│ ├── 4f0436f3850202d127036b38729c6861.js
│ ├── 4f96d1df55d7c479ed066be2863223c7.js
│ ├── 5094b30d2471cc7312746173d8a4bb25.js
│ ├── 51e6918f996813eafa4b1491d9dd343b.js
│ ├── 51e6ccd3ea9d7443949b155b113eebd5.js
│ ├── 52193d41677f370ad903b5437974afef.js
│ ├── 536bba7b10d156b509ec6516577ad3ce.js
│ ├── 540bba54b49ea7a6ec513270449132db.js
│ ├── 553aa6bb3b625428f4df57f5885d50f3.js
│ ├── 5540bb93f39dcb670a0f9b4e4b793d02.js
│ ├── 57c2d2eb6a844a8c9ecd932c6d4067b0.js
│ ├── 57c7c145c720f31f3749b658e3769833.js
│ ├── 587c674b536ffaf75df5db37c7b67c4a.js
│ ├── 58d885ab56201085ce55e8eb5d3f2ac2.js
│ ├── 59457eef0e0be735680874d74c13e469.js
│ ├── 5bd58f2ebad7e63ff72a891fb43e2b38.js
│ ├── 5ce9c9a26cf28c9ccdcf82388efacf29.js
│ ├── 5e1dbd63b493d399404d7d8d5b9e5934.js
│ ├── 5e4dd0452f14cf5dbb02a7dc7d9dda76.js
│ ├── 5e62ca244220154bbcae2a7eb2c50e0f.js
│ ├── 5e9314c1c0d4e5f4cb7a3f80fc01530c.js
│ ├── 5eeee1acc01b04328cf42db0715bb7f5.js
│ ├── 5f0b8714b08d299edbdf3b3d9adb7e71.js
│ ├── 5f6f5026d13b2a9b884a8144a119cf9e.js
│ ├── 60fc15a66fa7ba74ccd248f85b50fbe5.js
│ ├── 61cc56da80a76731283878abc3b13761.js
│ ├── 628b24103fca421515ec8724d12f026f.js
│ ├── 63999023068dcbebee417ac354fe4e78.js
│ ├── 63ccb1f1a27a2bf6271f40d3082186f4.js
│ ├── 642f5bce034554539cc93a5b965e730a.js
│ ├── 646c9322233a0ba128268dee916e5719.js
│ ├── 6477e8f75e2259e66e943bdef7b9e4a7.js
│ ├── 64a7727963416cd27ab100d1dfff8168.js
│ ├── 64f93b6b093bba4147485023263cf65f.js
│ ├── 66670f2c1f5e7c4e531007e89bb85355.js
│ ├── 666899335e954b291e938197a76bc90c.js
│ ├── 68cf9a0e1eaff7cc991e970a855108f8.js
│ ├── 697c2df91bf7c729d317c620a3cd77bd.js
│ ├── 6a42bdf71e3ae785252f124075145d08.js
│ ├── 6c6f2df70d907fa6b59b176f4d02dffd.js
│ ├── 6d9ca7a980db8fa74e39b1ff3b0c75cd.js
│ ├── 6dafd4eb9102ea47229a42a24d40f457.js
│ ├── 6e4d1075690c1f17775f02251592ac60.js
│ ├── 6e88d3943f4c3a068493aad131cd4898.js
│ ├── 6e9ca56e0fa3e784eab3da45f8d0d8ac.js
│ ├── 6f0543453c605ea6d673a3bd31dd1090.js
│ ├── 6f61a36cc8b4cd9472559c6f0c2374a0.js
│ ├── 6f783ca6efdcb90ccde9175312f6558d.js
│ ├── 7074e18e67a10875c827b6cfe2665b83.js
│ ├── 7150c52abe226d317116208cfe9fdc88.js
│ ├── 727184c92f9da8d8b0c013fd79cf32fe.js
│ ├── 72d23326220bc76ce06b4c1c68efb378.js
│ ├── 74973bbb728e661679e49a16773535a4.js
│ ├── 78999d905693a14a2c4677977ba222fb.js
│ ├── 79701bbf8c5436771916d9af708ae8ec.js
│ ├── 7982ae381c10e501e9a46d8693deddf6.js
│ ├── 7af5865535fb306e7d0364a9ff81f389.js
│ ├── 7bdb2e4d3bc51d15863aa7be6e0a23a9.js
│ ├── 7cef38946c33fa981d6d2c86c62428e0.js
│ ├── 7d46cd8e5efaac33d5bf823ed4268841.js
│ ├── 7d4e1c98726f11ff7baaf1a31882c59f.js
│ ├── 7da5aafe24e626f9bced82fe40567386.js
│ ├── 7e89c064ec09f955a6c3ffbfb96908a2.js
│ ├── 7e98c4d98664d6f7bcc52a07f21a1f9f.js
│ ├── 7f10fe526aec57bd522af77ea6ac2b62.js
│ ├── 7f63b670b51e07bd9a30869b68ada191.js
│ ├── 7f97ea63879ac5f3a2b491a651a1a82f.js
│ ├── 8043595ccf704fc61e7e3e4c7c7e77a5.js
│ ├── 806bfd960245b1da40a7e1057a076289.js
│ ├── 8103e73d2ea3574b81428aafc4e01c71.js
│ ├── 8120c57dbca7501da3ecf702c811f16f.js
│ ├── 817d52a47a4657b8a4dab79e057f5fb0.js
│ ├── 81be1aff3c1cfa0531037ebab355abbb.js
│ ├── 82ce99851e7fc39e91603bc3320fe6d2.js
│ ├── 833b242747fd7b098d46011e4289bc3f.js
│ ├── 83a1ba72f83e644dc4fbbc0d48501061.js
│ ├── 83ea78d42f1a8e5f7346f3a30140ebfb.js
│ ├── 8468b2aa5fbe665b49784c30b4a908f7.js
│ ├── 84d3403e422e4697e86914f183a60a13.js
│ ├── 84f75bf9ddb5400925d2a043a2013cec.js
│ ├── 852f3a4ec9ee58d75bd55c85161bb68f.js
│ ├── 8536514f6ace9c40d36020af05e067fe.js
│ ├── 85e246a36ca53e3f767608542dcd26b3.js
│ ├── 85f71b723441bcf428b8abed1fc8f56f.js
│ ├── 85fe85850b026b668c10d2c9e0e5e8c6.js
│ ├── 867fb2b26eef123915aff8634c0bbf4a.js
│ ├── 8681f562786fa45bebe8ee7ed2461026.js
│ ├── 86dfc095a8bb97b2b6d94b798ebcdc61.js
│ ├── 8833a126ef9d8892bfb372d227f7f088.js
│ ├── 8870430db332faf22d90e12f1620ee84.js
│ ├── 88d5efab68c7526ad2ad4196932adb03.js
│ ├── 88f2b86b79781364b99947d07d3c3469.js
│ ├── 89392e9dbbec39477b4b3e52a0676422.js
│ ├── 89859a411a50c90f1e669deaf8a6775f.js
│ ├── 89a47a0051ac0b3885ef8af2476526f0.js
│ ├── 8a7d1e82245ba58033df533faadfbaf4.js
│ ├── 8afcf3a037a7f37f9c0bbad01507d73b.js
│ ├── 8bdbab2f0d58195a7d509ad6fbe02966.js
│ ├── 8dec848a9d34e3804976ae4a589fbc4f.js
│ ├── 8e6a809082edab0aaf90b9eb118ae571.js
│ ├── 8e81f51d2e7be98e9e45fe93239c7e99.js
│ ├── 8ee6948d963e299de55144b3c7a60c0a.js
│ ├── 8f69fc81a83ba318eca7dbae6c6eba75.js
│ ├── 90643b9da87302fef490f3f48af806e2.js
│ ├── 908119c25a234151c8c7c1a97005c866.js
│ ├── 91832748c8f066b07af2341ccc6dd5b1.js
│ ├── 92cf63e9a949f08d97a74d9ed17392ed.js
│ ├── 9360974ffacadb05145e2f6c1458f35b.js
│ ├── 93edcad7b93942b98afaab6436a13d10.js
│ ├── 94a0179602c94d55621a35e41c97ed5c.js
│ ├── 94a5c40baab0f2df8b43889ed5fb6b8a.js
│ ├── 9588381016bdc5e88634572e630b4551.js
│ ├── 983ddc3115fae8e0dfd108d799662892.js
│ ├── 985b400088bf5e23fb83e70d9948eccb.js
│ ├── 998c5f13555e18b42e9bf826578b2e16.js
│ ├── 99b756405f919e9022e6a4e3579dd5ee.js
│ ├── 99f6bcba35fb277563c6362f3caab715.js
│ ├── 9abcc804fa38b6d05e62a10cb8dbb668.js
│ ├── 9c202aefac35a5ff49d3d3795e9932bc.js
│ ├── 9cf3be7669b89ac4036cd07c9baf7e13.js
│ ├── 9d0f4f65be2f50ad54488089f126feda.js
│ ├── 9e357a97da26127713394684a51946b8.js
│ ├── 9e69cb39701c3578226b39536edd4dd7.js
│ ├── 9e875d25eb6d80340adac0cfc35700c1.js
│ ├── a026164ca1f6f157fcb0f5f6bfd4abce.js
│ ├── a06ea1f6e485f67413d6cb34d7cc3515.js
│ ├── a07f2b025030bd4f277803aea0e6a539.js
│ ├── a26463d029a2515171748a1ebcca53c3.js
│ ├── a311e02008e0f00a37305a12d479159a.js
│ ├── a33f52a5f1ea0162305f99d63235f807.js
│ ├── a477d7b35783dd10040a243a84c86a0c.js
│ ├── a5cb31cfb4711ef14999198f0d35eaf3.js
│ ├── a5cd4d965591278c0519bdfa761ea3aa.js
│ ├── a65a0bae3e5b73407d15ea6bbb08e515.js
│ ├── a71d8ecb9a2a4b35fcd828bb970e7e84.js
│ ├── a84f565fc5473f112281550ea6c2ccf4.js
│ ├── aa2f98073a8d9f266f3928b5d9c457d1.js
│ ├── ab16c1237e6e04bbf0024ee2bae42130.js
│ ├── acc30207efba7ab5b7b509b599f37e6f.js
│ ├── acc4ded8b9debce27f884c9cce5bf63c.js
│ ├── acc7448b80728a73c9a4046b3ec4407f.js
│ ├── adbb57fa182dce548204311d3be6dffa.js
│ ├── ae5d4d6eea08ccfac67e44bfe11da4ed.js
│ ├── b02513e1d0cc664936e1ba9cb5a923af.js
│ ├── b0fc54e0e936c84253a30c9b39cfd9bf.js
│ ├── b111a00f8f22708140c6fdbc26963155.js
│ ├── b131314d1ea62fa7bba91a4da8360298.js
│ ├── b1ff2cb4863b8ed961d815393cfe246d.js
│ ├── b225cb9e753bd0a8ca508ccb2637bf91.js
│ ├── b25d5064a26eda70aa3d2bae3a1122cc.js
│ ├── b26738d581e044c69f7a4392906e6843.js
│ ├── b2a2011665f9a22c8dddaf833ec822b8.js
│ ├── b435aebcb57d65080cfd510e0a9d5d9d.js
│ ├── b4787b2bbb3e2481e0aca0830ab31484.js
│ ├── b49c9a9ab619e46a7ba6f9f89c800589.js
│ ├── b4bd28ac3a7935d0c52a6cb19c89aced.js
│ ├── b518725b1ee5b4ba27eec173687966f0.js
│ ├── b830d88aa22a866a208be27af90526a7.js
│ ├── ba07c8c1ca6ea903fd0f0379db66ea1e.js
│ ├── bae95bdb1bbcc0969e0e40fb72539df3.js
│ ├── bb3e0098a11d21ca01d6e44c2e39f90b.js
│ ├── bb48e1051c32d32d425681e9200706bc.js
│ ├── bb9282d93d3ae9d53870a66627f8c797.js
│ ├── bbd62124f6d03e01eb4332f55ead999d.js
│ ├── bc26ab0797e975ba01e701683935864b.js
│ ├── bd33197d8c34bf6387e39130c28f8342.js
│ ├── bd98610e395f3b4c7915cf3fbe854f6f.js
│ ├── bd9ff502ba460f402b4e2005689402a7.js
│ ├── be2fbe775b19bdc18e4f78de18beb433.js
│ ├── be734ac9c9a7b29439001bfc78984ba3.js
│ ├── bf06f353bf67ef497b65afe567e7f294.js
│ ├── bffad0f26b7a14d73f338aefa2d2f9e5.js
│ ├── c02d976c2c838a2b5ad0e5dfd1facb75.js
│ ├── c033d0cf791d80ef14327c1ade637578.js
│ ├── c0b4241b59cd6750a7d6ad4f3d019d84.js
│ ├── c0b4cd50c3fcc1292b34cedf813a16dd.js
│ ├── c0f91d067bd4f665ec7b85a632e3168d.js
│ ├── c23b1f80ab9746b425f3848bdaacc144.js
│ ├── c24de6963d7d00c269db34091059e06d.js
│ ├── c2b469d0ddb280bda5f621563579725d.js
│ ├── c2c0e5fa8323e2c5c1f54f20afda51b8.js
│ ├── c38a3226f3858a47ba9fb788dc7b44fc.js
│ ├── c3b0cd15adcc12a549e7ac5d165ac1f4.js
│ ├── c502e0f58557345fbd8e157a93dc4d43.js
│ ├── c5d7c4a345a7bb4c84ee8ced7322a8db.js
│ ├── c6d4a590e14107a8a5ad505d66241032.js
│ ├── c6f608398c43e25821557ee65cda5e58.js
│ ├── c755e7fc08446566ee8dd3a8aa8fe43f.js
│ ├── c797cd030330cde3e9c0f5e9db6b2be5.js
│ ├── c7d3b0afe7600a632fbf44ee8d84996e.js
│ ├── c7fb0ccebacccfb5c2f7b2f6023ebe4a.js
│ ├── c806ba4f0026195e7907bfb62d00b502.js
│ ├── c8bdb139ff462c0e7dc4ba2f56a49318.js
│ ├── c8c48c73e7d7dd2c142badc913ab26fe.js
│ ├── c98e5722b508d4eb3afcea637246de33.js
│ ├── ca1483809659f6c87cc6f588891d2bd4.js
│ ├── cb332e7b5386c55fe0ced93b36d73da7.js
│ ├── ce73c3243f61524d76000c4ace94f2bb.js
│ ├── cf0a04afa21ac9ba23a1de0416a03105.js
│ ├── cf1f6c842a1ec0af6b00ce1859dce6d5.js
│ ├── css.worker.js
│ ├── css
│ ├── app.2a1944af.css
│ ├── chunk-0279f58f.f040dd0a.css
│ ├── chunk-05a99c67.b1dd7a76.css
│ ├── chunk-24a54a1d.03727b70.css
│ ├── chunk-39b1e937.e5d373cf.css
│ ├── chunk-6260e53b.bcae8e8e.css
│ ├── chunk-88ab404a.8ffb2425.css
│ ├── chunk-fb24efc2.3de04029.css
│ └── chunk-libs.77b8d5d9.css
│ ├── d08030a8f6057b63643bacf4cee162b0.js
│ ├── d08daa8e673c585e1311729dbcb63eb4.js
│ ├── d27d5c5480c14bffe9ffc07fec3a806d.js
│ ├── d2b533a0128ef6edfaf153c0fa19e432.js
│ ├── d2e30554e6939a2542e5135fff541daa.js
│ ├── d465c0a35c6ef244bf587b0e6bdb4019.js
│ ├── d47938906a471dea833a3b57991c7124.js
│ ├── d5a596705e8b1c50832d29b25f4ffb0a.js
│ ├── d70ab0885fcc546aaf5eee0c5fca6278.js
│ ├── d750a8dbf9dd09c0a33b9986e79e3c8c.js
│ ├── d754905fe54aac6f3c350df34f51a0b6.js
│ ├── d7889907dbb51f58ceadb3e1eec03a5d.js
│ ├── d7cdf8e31755f70cd564c742feec3be0.js
│ ├── d7e8066668f05d83f86a128d7dbd45a2.js
│ ├── d7f9c3bcea90f112bc7cac6559dcb00c.js
│ ├── d8c239d65159c02ebd6a2afa3cdc584b.js
│ ├── d9a00ccd64f554cd458b3d6f6c66f465.js
│ ├── d9e70caae42a8f91d34536f0d7941673.js
│ ├── da06d4429e8bccd9ef90b16ebe49354b.js
│ ├── da1719655627488c0c1afaa1379e2c1d.js
│ ├── dad7909925cdea4ce193d5c14a13abf3.js
│ ├── db7eff370e6f80152653db4bc1c65285.js
│ ├── dcb084d6aacfa517923dd3a94e3b9af5.js
│ ├── dcf82c5c24de859d74953010a3bf7f11.js
│ ├── dcf8b9b721cab79d285ab33fe2154a58.js
│ ├── dd40dfc7840568927fdef65087a233ed.js
│ ├── dde12e6c2c05d17c95ed0a94da234b3b.js
│ ├── de385e48e4b7a8c5837c9a2fd07ede3e.js
│ ├── de581fe10be3ac282fa6abc2f8171551.js
│ ├── e0476257d7657264e527f7a1f1ecbece.js
│ ├── e0e2b1267a5d4acb4dda3a4a598cd8a5.js
│ ├── e1dbe800b2d3f5d74b2b5480ea2b897a.js
│ ├── e2792218bae78a6aef6764de4e61fd82.js
│ ├── e393bf5358fc198ca07e518900b24311.js
│ ├── e4d51c8b4202d444cb39db4e7642d7d9.js
│ ├── e6c2b11f457b5aa71fd08de4ae738c3f.js
│ ├── e6fe37aef08c1bd39b8fc610216b5228.js
│ ├── e745f8fb4f054a3f5b66ccad100a1217.js
│ ├── e7a892eff1dd4ac60e8201386497b66b.js
│ ├── e8250271e7641960341ae2ac170af4ac.js
│ ├── ea5c101c16108be8cf1522aae5736f5f.js
│ ├── eb6f00b565c6441d02346354a0ef64ce.js
│ ├── editor.worker.js
│ ├── ef2640638453d7df3e7e1659d1f67105.js
│ ├── efa2aae8c65855514b0ca66c4fe1cc68.js
│ ├── efc508c36f4e417ec6bd5ec72989443b.js
│ ├── f023b7e5335b8e16fb42f8f3e18ecf3f.js
│ ├── f102c542cd35eef623ab82b087af2f14.js
│ ├── f120c3f4e008f9abcd3a576bd66dd315.js
│ ├── f2040b70e41cfa457e9796aca8abfeea.js
│ ├── f2195d2eae3dbef7e3798e115209dcd7.js
│ ├── f29286fc7d5663eb11457f48664f324d.js
│ ├── f2cfc0e604350e23bfcd7c78165b1411.js
│ ├── f35e34e60520cef0b0dbba2bc2931941.js
│ ├── f3a0f6e7e442de2ae51eddbf4eb98d97.js
│ ├── f3b6993cd8f9bbdd1d5ad68a5e1cdf70.js
│ ├── f457edce8a9809fa16aab3c8e695bf38.js
│ ├── f473db7186a8dd6d4526d55c4d7ed873.js
│ ├── f4b747bf296f21fcf6d59357e92f948d.js
│ ├── f4ee92824c023ab7278694588c9c40f1.js
│ ├── f50d7c4ce743ce495230d19bd33fefab.js
│ ├── f5292be525fc36a337ce7bfb792070de.js
│ ├── f52e2798c3b260592cf35f3a20958d87.js
│ ├── f61f1aaed3f32a7dabd977a6f47ecd5f.js
│ ├── f6cfc0e0566a350632db32ece39b649d.js
│ ├── f7443e8232a7e4289b9f2ed4a512750c.js
│ ├── f7b04f07406ef16d88688a7ffb81ce3f.js
│ ├── f80c6eb0f52a68464b21211240e3d6e6.js
│ ├── f88127ad8950e3c94c3af6c65a7120fa.js
│ ├── f913332fa21973f354fcb5b680811e56.js
│ ├── f95dc04dc50d90d0555ca3561e75c4c2.js
│ ├── fa1618cda4da7d5362c381ea2d5f7321.js
│ ├── faf460076b3383fdc3ecc224068964cf.js
│ ├── favicon.ico
│ ├── fb4580529d9585e912b7142f6b62cae4.js
│ ├── fe4de7aeda3abed04c238956a8565de4.js
│ ├── fe51d45583c0425b00c9a784727072e0.js
│ ├── fe56e099960b1f5a3ac7143e245f7ce1.js
│ ├── fe58209a4ef163863b95ab289a69cdaf.js
│ ├── fe5fd32b764aa22fde63925ac549a9c9.js
│ ├── fffbc895129cdb3efeafa5b234743aa0.js
│ ├── fonts
│ ├── eiconfont.016bbe3f.woff
│ ├── eiconfont.0ff67604.ttf
│ ├── eiconfont.ae6bc167.eot
│ ├── element-icons.535877f5.woff
│ ├── element-icons.732389de.ttf
│ ├── fontawesome-webfont.674f50d2.eot
│ ├── fontawesome-webfont.af7ae505.woff2
│ ├── fontawesome-webfont.b06871f2.ttf
│ ├── fontawesome-webfont.fee66e71.woff
│ ├── iconfont.34ea3475.34ea3475.woff
│ ├── iconfont.34ea3475.woff
│ ├── iconfont.4d5a9051.4d5a9051.ttf
│ ├── iconfont.4d5a9051.ttf
│ ├── iconfont.8efbc988.8efbc988.eot
│ └── iconfont.8efbc988.eot
│ ├── html.worker.js
│ ├── img
│ ├── 401.089007e7.gif
│ ├── 404.a57b6f31.png
│ ├── 404_cloud.0f4bc32b.png
│ ├── eiconfont.30cb46e7.svg
│ ├── end.9687f898.svg
│ ├── exclusive-gateway.56b82dfd.svg
│ ├── fontawesome-webfont.912ec66d.svg
│ ├── icon_java.d3cc233a.svg
│ ├── icon_mail.0f68d5c7.svg
│ ├── icon_message.01031aed.svg
│ ├── icon_receive.a6c46918.svg
│ ├── icon_script.07c7423e.svg
│ ├── icon_signal.0e96b3b6.svg
│ ├── icon_timer.b4fcbba6.svg
│ ├── icon_user.2b39cf22.svg
│ ├── iconfont.6c66fc36.svg
│ ├── iconfont.f0e930ef.f0e930ef.svg
│ ├── iconfont.f0e930ef.svg
│ ├── login.ede1cdb8.png
│ ├── parallel-gateway.dfb4ebaf.svg
│ ├── receive-task.e1131038.svg
│ ├── start.894f1842.svg
│ └── user-task.90bd34cf.svg
│ ├── index.html
│ ├── js
│ ├── app.9311df7b.js
│ ├── chunk-0279f58f.1f192749.js
│ ├── chunk-05a99c67.cfbcb6c6.js
│ ├── chunk-192165dd.25e2ffe9.js
│ ├── chunk-24a54a1d.eeaaeb1b.js
│ ├── chunk-292427cd.49f63400.js
│ ├── chunk-2d0e2366.359919a5.js
│ ├── chunk-2d2105d3.b54ad484.js
│ ├── chunk-2d230fe7.19def69d.js
│ ├── chunk-39b1e937.3a2314ea.js
│ ├── chunk-4f5f604e.cf35faa9.js
│ ├── chunk-50a983d1.babc8539.js
│ ├── chunk-6260e53b.51269640.js
│ ├── chunk-748b566e.2d85de49.js
│ ├── chunk-88ab404a.4ce530b5.js
│ ├── chunk-cff79be6.1d9c70c2.js
│ ├── chunk-elementUI.749da353.js
│ ├── chunk-fb24efc2.cba6adf3.js
│ └── chunk-libs.c758eded.js
│ ├── json.worker.js
│ └── ts.worker.js
├── template
├── api.go.template
├── js.go.template
├── model.go.template
├── router.go.template
├── vue.go.template
└── web
│ └── index.html
├── test
├── api.go.template
└── model.go.template
└── tools
├── app
├── model.go
├── msg
│ └── message.go
└── return.go
├── captcha
└── captcha.go
├── config
├── application.go
├── config.go
├── database.go
├── jwt.go
└── ssl.go
├── env.go
├── float64.go
├── int.go
├── int64.go
├── ip.go
├── string.go
├── url.go
├── user.go
└── utils.go
/.air.conf:
--------------------------------------------------------------------------------
1 | # Config file for [Air](https://github.com/cosmtrek/air) in TOML format
2 |
3 | # Working directory
4 | # . or absolute path, please note that the directories following must be under root.
5 | root = "."
6 | tmp_dir = "tmp"
7 |
8 | [build]
9 | # Just plain old shell command. You could use `make` as well.
10 | cmd = "go build -o ./tmp/main ."
11 | # Binary file yields from `cmd`.
12 | bin = "tmp/main"
13 | # Customize binary.
14 | # full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
15 | full_bin = "./tmp/main server -c=config/settings.dev.yml"
16 | # Watch these filename extensions.
17 | include_ext = ["go", "tpl", "tmpl", "html"]
18 | # Ignore these filename extensions or directories.
19 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
20 | # Watch these directories if you specified.
21 | include_dir = []
22 | # Exclude files.
23 | exclude_file = []
24 | # This log file places in your tmp_dir.
25 | log = "./tmp/air.log"
26 | # It's not necessary to trigger build each time file changes if it's too frequent.
27 | delay = 1000 # ms
28 | # Stop running old binary when build errors occur.
29 | stop_on_error = true
30 | # Send Interrupt signal before killing process (windows does not support this feature)
31 | send_interrupt = false
32 | # Delay after sending Interrupt signal
33 | kill_delay = 500 # ms
34 |
35 | [log]
36 | # Show log time
37 | time = false
38 |
39 | [color]
40 | # Customize each part's color. If no color found, use the raw app log.
41 | main = "magenta"
42 | watcher = "cyan"
43 | build = "yellow"
44 | runner = "green"
45 |
46 | [misc]
47 | # Delete tmp directory on exit
48 | clean_on_exit = true
49 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 |
11 | build:
12 | name: Build
13 | runs-on: ubuntu-latest
14 | steps:
15 |
16 | - name: Set up Go 1.13
17 | uses: actions/setup-go@v1
18 | with:
19 | go-version: 1.13
20 | id: go
21 |
22 | - name: Check out code into the Go module directory
23 | uses: actions/checkout@v2
24 |
25 | - name: Get dependencies
26 | run: |
27 | go get -v -t -d ./...
28 | if [ -f Gopkg.toml ]; then
29 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
30 | dep ensure
31 | fi
32 |
33 | - name: Build
34 | run: go build -v .
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | static/uploadfile
3 | ferry
4 | temp/
5 | !temp
6 | vendor
7 | tmp/
8 | config/settings.dev.yml
9 | logs
10 | mysql/data
11 | redis/data
12 | data/
13 | needinit
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 lanyulei
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PROJECT:=ferry
2 |
3 | .PHONY: build
4 | build:
5 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ferry main.go && upx -9 ferry
6 | build-sqlite:
7 | go build -tags sqlite3 -o ferry main.go
8 | #.PHONY: test
9 | #test:
10 | # go test -v ./... -cover
11 |
12 | #.PHONY: docker
13 | #docker:
14 | # docker build . -t ferry:latest
15 |
--------------------------------------------------------------------------------
/apis/monitor/server.go:
--------------------------------------------------------------------------------
1 | package monitor
2 |
3 | import (
4 | "ferry/tools/app"
5 | "runtime"
6 |
7 | "github.com/gin-gonic/gin"
8 | "github.com/shirou/gopsutil/cpu"
9 | "github.com/shirou/gopsutil/disk"
10 | "github.com/shirou/gopsutil/mem"
11 | )
12 |
13 | const (
14 | B = 1
15 | KB = 1024 * B
16 | MB = 1024 * KB
17 | GB = 1024 * MB
18 | )
19 |
20 | func ServerInfo(c *gin.Context) {
21 |
22 | osDic := make(map[string]interface{}, 0)
23 | osDic["goOs"] = runtime.GOOS
24 | osDic["arch"] = runtime.GOARCH
25 | osDic["mem"] = runtime.MemProfileRate
26 | osDic["compiler"] = runtime.Compiler
27 | osDic["version"] = runtime.Version()
28 | osDic["numGoroutine"] = runtime.NumGoroutine()
29 |
30 | dis, _ := disk.Usage("/")
31 | diskTotalGB := int(dis.Total) / GB
32 | diskFreeGB := int(dis.Free) / GB
33 | diskDic := make(map[string]interface{}, 0)
34 | diskDic["total"] = diskTotalGB
35 | diskDic["free"] = diskFreeGB
36 |
37 | mem, _ := mem.VirtualMemory()
38 | memUsedMB := int(mem.Used) / GB
39 | memTotalMB := int(mem.Total) / GB
40 | memFreeMB := int(mem.Free) / GB
41 | memUsedPercent := int(mem.UsedPercent)
42 | memDic := make(map[string]interface{}, 0)
43 | memDic["total"] = memTotalMB
44 | memDic["used"] = memUsedMB
45 | memDic["free"] = memFreeMB
46 | memDic["usage"] = memUsedPercent
47 |
48 | cpuDic := make(map[string]interface{}, 0)
49 | cpuDic["cpuNum"], _ = cpu.Counts(false)
50 |
51 | app.Custum(c, gin.H{
52 | "code": 200,
53 | "os": osDic,
54 | "mem": memDic,
55 | "cpu": cpuDic,
56 | "disk": diskDic,
57 | })
58 | }
59 |
--------------------------------------------------------------------------------
/apis/system/captcha.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/tools/app"
5 | "ferry/tools/captcha"
6 | "fmt"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | func GenerateCaptchaHandler(c *gin.Context) {
16 | id, b64s, _, err := captcha.DriverDigitFunc()
17 | if err != nil {
18 | app.Error(c, -1, err, fmt.Sprintf("验证码获取失败, %v", err.Error()))
19 | return
20 | }
21 | app.Custum(c, gin.H{
22 | "code": 200,
23 | "data": b64s,
24 | "id": id,
25 | "msg": "success",
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/apis/system/index.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | */
10 |
11 | const INDEX = `
12 |
13 |
14 |
15 |
16 | ferry欢迎您
17 |
24 |
25 |
33 |
34 |
35 |
36 |
37 |
38 | `
39 |
40 | func HelloWorld(c *gin.Context) {
41 | c.Header("Content-Type", "text/html; charset=utf-8")
42 | c.String(200, INDEX)
43 | }
44 |
--------------------------------------------------------------------------------
/apis/system/info.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/models/system"
5 | "ferry/tools"
6 | "ferry/tools/app"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | func GetInfo(c *gin.Context) {
16 |
17 | var roles = make([]string, 1)
18 | roles[0] = tools.GetRoleName(c)
19 |
20 | var permissions = make([]string, 1)
21 | permissions[0] = "*:*:*"
22 |
23 | var buttons = make([]string, 1)
24 | buttons[0] = "*:*:*"
25 |
26 | RoleMenu := system.RoleMenu{}
27 | RoleMenu.RoleId = tools.GetRoleId(c)
28 |
29 | var mp = make(map[string]interface{})
30 | mp["roles"] = roles
31 | if tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员" {
32 | mp["permissions"] = permissions
33 | mp["buttons"] = buttons
34 | } else {
35 | list, _ := RoleMenu.GetPermis()
36 | mp["permissions"] = list
37 | mp["buttons"] = list
38 | }
39 |
40 | sysuser := system.SysUser{}
41 | sysuser.UserId = tools.GetUserId(c)
42 | user, err := sysuser.Get()
43 | if err != nil {
44 | app.Error(c, -1, err, "")
45 | return
46 | }
47 |
48 | mp["introduction"] = " am a super administrator"
49 |
50 | mp["avatar"] = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"
51 | if user.Avatar != "" {
52 | mp["avatar"] = user.Avatar
53 | }
54 | mp["userName"] = user.NickName
55 | mp["userId"] = user.UserId
56 | mp["deptId"] = user.DeptId
57 | mp["name"] = user.NickName
58 |
59 | app.OK(c, mp, "")
60 | }
61 |
--------------------------------------------------------------------------------
/apis/system/rolemenu.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/models/system"
5 | "ferry/tools/app"
6 | "net/http"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | // @Summary RoleMenu列表数据
16 | // @Description 获取JSON
17 | // @Tags 角色菜单
18 | // @Param RoleId query string false "RoleId"
19 | // @Success 200 {string} string "{"code": 200, "data": [...]}"
20 | // @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
21 | // @Router /api/v1/rolemenu [get]
22 | // @Security Bearer
23 | func GetRoleMenu(c *gin.Context) {
24 | var (
25 | res app.Response
26 | Rm system.RoleMenu
27 | )
28 | _ = c.ShouldBind(&Rm)
29 | result, err := Rm.Get()
30 | if err != nil {
31 | app.Error(c, -1, err, "")
32 | return
33 | }
34 | res.Data = result
35 | c.JSON(http.StatusOK, res.ReturnOK())
36 | }
37 |
38 | type RoleMenuPost struct {
39 | RoleId string
40 | RoleMenu []system.RoleMenu
41 | }
42 |
43 | func InsertRoleMenu(c *gin.Context) {
44 |
45 | var res app.Response
46 | res.Msg = "添加成功"
47 | c.JSON(http.StatusOK, res.ReturnOK())
48 | }
49 |
50 | // @Summary 删除用户菜单数据
51 | // @Description 删除数据
52 | // @Tags 角色菜单
53 | // @Param id path string true "id"
54 | // @Param menu_id query string false "menu_id"
55 | // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
56 | // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
57 | // @Router /api/v1/rolemenu/{id} [delete]
58 | func DeleteRoleMenu(c *gin.Context) {
59 | var t system.RoleMenu
60 | id := c.Param("id")
61 | menuId := c.Request.FormValue("menu_id")
62 | _, err := t.Delete(id, menuId)
63 | if err != nil {
64 | app.Error(c, -1, err, "")
65 | return
66 | }
67 | var res app.Response
68 | res.Msg = "删除成功"
69 | c.JSON(http.StatusOK, res.ReturnOK())
70 | }
71 |
--------------------------------------------------------------------------------
/apis/system/settings.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/global/orm"
5 | "ferry/models/system"
6 | "ferry/tools/app"
7 | "fmt"
8 |
9 | "github.com/gin-gonic/gin"
10 | )
11 |
12 | /*
13 | @Author : lanyulei
14 | */
15 |
16 | // 设置系统信息
17 | func GetSettingsInfo(c *gin.Context) {
18 | var (
19 | err error
20 | settingsInfo []*system.Settings
21 | classify string
22 | )
23 | db := orm.Eloquent.Model(&settingsInfo)
24 | classify = c.DefaultQuery("classify", "")
25 | if classify != "" {
26 | db = db.Where("classify = ?", classify)
27 | }
28 |
29 | err = db.Find(&settingsInfo).Error
30 | if err != nil {
31 | app.Error(c, -1, fmt.Errorf("查询数据失败,%v", err.Error()), "")
32 | return
33 | }
34 |
35 | app.OK(c, settingsInfo, "查询配置信息成功")
36 | }
37 |
38 | // 设置系统信息
39 | func SetSettingsInfo(c *gin.Context) {
40 | var (
41 | err error
42 | settingsInfo system.Settings
43 | settingsCount int
44 | )
45 |
46 | err = c.ShouldBind(&settingsInfo)
47 | if err != nil {
48 | app.Error(c, -1, fmt.Errorf("绑定数据失败,%v", err.Error()), "")
49 | return
50 | }
51 |
52 | // 查询数据是否存在
53 | err = orm.Eloquent.Model(&system.Settings{}).
54 | Where("classify = ?", settingsInfo.Classify).
55 | Count(&settingsCount).Error
56 | if err != nil {
57 | app.Error(c, -1, fmt.Errorf("查询数据失败,%v", err.Error()), "")
58 | return
59 | }
60 | if settingsCount == 0 {
61 | // 创建新的配置信息
62 | err = orm.Eloquent.Create(&settingsInfo).Error
63 | if err != nil {
64 | app.Error(c, -1, fmt.Errorf("创建配置信息失败,%v", err.Error()), "")
65 | return
66 | }
67 | } else {
68 | err = orm.Eloquent.Model(&settingsInfo).
69 | Where("classify = ?", settingsInfo.Classify).
70 | Updates(&settingsInfo).Error
71 | if err != nil {
72 | app.Error(c, -1, fmt.Errorf("更新配置信息失败,%v", err.Error()), "")
73 | return
74 | }
75 | }
76 |
77 | app.OK(c, "", "配置信息设置成功")
78 | }
79 |
--------------------------------------------------------------------------------
/apis/tpl/tpl.go:
--------------------------------------------------------------------------------
1 | package tpl
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | /*
10 | @Author : lanyulei
11 | */
12 |
13 | func Tpl(c *gin.Context) {
14 | c.HTML(http.StatusOK, "index.html", gin.H{})
15 | }
16 |
--------------------------------------------------------------------------------
/cmd/cobra.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "errors"
5 | "ferry/cmd/api"
6 | "ferry/cmd/migrate"
7 | "ferry/pkg/logger"
8 | "os"
9 |
10 | "github.com/spf13/cobra"
11 | )
12 |
13 | var rootCmd = &cobra.Command{
14 | Use: "ferry",
15 | Short: "-v",
16 | SilenceUsage: true,
17 | DisableAutoGenTag: true,
18 | Long: `ferry`,
19 | Args: func(cmd *cobra.Command, args []string) error {
20 | if len(args) < 1 {
21 | return errors.New("requires at least one arg")
22 | }
23 | return nil
24 | },
25 | PersistentPreRunE: func(*cobra.Command, []string) error { return nil },
26 | Run: func(cmd *cobra.Command, args []string) {
27 | usageStr := `欢迎使用 ferry,可以使用 -h 查看命令`
28 | logger.Infof("%s\n", usageStr)
29 | },
30 | }
31 |
32 | func init() {
33 | rootCmd.AddCommand(api.StartCmd)
34 | rootCmd.AddCommand(migrate.StartCmd)
35 | }
36 |
37 | //Execute : apply commands
38 | func Execute() {
39 | if err := rootCmd.Execute(); err != nil {
40 | os.Exit(-1)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/cmd/migrate/server.go:
--------------------------------------------------------------------------------
1 | package migrate
2 |
3 | import (
4 | "ferry/database"
5 | "ferry/global/orm"
6 | "ferry/models/gorm"
7 | "ferry/models/system"
8 | "ferry/pkg/logger"
9 | config2 "ferry/tools/config"
10 | "fmt"
11 |
12 | "github.com/spf13/cobra"
13 | )
14 |
15 | var (
16 | config string
17 | mode string
18 | StartCmd = &cobra.Command{
19 | Use: "init",
20 | Short: "initialize the database",
21 | Run: func(cmd *cobra.Command, args []string) {
22 | run()
23 | },
24 | }
25 | )
26 |
27 | func init() {
28 | StartCmd.PersistentFlags().StringVarP(&config, "config", "c", "config/settings.yml", "Start server with provided configuration file")
29 | StartCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "dev", "server mode ; eg:dev,test,prod")
30 | }
31 |
32 | func run() {
33 | usage := `start init`
34 | fmt.Println(usage)
35 | //1. 读取配置
36 | config2.ConfigSetup(config)
37 | //2. 初始化数据库链接
38 | database.Setup()
39 | //3. 数据库迁移
40 | _ = migrateModel()
41 | logger.Info("数据库结构初始化成功!")
42 | //4. 数据初始化完成
43 | if err := system.InitDb(); err != nil {
44 | logger.Fatalf("数据库基础数据初始化失败,%v", err)
45 | }
46 |
47 | usage = `数据库基础数据初始化成功`
48 | fmt.Println(usage)
49 | }
50 |
51 | func migrateModel() error {
52 | if config2.DatabaseConfig.Dbtype == "mysql" {
53 | orm.Eloquent = orm.Eloquent.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4")
54 | }
55 | return gorm.AutoMigrate(orm.Eloquent)
56 | }
57 |
--------------------------------------------------------------------------------
/config/rbac_model.conf:
--------------------------------------------------------------------------------
1 | [request_definition]
2 | r = sub, obj, act
3 |
4 | [policy_definition]
5 | p = sub, obj, act
6 |
7 | [policy_effect]
8 | e = some(where (p.eft == allow))
9 |
10 | [matchers]
11 | m = r.sub == p.sub && (keyMatch2(r.obj, p.obj) || keyMatch(r.obj, p.obj)) && (r.act == p.act || p.act == "*")
--------------------------------------------------------------------------------
/config/settings.dev.yml:
--------------------------------------------------------------------------------
1 | script:
2 | path: ./static/scripts
3 | settings:
4 | application:
5 | domain: localhost:8002
6 | host: 0.0.0.0
7 | ishttps: false
8 | mode: dev
9 | name: ferry-test
10 | port: "8002"
11 | readtimeout: 1
12 | writertimeout: 2
13 | database:
14 | dbtype: mysql
15 | host: 192.168.31.94
16 | name: ferry
17 | password: 123456
18 | port: 3306
19 | username: root
20 | dingtalk:
21 | agentid: 1234567890
22 | appkey: your dingtalk appkey
23 | appsecret: your dingtalk appsecret
24 | enable: false
25 | domain:
26 | gethost: 1
27 | url: localhost:9527
28 | email:
29 | alias: ferry
30 | host: smtp.163.com
31 | pass: your password
32 | port: 465
33 | user: fdevops@163.com
34 | gorm:
35 | logmode: 0
36 | maxidleconn: 0
37 | maxopenconn: 20000
38 | jwt:
39 | secret: ferry
40 | timeout: 86400
41 | ldap:
42 | anonymousquery: 0
43 | basedn: dc=fdevops,dc=com
44 | bindpwd: 123456
45 | binduserdn: cn=admin,dc=fdevops,dc=com
46 | host: localhost
47 | port: 389
48 | tls: 0
49 | userfield: uid
50 | log:
51 | compress: 1
52 | consolestdout: 1
53 | filestdout: 0
54 | level: debug
55 | localtime: 1
56 | maxage: 30
57 | maxbackups: 300
58 | maxsize: 10240
59 | path: ./logs/ferry.log
60 | public:
61 | islocation: 0
62 | redis:
63 | url: redis://:123456@192.168.31.94:6379
64 | ssl:
65 | key: keystring
66 | pem: temp/pem.pem
67 |
--------------------------------------------------------------------------------
/config/settings.yml:
--------------------------------------------------------------------------------
1 | script:
2 | path: ./static/scripts
3 | settings:
4 | application:
5 | domain: localhost:8002
6 | host: 0.0.0.0
7 | ishttps: false
8 | mode: dev
9 | name: ferry
10 | port: "8002"
11 | readtimeout: 1
12 | writertimeout: 2
13 | database:
14 | dbtype: mysql
15 | host: ferry_mysql
16 | name: ferry
17 | password: 123456
18 | port: 3306
19 | username: root
20 | dingtalk:
21 | agentid: 1234567890
22 | appkey: your dingtalk appkey
23 | appsecret: your dingtalk appsecret
24 | enable: false
25 | domain:
26 | gethost: 1
27 | url: localhost:9527
28 | email:
29 | alias: ferry
30 | host: smtp.163.com
31 | pass: your password
32 | port: 465
33 | user: fdevops@163.com
34 | gorm:
35 | logmode: 0
36 | maxidleconn: 0
37 | maxopenconn: 20000
38 | jwt:
39 | secret: ferry
40 | timeout: 86400
41 | ldap:
42 | anonymousquery: 0
43 | basedn: dc=fdevops,dc=com
44 | bindpwd: 123456
45 | binduserdn: cn=admin,dc=fdevops,dc=com
46 | host: localhost
47 | port: 389
48 | tls: 0
49 | userfield: uid
50 | log:
51 | compress: 1
52 | consolestdout: 1
53 | filestdout: 0
54 | level: debug
55 | localtime: 1
56 | maxage: 30
57 | maxbackups: 300
58 | maxsize: 10240
59 | path: ./logs/ferry.log
60 | public:
61 | islocation: 0
62 | redis:
63 | url: redis://ferry_redis:6379
64 | ssl:
65 | key: keystring
66 | pem: temp/pem.pem
67 |
--------------------------------------------------------------------------------
/database/initialize.go:
--------------------------------------------------------------------------------
1 | package database
2 |
3 | import "ferry/tools/config"
4 |
5 | func Setup() {
6 | dbType := config.DatabaseConfig.Dbtype
7 | if dbType == "mysql" {
8 | var db = new(Mysql)
9 | db.Setup()
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/database/interface.go:
--------------------------------------------------------------------------------
1 | package database
2 |
3 | import "github.com/jinzhu/gorm"
4 |
5 | type Database interface {
6 | Open(dbType string, conn string) (db *gorm.DB, err error)
7 | GetConnect() string
8 | }
9 |
--------------------------------------------------------------------------------
/deploy/helm/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/deploy/helm/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: ferry_helm
3 | description: A Helm chart for Kubernetes
4 |
5 | # A chart can be either an 'application' or a 'library' chart.
6 | #
7 | # Application charts are a collection of templates that can be packaged into versioned archives
8 | # to be deployed.
9 | #
10 | # Library charts provide useful utilities or functions for the chart developer. They're included as
11 | # a dependency of application charts to inject those utilities and functions into the rendering
12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed.
13 | type: application
14 |
15 | # This is the chart version. This version number should be incremented each time you make changes
16 | # to the chart and its templates, including the app version.
17 | # Versions are expected to follow Semantic Versioning (https://semver.org/)
18 | version: 0.1.0
19 |
20 | # This is the version number of the application being deployed. This version number should be
21 | # incremented each time you make changes to the application. Versions are not expected to
22 | # follow Semantic Versioning. They should reflect the version the application is using.
23 | # It is recommended to use it with quotes.
24 | appVersion: "1.16.0"
25 |
--------------------------------------------------------------------------------
/deploy/helm/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | **********
2 | Attention!
3 | **********
4 |
5 | Before using Ferry, you need to import ferry.sql and db.sql from templates/mysql/sql into your database!
6 | You need to import ferroy.sql first and then import db.sql. It is recommended that you import it into a database called ferroy!
7 |
8 |
9 | Thank you for installing {{ .Chart.Name }}.
10 |
11 | Your release is named {{ .Release.Name }}.
12 |
13 | To learn more about the release, try:
14 |
15 | $ helm status {{ .Release.Name }} -n {{ .Values.namespace }}
16 | $ helm get all {{ .Release.Name }} -n {{ .Values.namespace }}
17 |
--------------------------------------------------------------------------------
/deploy/helm/templates/configmap.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: ferry-config
5 | namespace: {{ .Values.namespace }}
6 | data:
7 | rbac_model.conf: |
8 | {{ .Values.configMap.rbac_model_conf | nindent 4 }}
9 |
10 | settings.yml: |
11 | {{ .Values.configMap.settings_yml | indent 4 }}
12 |
--------------------------------------------------------------------------------
/deploy/helm/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: ferry
5 | namespace: {{ .Values.namespace }}
6 | labels:
7 | app: ferry
8 | spec:
9 | replicas: {{ .Values.replicaCount }}
10 | selector:
11 | matchLabels:
12 | app: ferry
13 | template:
14 | metadata:
15 | labels:
16 | app: ferry
17 | spec:
18 | volumes:
19 | - name: ferry-secret
20 | secret:
21 | secretName: ferry-secret
22 | - name: ferry-storage
23 | persistentVolumeClaim:
24 | claimName: ferry-pvc
25 | - name: ferry-config-volume
26 | configMap:
27 | name: ferry-config
28 | - name: ferry-rbac
29 | configMap:
30 | name: ferry-config
31 | containers:
32 | - name: ferry
33 | image: "{{ .Values.ferry.image.repository }}:{{ .Values.ferry.image.tag }}"
34 | imagePullPolicy: {{ .Values.ferry.image.pullPolicy }}
35 | env:
36 | - name: ENV
37 | value: {{ .Values.env.ENV | quote }}
38 | volumeMounts:
39 | - name: ferry-storage
40 | mountPath: /opt/workflow/ferry/config
41 | - name: ferry-config-volume
42 | mountPath: /opt/workflow/ferry/config/settings.yml
43 | subPath: settings.yml
44 | - name: ferry-rbac
45 | mountPath: /opt/workflow/ferry/config/rbac_model.conf
46 | subPath: rbac_model.conf
47 | ports:
48 | - containerPort: 8002
49 |
50 |
--------------------------------------------------------------------------------
/deploy/helm/templates/mysql/persistentvolumeclaim.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.mysql.enable }}
2 | apiVersion: v1
3 | kind: PersistentVolumeClaim
4 | metadata:
5 | name: ferry-mysql-pvc
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | storageClassName: {{ .Values.global.storageClassName }}
9 | accessModes:
10 | - {{ .Values.ferry.persistentVolume.accessModes | join ", " }}
11 | resources:
12 | requests:
13 | storage: {{ .Values.mysql.persistentVolume.size }}
14 | {{ end }}
15 |
--------------------------------------------------------------------------------
/deploy/helm/templates/mysql/service.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.mysql.enable }}
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: ferry-mysql
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | selector:
9 | app: ferry-mysql
10 | ports:
11 | - protocol: TCP
12 | port: {{ .Values.mysql.port }}
13 | targetPort: {{ .Values.mysql.port }}
14 | type: ClusterIP
15 | {{ end }}
--------------------------------------------------------------------------------
/deploy/helm/templates/mysql/statefulset.yaml:
--------------------------------------------------------------------------------
1 | # templates/mysql/statefulset.yaml
2 | {{ if .Values.mysql.enable }}
3 | apiVersion: apps/v1
4 | kind: StatefulSet
5 | metadata:
6 | name: ferry-mysql
7 | namespace: {{ .Values.namespace }}
8 | spec:
9 | replicas: 1
10 | selector:
11 | matchLabels:
12 | app: ferry-mysql
13 | template:
14 | metadata:
15 | labels:
16 | app: ferry-mysql
17 | spec:
18 | containers:
19 | - name: mysql
20 | image: {{ .Values.mysql.image.repository }}:{{ .Values.mysql.image.tag }}
21 | env:
22 | - name: MYSQL_ROOT_PASSWORD
23 | valueFrom:
24 | secretKeyRef:
25 | name: ferry-secret
26 | key: MYSQL_ROOT_PASSWORD
27 | - name: MYSQL_USER
28 | valueFrom:
29 | secretKeyRef:
30 | name: ferry-secret
31 | key: MYSQL_USER
32 | - name: MYSQL_PASSWORD
33 | valueFrom:
34 | secretKeyRef:
35 | name: ferry-secret
36 | key: MYSQL_PASSWORD
37 | - name: MYSQL_DATABASE
38 | valueFrom:
39 | secretKeyRef:
40 | name: ferry-secret
41 | key: MYSQL_DATABASE
42 | volumeMounts:
43 | - name: mysql-storage
44 | mountPath: /var/lib/mysql
45 | ports:
46 | - containerPort: 3306
47 | volumes:
48 | - name: mysql-storage
49 | persistentVolumeClaim:
50 | claimName: ferry-mysql-pvc
51 | {{ end }}
52 |
--------------------------------------------------------------------------------
/deploy/helm/templates/persistentvolumeclaim.yaml:
--------------------------------------------------------------------------------
1 | # templates/persistentvolumeclaim.yaml
2 | apiVersion: v1
3 | kind: PersistentVolumeClaim
4 | metadata:
5 | name: ferry-pvc
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | storageClassName: {{ .Values.global.storageClassName }}
9 | accessModes:
10 | - {{ .Values.ferry.persistentVolume.accessModes | join ", " }}
11 | resources:
12 | requests:
13 | storage: {{ .Values.ferry.persistentVolume.size }}
14 |
--------------------------------------------------------------------------------
/deploy/helm/templates/redis/deployment.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.redis.enable }}
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: ferry-redis
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | replicas: 1
9 | selector:
10 | matchLabels:
11 | app: ferry-redis
12 | template:
13 | metadata:
14 | labels:
15 | app: ferry-redis
16 | spec:
17 | containers:
18 | - name: redis
19 | image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}"
20 | command:
21 | - redis-server
22 | - "--save"
23 | - "60"
24 | - "1"
25 | - "--loglevel"
26 | - "warning"
27 | ports:
28 | - containerPort: {{ .Values.redis.port }}
29 | volumeMounts:
30 | - name: redis-storage
31 | mountPath: /data
32 | volumes:
33 | - name: redis-storage
34 | persistentVolumeClaim:
35 | claimName: ferry-redis-pvc
36 | {{ end }}
37 |
38 |
--------------------------------------------------------------------------------
/deploy/helm/templates/redis/persistentvolumeclaim.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.redis.enable }}
2 | apiVersion: v1
3 | kind: PersistentVolumeClaim
4 | metadata:
5 | name: ferry-redis-pvc
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | accessModes:
9 | - {{ .Values.ferry.persistentVolume.accessModes | join ", " }}
10 | resources:
11 | requests:
12 | storage: {{ .Values.redis.persistentVolume.size }}
13 | storageClassName: {{ .Values.global.storageClassName }}
14 | {{ end }}
15 |
--------------------------------------------------------------------------------
/deploy/helm/templates/redis/service.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.redis.enable }}
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: ferry-redis
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | ports:
9 | - port: {{ .Values.redis.port }}
10 | targetPort: {{ .Values.redis.port }}
11 | selector:
12 | app: ferry-redis
13 | clusterIP: None
14 | {{ end }}
15 |
--------------------------------------------------------------------------------
/deploy/helm/templates/secret.yaml:
--------------------------------------------------------------------------------
1 | # templates/secret.yaml
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: ferry-secret
6 | namespace: {{ .Values.namespace }}
7 | type: Opaque
8 | data:
9 | MYSQL_ROOT_PASSWORD: {{ .Values.env.MYSQL_ROOT_PASSWORD | b64enc | quote }}
10 | MYSQL_USER: {{ .Values.env.MYSQL_USER | b64enc | quote }}
11 | MYSQL_DATABASE: {{ .Values.env.MYSQL_DATABASE | b64enc | quote }}
12 | MYSQL_PASSWORD: {{ .Values.env.MYSQL_PASSWORD | b64enc | quote }}
--------------------------------------------------------------------------------
/deploy/helm/templates/service.yaml:
--------------------------------------------------------------------------------
1 | # templates/service.yaml
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: ferry
6 | namespace: {{ .Values.namespace }}
7 | spec:
8 | selector:
9 | app: ferry
10 | ports:
11 | - protocol: TCP
12 | port: {{ .Values.ferry.service.port }}
13 | targetPort: {{ .Values.ferry.service.port }}
14 | type: {{ .Values.ferry.service.type }}
15 |
--------------------------------------------------------------------------------
/deploy/kubernetes/deploy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: ferry
5 | namespace: ferry
6 | labels:
7 | app: ferry
8 | spec:
9 | replicas: 1
10 | selector:
11 | matchLabels:
12 | app: ferry
13 | template:
14 | metadata:
15 | labels:
16 | app: ferry
17 | spec:
18 | volumes:
19 | - name: ferry-secret
20 | secret:
21 | secretName: ferry-secret
22 | - name: ferry-storage
23 | persistentVolumeClaim:
24 | claimName: ferry-pvc
25 | - name: ferry-config-volume
26 | configMap:
27 | name: ferry-config
28 | - name: ferry-rbac
29 | configMap:
30 | name: ferry-config
31 | containers:
32 | - name: ferry
33 | image: beatrueman/ferry:1.0.0
34 | env:
35 | - name: ENV
36 | value: "production"
37 | volumeMounts:
38 | - name: ferry-storage
39 | mountPath: /opt/workflow/ferry/config
40 | - name: ferry-config-volume
41 | mountPath: /opt/workflow/ferry/config/settings.yml
42 | subPath: settings.yml
43 | - name: ferry-rbac
44 | mountPath: /opt/workflow/ferry/config/rbac_model.conf
45 | subPath: rbac_model.conf
46 | ports:
47 | - containerPort: 8002
48 |
49 | ---
50 |
51 | apiVersion: v1
52 | kind: PersistentVolumeClaim
53 | metadata:
54 | name: ferry-pvc
55 | namespace: ferry
56 | spec:
57 | storageClassName: longhorn
58 | accessModes:
59 | - ReadWriteOnce
60 | resources:
61 | requests:
62 | storage: 2Gi
63 | ---
64 | apiVersion: v1
65 | kind: Service
66 | metadata:
67 | name: ferry
68 | namespace: ferry
69 | spec:
70 | selector:
71 | app: ferry
72 | ports:
73 | - protocol: TCP
74 | port: 8002
75 | targetPort: 8002
76 | type: NodePort
77 |
78 |
--------------------------------------------------------------------------------
/deploy/kubernetes/redis.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: ferry-redis
5 | namespace: ferry
6 | spec:
7 | replicas: 1
8 | selector:
9 | matchLabels:
10 | app: ferry-redis
11 | template:
12 | metadata:
13 | labels:
14 | app: ferry-redis
15 | spec:
16 | containers:
17 | - name: redis
18 | image: redis:latest
19 | command:
20 | - redis-server
21 | - "--save"
22 | - "60"
23 | - "1"
24 | - "--loglevel"
25 | - "warning"
26 | ports:
27 | - containerPort: 6379
28 | volumeMounts:
29 | - name: redis-storage
30 | mountPath: /data
31 | volumes:
32 | - name: redis-storage
33 | persistentVolumeClaim:
34 | claimName: redis-pvc
35 |
36 | ---
37 | apiVersion: v1
38 | kind: PersistentVolumeClaim
39 | metadata:
40 | name: redis-pvc
41 | namespace: ferry
42 | spec:
43 | accessModes:
44 | - ReadWriteOnce
45 | resources:
46 | requests:
47 | storage: 1Gi
48 | storageClassName: longhorn
49 |
50 | ---
51 | apiVersion: v1
52 | kind: Service
53 | metadata:
54 | name: ferry-redis
55 | namespace: ferry
56 | spec:
57 | ports:
58 | - port: 6379
59 | targetPort: 6379
60 | selector:
61 | app: ferry-redis
62 | clusterIP: None
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/deploy/kubernetes/secret.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Secret
3 | metadata:
4 | name: ferry-secret
5 | namespace: ferry
6 | type: Opaque
7 | # 将所有凭据转为base64后填入
8 | data:
9 | MYSQL_ROOT_PASSWORD: ""
10 | MYSQL_USER: ""
11 | MYSQL_DATABASE: ""
12 | MYSQL_PASSWORD: ""
13 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 |
4 | ferry_mysql:
5 | image: mysql:8
6 | container_name: ferry_mysql
7 | restart: unless-stopped
8 | # 可开放出来
9 | #ports:
10 | # - 3306:3306
11 | environment:
12 | MYSQL_ROOT_PASSWORD: '123456'
13 | MYSQL_DATABASE: 'ferry'
14 | MYSQL_USER: 'ferry'
15 | MYSQL_PASSWORD: '123456'
16 | volumes:
17 | - './mysql/db:/var/lib/mysql'
18 | - '/etc/localtime:/etc/localtime:ro'
19 |
20 | ferry_redis:
21 | container_name: ferry_redis
22 | image: redis:latest
23 | restart: unless-stopped
24 | # 可开放出来
25 | #ports:
26 | # - 6379:6379
27 | command: redis-server --save 60 1 --loglevel warning
28 |
29 | ferry:
30 | build:
31 | context: "."
32 | dockerfile: "Dockerfile"
33 | image: ferry:latest
34 | container_name: ferry
35 | restart: unless-stopped
36 | depends_on:
37 | - ferry_mysql
38 | - ferry_redis
39 | ports:
40 | - "8002:8002"
41 | volumes:
42 | - '/etc/localtime:/etc/localtime:ro'
43 | - './config:/opt/workflow/ferry/config'
44 | logging:
45 | driver: json-file
46 | options:
47 | max-size: "10m"
48 | max-file: "10"
49 |
--------------------------------------------------------------------------------
/docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | if [[ ! -f /opt/workflow/ferry/config/settings.yml ]]
4 | then
5 | cp /opt/workflow/ferry/default_config/* /opt/workflow/ferry/config/
6 | fi
7 | if [[ -f /opt/workflow/ferry/config/needinit ]]
8 | then
9 | /opt/workflow/ferry/ferry init -c=/opt/workflow/ferry/config/settings.yml
10 | rm -f /opt/workflow/ferry/config/needinit
11 | fi
12 | /opt/workflow/ferry/ferry server -c=/opt/workflow/ferry/config/settings.yml
13 |
--------------------------------------------------------------------------------
/global/orm/db.go:
--------------------------------------------------------------------------------
1 | package orm
2 |
3 | import (
4 | "github.com/jinzhu/gorm"
5 | )
6 |
7 | var Eloquent *gorm.DB
8 | var MysqlConn string
9 |
10 |
--------------------------------------------------------------------------------
/handler/httpshandler.go:
--------------------------------------------------------------------------------
1 | package handler
2 |
3 | import (
4 | "ferry/tools/config"
5 |
6 | "github.com/gin-gonic/gin"
7 | "github.com/unrolled/secure"
8 | )
9 |
10 | func TlsHandler() gin.HandlerFunc {
11 | return func(c *gin.Context) {
12 | secureMiddleware := secure.New(secure.Options{
13 | SSLRedirect: true,
14 | SSLHost: config.ApplicationConfig.Domain,
15 | })
16 | err := secureMiddleware.Process(c.Writer, c.Request)
17 | if err != nil {
18 | return
19 | }
20 | c.Next()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/handler/ping.go:
--------------------------------------------------------------------------------
1 | package handler
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | )
6 |
7 | func Ping(c *gin.Context) {
8 | c.JSON(200, gin.H{
9 | "message": "ok",
10 | })
11 | }
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "ferry/cmd"
5 | )
6 |
7 | func main() {
8 | cmd.Execute()
9 | }
10 |
--------------------------------------------------------------------------------
/middleware/auth.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "ferry/handler"
5 | jwt "ferry/pkg/jwtauth"
6 | "ferry/tools/config"
7 | "time"
8 | )
9 |
10 | func AuthInit() (*jwt.GinJWTMiddleware, error) {
11 | return jwt.New(&jwt.GinJWTMiddleware{
12 | Realm: "test zone",
13 | Key: []byte(config.ApplicationConfig.JwtSecret),
14 | Timeout: time.Hour,
15 | MaxRefresh: time.Hour,
16 | PayloadFunc: handler.PayloadFunc,
17 | IdentityHandler: handler.IdentityHandler,
18 | Authenticator: handler.Authenticator,
19 | Authorizator: handler.Authorizator,
20 | Unauthorized: handler.Unauthorized,
21 | TokenLookup: "header: Authorization, query: token, cookie: jwt",
22 | TokenHeadName: "Bearer",
23 | TimeFunc: time.Now,
24 | })
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/middleware/customerror.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "fmt"
5 | "github.com/gin-gonic/gin"
6 | "net/http"
7 | "strconv"
8 | "strings"
9 | "time"
10 | )
11 |
12 | func CustomError(c *gin.Context) {
13 | defer func() {
14 | if err := recover(); err != nil {
15 |
16 | if c.IsAborted() {
17 | c.Status(200)
18 | }
19 | switch errStr := err.(type) {
20 | case string:
21 | p := strings.Split(errStr, "#")
22 | if len(p) == 3 && p[0] == "CustomError" {
23 | statusCode, e := strconv.Atoi(p[1])
24 | if e != nil {
25 | break
26 | }
27 | c.Status(statusCode)
28 | fmt.Println(
29 | time.Now().Format("\n 2006-01-02 15:04:05.9999"),
30 | "[ERROR]",
31 | c.Request.Method,
32 | c.Request.URL,
33 | statusCode,
34 | c.Request.RequestURI,
35 | c.ClientIP(),
36 | p[2],
37 | )
38 | c.JSON(http.StatusOK, gin.H{
39 | "code": statusCode,
40 | "msg": p[2],
41 | })
42 | }
43 | default:
44 | panic(err)
45 | }
46 | }
47 | }()
48 | c.Next()
49 | }
50 |
--------------------------------------------------------------------------------
/middleware/header.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "net/http"
6 | "time"
7 | )
8 |
9 | // NoCache is a middleware function that appends headers
10 | // to prevent the client from caching the HTTP response.
11 | func NoCache(c *gin.Context) {
12 | c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
13 | c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
14 | c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
15 | c.Next()
16 | }
17 |
18 | // Options is a middleware function that appends headers
19 | // for options requests and aborts then exits the middleware
20 | // chain and ends the request.
21 | func Options(c *gin.Context) {
22 | if c.Request.Method != "OPTIONS" {
23 | c.Next()
24 | } else {
25 | c.Header("Access-Control-Allow-Origin", "*")
26 | c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
27 | c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
28 | c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS")
29 | c.Header("Content-Type", "application/json")
30 | c.AbortWithStatus(200)
31 | }
32 | }
33 |
34 | // Secure is a middleware function that appends security
35 | // and resource access headers.
36 | func Secure(c *gin.Context) {
37 | c.Header("Access-Control-Allow-Origin", "*")
38 | //c.Header("X-Frame-Options", "DENY")
39 | c.Header("X-Content-Type-Options", "nosniff")
40 | c.Header("X-XSS-Protection", "1; mode=block")
41 | if c.Request.TLS != nil {
42 | c.Header("Strict-Transport-Security", "max-age=31536000")
43 | }
44 |
45 | // Also consider adding Content-Security-Policy headers
46 | // c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com")
47 | }
48 |
--------------------------------------------------------------------------------
/middleware/init.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 |
6 | )
7 |
8 |
9 | func InitMiddleware(r *gin.Engine) {
10 | // 日志处理
11 | r.Use(LoggerToFile())
12 | // 自定义错误处理
13 | r.Use(CustomError)
14 | // NoCache is a middleware function that appends headers
15 | r.Use(NoCache)
16 | // 跨域处理
17 | r.Use(Options)
18 | // Secure is a middleware function that appends security
19 | r.Use(Secure)
20 | // Set X-Request-Id header
21 | r.Use(RequestId())
22 | }
--------------------------------------------------------------------------------
/middleware/logger.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "ferry/pkg/logger"
5 | "time"
6 |
7 | "github.com/gin-gonic/gin"
8 | )
9 |
10 | // 日志记录到文件
11 | func LoggerToFile() gin.HandlerFunc {
12 |
13 | return func(c *gin.Context) {
14 | // 开始时间
15 | startTime := time.Now()
16 |
17 | // 处理请求
18 | c.Next()
19 |
20 | // 结束时间
21 | endTime := time.Now()
22 |
23 | // 执行时间
24 | latencyTime := endTime.Sub(startTime)
25 |
26 | // 请求方式
27 | reqMethod := c.Request.Method
28 |
29 | // 请求路由
30 | reqUri := c.Request.RequestURI
31 |
32 | // 状态码
33 | statusCode := c.Writer.Status()
34 |
35 | // 请求IP
36 | clientIP := c.ClientIP()
37 |
38 | // 日志格式
39 | logger.Infof(" %s %3d %13v %15s %s %s",
40 | startTime.Format("2006-01-02 15:04:05.9999"),
41 | statusCode,
42 | latencyTime,
43 | clientIP,
44 | reqMethod,
45 | reqUri,
46 | )
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/middleware/permission.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | mycasbin "ferry/pkg/casbin"
5 | "ferry/pkg/jwtauth"
6 | _ "ferry/pkg/jwtauth"
7 | "ferry/pkg/logger"
8 | "ferry/tools"
9 | "fmt"
10 | "net/http"
11 |
12 | "github.com/gin-gonic/gin"
13 | )
14 |
15 | //权限检查中间件
16 | func AuthCheckRole() gin.HandlerFunc {
17 | return func(c *gin.Context) {
18 | data, _ := c.Get("JWT_PAYLOAD")
19 | v := data.(jwtauth.MapClaims)
20 | e, err := mycasbin.Casbin()
21 | tools.HasError(err, "", 500)
22 | //检查权限
23 | res, err := e.Enforce(v["rolekey"], c.Request.URL.Path, c.Request.Method)
24 | logger.Info(v["rolekey"], c.Request.URL.Path, c.Request.Method)
25 | tools.HasError(err, "", 500)
26 |
27 | if res {
28 | c.Next()
29 | } else {
30 | c.JSON(http.StatusOK, gin.H{
31 | "code": 403,
32 | "msg": fmt.Sprintf("对不起,您没有 <%v-%v> 访问权限,请联系管理员", c.Request.URL.Path, c.Request.Method),
33 | })
34 | c.Abort()
35 | return
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/middleware/requestid.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "github.com/google/uuid"
6 | )
7 |
8 | func RequestId() gin.HandlerFunc {
9 | return func(c *gin.Context) {
10 | // Check for incoming header, use it if exists
11 | requestId := c.Request.Header.Get("X-Request-Id")
12 |
13 | // Create request id with UUID4
14 | if requestId == "" {
15 | requestId = uuid.NewString()
16 | }
17 |
18 | // Expose it for use in the application
19 | c.Set("X-Request-Id", requestId)
20 |
21 | // Set X-Request-Id header
22 | c.Writer.Header().Set("X-Request-Id", requestId)
23 | c.Next()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/models/base/base.go:
--------------------------------------------------------------------------------
1 | /*
2 | @Author : lanyulei
3 | */
4 |
5 | package base
6 |
7 | import (
8 | "ferry/pkg/jsonTime"
9 | )
10 |
11 | type Model struct {
12 | Id int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" form:"id"`
13 | CreatedAt jsonTime.JSONTime `gorm:"column:create_time" json:"create_time" form:"create_time"`
14 | UpdatedAt jsonTime.JSONTime `gorm:"column:update_time" json:"update_time" form:"update_time"`
15 | DeletedAt *jsonTime.JSONTime `gorm:"column:delete_time" sql:"index" json:"-"`
16 | }
17 |
--------------------------------------------------------------------------------
/models/gorm/gorm.go:
--------------------------------------------------------------------------------
1 | package gorm
2 |
3 | import (
4 | "ferry/models/process"
5 | "ferry/models/system"
6 |
7 | "github.com/jinzhu/gorm"
8 | )
9 |
10 | func AutoMigrate(db *gorm.DB) error {
11 | db.SingularTable(true)
12 | return db.AutoMigrate(
13 | // 系统管理
14 | new(system.CasbinRule),
15 | new(system.Dept),
16 | new(system.Menu),
17 | new(system.LoginLog),
18 | new(system.RoleMenu),
19 | new(system.SysRoleDept),
20 | new(system.SysUser),
21 | new(system.SysRole),
22 | new(system.Post),
23 | new(system.Settings),
24 |
25 | // 流程中心
26 | new(process.Classify),
27 | new(process.TplInfo),
28 | new(process.TplData),
29 | new(process.WorkOrderInfo),
30 | new(process.TaskInfo),
31 | new(process.Info),
32 | new(process.History),
33 | new(process.CirculationHistory),
34 | ).Error
35 | }
36 |
--------------------------------------------------------------------------------
/models/process/circulationHistory.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "ferry/models/base"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | */
10 |
11 | // 工单流转历史
12 | type CirculationHistory struct {
13 | base.Model
14 | Title string `gorm:"column:title; type: varchar(128)" json:"title" form:"title"` // 工单标题
15 | WorkOrder int `gorm:"column:work_order; type: int(11)" json:"work_order" form:"work_order"` // 工单ID
16 | State string `gorm:"column:state; type: varchar(128)" json:"state" form:"state"` // 工单状态
17 | Source string `gorm:"column:source; type: varchar(128)" json:"source" form:"source"` // 源节点ID
18 | Target string `gorm:"column:target; type: varchar(128)" json:"target" form:"target"` // 目标节点ID
19 | Circulation string `gorm:"column:circulation; type: varchar(128)" json:"circulation" form:"circulation"` // 流转ID
20 | Status int `gorm:"column:status; type: int(11)" json:"status" form:"status"` // 流转状态 1 同意, 0 拒绝, 2 其他
21 | Processor string `gorm:"column:processor; type: varchar(45)" json:"processor" form:"processor"` // 处理人
22 | ProcessorId int `gorm:"column:processor_id; type: int(11)" json:"processor_id" form:"processor_id"` // 处理人ID
23 | CostDuration int64 `gorm:"column:cost_duration; type: int(11)" json:"cost_duration" form:"cost_duration"` // 处理时长
24 | Remarks string `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"` // 备注
25 | }
26 |
27 | func (CirculationHistory) TableName() string {
28 | return "p_work_order_circulation_history"
29 | }
30 |
--------------------------------------------------------------------------------
/models/process/classify.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "ferry/models/base"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | */
10 |
11 | // 流程分类
12 | type Classify struct {
13 | base.Model
14 | Name string `gorm:"column:name; type: varchar(128)" json:"name" form:"name"` // 分类名称
15 | Creator int `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"` // 创建者
16 | }
17 |
18 | func (Classify) TableName() string {
19 | return "p_process_classify"
20 | }
21 |
--------------------------------------------------------------------------------
/models/process/history.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "ferry/models/base"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | */
10 |
11 | // 任务
12 | type History struct {
13 | base.Model
14 | Task int `gorm:"column:task; type: int(11)" json:"task" form:"task"` // 任务ID
15 | Name string `gorm:"column:name; type: varchar(256)" json:"name" form:"name"` // 任务名称
16 | TaskType int `gorm:"column:task_type; type: int(11)" json:"task_type" form:"task_type"` // 任务类型, python, shell
17 | ExecutionTime string `gorm:"column:execution_time; type: varchar(128)" json:"execution_time" form:"execution_time"` // 执行时间
18 | Result string `gorm:"column:result; type: longtext" json:"result" form:"result"` // 任务返回
19 | }
20 |
21 | func (History) TableName() string {
22 | return "p_task_history"
23 | }
24 |
--------------------------------------------------------------------------------
/models/process/process.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/models/base"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | // 流程
13 | type Info struct {
14 | base.Model
15 | Name string `gorm:"column:name; type:varchar(128)" json:"name" form:"name"` // 流程名称
16 | Icon string `gorm:"column:icon; type:varchar(128)" json:"icon" form:"icon"` // 流程标签
17 | Structure json.RawMessage `gorm:"column:structure; type:json" json:"structure" form:"structure"` // 流程结构
18 | Classify int `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"` // 分类ID
19 | Tpls json.RawMessage `gorm:"column:tpls; type:json" json:"tpls" form:"tpls"` // 模版
20 | Task json.RawMessage `gorm:"column:task; type:json" json:"task" form:"task"` // 任务ID, array, 可执行多个任务,可以当成通知任务,每个节点都会去执行
21 | SubmitCount int `gorm:"column:submit_count; type:int(11); default:0" json:"submit_count" form:"submit_count"` // 提交统计
22 | Creator int `gorm:"column:creator; type:int(11)" json:"creator" form:"creator"` // 创建者
23 | Notice json.RawMessage `gorm:"column:notice; type:json" json:"notice" form:"notice"` // 绑定通知
24 | Remarks string `gorm:"column:remarks; type:varchar(1024)" json:"remarks" form:"remarks"` // 流程备注
25 | }
26 |
27 | func (Info) TableName() string {
28 | return "p_process_info"
29 | }
30 |
--------------------------------------------------------------------------------
/models/process/task.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "ferry/models/base"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | */
10 |
11 | // 任务
12 | type TaskInfo struct {
13 | base.Model
14 | Name string `gorm:"column:name; type: varchar(256)" json:"name" form:"name"` // 任务名称
15 | TaskType string `gorm:"column:task_type; type: varchar(45)" json:"task_type" form:"task_type"` // 任务类型
16 | Content string `gorm:"column:content; type: longtext" json:"content" form:"content"` // 任务内容
17 | Creator int `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"` // 创建者
18 | Remarks string `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"` // 备注
19 | }
20 |
21 | func (TaskInfo) TableName() string {
22 | return "p_task_info"
23 | }
24 |
--------------------------------------------------------------------------------
/models/process/tpl.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/models/base"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | // 模板
13 | type TplInfo struct {
14 | base.Model
15 | Name string `gorm:"column:name; type: varchar(128)" json:"name" form:"name" binding:"required"` // 模板名称
16 | FormStructure json.RawMessage `gorm:"column:form_structure; type: json" json:"form_structure" form:"form_structure" binding:"required"` // 表单结构
17 | Creator int `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"` // 创建者
18 | Remarks string `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"` // 备注
19 | }
20 |
21 | func (TplInfo) TableName() string {
22 | return "p_tpl_info"
23 | }
24 |
--------------------------------------------------------------------------------
/models/process/tplData.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/models/base"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | // 工单绑定模版数据
13 | type TplData struct {
14 | base.Model
15 | WorkOrder int `gorm:"column:work_order; type: int(11)" json:"work_order" form:"work_order"` // 工单ID
16 | FormStructure json.RawMessage `gorm:"column:form_structure; type: json" json:"form_structure" form:"form_structure"` // 表单结构
17 | FormData json.RawMessage `gorm:"column:form_data; type: json" json:"form_data" form:"form_data"` // 表单数据
18 | }
19 |
20 | func (TplData) TableName() string {
21 | return "p_work_order_tpl_data"
22 | }
23 |
--------------------------------------------------------------------------------
/models/process/workOrder.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/models/base"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | // 工单
13 | type WorkOrderInfo struct {
14 | base.Model
15 | Title string `gorm:"column:title; type:varchar(128)" json:"title" form:"title"` // 工单标题
16 | Priority int `gorm:"column:priority; type:int(11)" json:"priority" form:"priority"` // 工单优先级 1,正常 2,紧急 3,非常紧急
17 | Process int `gorm:"column:process; type:int(11)" json:"process" form:"process"` // 流程ID
18 | Classify int `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"` // 分类ID
19 | IsEnd int `gorm:"column:is_end; type:int(11); default:0" json:"is_end" form:"is_end"` // 是否结束, 0 未结束,1 已结束
20 | IsDenied int `gorm:"column:is_denied; type:int(11); default:0" json:"is_denied" form:"is_denied"` // 是否被拒绝, 0 没有,1 有
21 | State json.RawMessage `gorm:"column:state; type:json" json:"state" form:"state"` // 状态信息
22 | RelatedPerson json.RawMessage `gorm:"column:related_person; type:json" json:"related_person" form:"related_person"` // 工单所有处理人
23 | Creator int `gorm:"column:creator; type:int(11)" json:"creator" form:"creator"` // 创建人
24 | UrgeCount int `gorm:"column:urge_count; type:int(11); default:0" json:"urge_count" form:"urge_count"` // 催办次数
25 | UrgeLastTime int `gorm:"column:urge_last_time; type:int(11); default:0" json:"urge_last_time" form:"urge_last_time"` // 上一次催促时间
26 | }
27 |
28 | func (WorkOrderInfo) TableName() string {
29 | return "p_work_order_info"
30 | }
31 |
--------------------------------------------------------------------------------
/models/system/casbinrule.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 |
7 | //casbin_rule
8 | type CasbinRule struct {
9 | PType string `json:"p_type" gorm:"type:varchar(100);"`
10 | V0 string `json:"v0" gorm:"type:varchar(100);"`
11 | V1 string `json:"v1" gorm:"type:varchar(100);"`
12 | V2 string `json:"v2" gorm:"type:varchar(100);"`
13 | V3 string `json:"v3" gorm:"type:varchar(100);"`
14 | V4 string `json:"v4" gorm:"type:varchar(100);"`
15 | V5 string `json:"v5" gorm:"type:varchar(100);"`
16 | Id int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" form:"id"`
17 | BaseModel
18 | }
19 |
20 | func (CasbinRule) TableName() string {
21 | return "casbin_rule"
22 | }
23 |
--------------------------------------------------------------------------------
/models/system/initdb.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/global/orm"
5 | "fmt"
6 | "os"
7 | "strings"
8 | )
9 |
10 | /*
11 | @Author : lanyulei
12 | */
13 |
14 | func InitDb() error {
15 | filePath := "config/db.sql"
16 | sql, err := Ioutil(filePath)
17 | if err != nil {
18 | fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error())
19 | return err
20 | }
21 | sqlList := strings.Split(sql, ";")
22 | for _, sql := range sqlList {
23 | if strings.Contains(sql, "--") {
24 | fmt.Println(sql)
25 | continue
26 | }
27 | sqlValue := strings.Replace(sql+";", "\n", "", 1)
28 | if err = orm.Eloquent.Exec(sqlValue).Error; err != nil {
29 | if !strings.Contains(err.Error(), "Query was empty") {
30 | return err
31 | }
32 | }
33 | }
34 | return nil
35 | }
36 |
37 | func Ioutil(name string) (string, error) {
38 | if contents, err := os.ReadFile(name); err == nil {
39 | //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符
40 | result := strings.Replace(string(contents), "\n", "", 1)
41 | return result, nil
42 | } else {
43 | return "", err
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/models/system/login.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/global/orm"
5 | "ferry/tools"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | type Login struct {
13 | Username string `form:"UserName" json:"username" binding:"required"`
14 | Password string `form:"Password" json:"password" binding:"required"`
15 | Code string `form:"Code" json:"code"`
16 | UUID string `form:"UUID" json:"uuid"`
17 | LoginType int `form:"LoginType" json:"loginType"`
18 | }
19 |
20 | func (u *Login) GetUser() (user SysUser, role SysRole, e error) {
21 |
22 | e = orm.Eloquent.Table("sys_user").Where("username = ? ", u.Username).Find(&user).Error
23 | if e != nil {
24 | return
25 | }
26 |
27 | // 验证密码
28 | if u.LoginType == 0 {
29 | _, e = tools.CompareHashAndPassword(user.Password, u.Password)
30 | if e != nil {
31 | return
32 | }
33 | }
34 |
35 | e = orm.Eloquent.Table("sys_role").Where("role_id = ? ", user.RoleId).First(&role).Error
36 | if e != nil {
37 | return
38 | }
39 | return
40 | }
41 |
--------------------------------------------------------------------------------
/models/system/model.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 | import (
7 | "time"
8 | )
9 |
10 | type BaseModel struct {
11 | CreatedAt time.Time `gorm:"column:create_time" json:"create_time" form:"create_time"`
12 | UpdatedAt time.Time `gorm:"column:update_time" json:"update_time" form:"update_time"`
13 | DeletedAt *time.Time `gorm:"column:delete_time" sql:"index" json:"-"`
14 | }
15 |
--------------------------------------------------------------------------------
/models/system/roledept.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "ferry/global/orm"
5 | "fmt"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | //sys_role_dept
13 | type SysRoleDept struct {
14 | RoleId int `gorm:"type:int(11)"`
15 | DeptId int `gorm:"type:int(11)"`
16 | Id int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" form:"id"`
17 | }
18 |
19 | func (SysRoleDept) TableName() string {
20 | return "sys_role_dept"
21 | }
22 |
23 | func (rm *SysRoleDept) Insert(roleId int, deptIds []int) (bool, error) {
24 | //ORM不支持批量插入所以需要拼接 sql 串
25 | sql := "INSERT INTO `sys_role_dept` (`role_id`,`dept_id`) VALUES "
26 |
27 | for i := 0; i < len(deptIds); i++ {
28 | if len(deptIds)-1 == i {
29 | //最后一条数据 以分号结尾
30 | sql += fmt.Sprintf("(%d,%d);", roleId, deptIds[i])
31 | } else {
32 | sql += fmt.Sprintf("(%d,%d),", roleId, deptIds[i])
33 | }
34 | }
35 | orm.Eloquent.Exec(sql)
36 |
37 | return true, nil
38 | }
39 |
40 | func (rm *SysRoleDept) DeleteRoleDept(roleId int) (bool, error) {
41 | if err := orm.Eloquent.Table("sys_role_dept").Where("role_id = ?", roleId).Delete(&rm).Error; err != nil {
42 | return false, err
43 | }
44 | var role SysRole
45 | if err := orm.Eloquent.Table("sys_role").Where("role_id = ?", roleId).First(&role).Error; err != nil {
46 | return false, err
47 | }
48 |
49 | return true, nil
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/models/system/settings.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/models/base"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | // 配置信息
13 | type Settings struct {
14 | base.Model
15 | Classify int `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"` // 设置分类,1 配置信息,2 Ldap配置
16 | Content json.RawMessage `gorm:"column:content; type:json" json:"content" form:"content"` // 配置内容
17 | }
18 |
19 | func (Settings) TableName() string {
20 | return "sys_settings"
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/casbin/mycasbin.go:
--------------------------------------------------------------------------------
1 | package mycasbin
2 |
3 | import (
4 | "ferry/global/orm"
5 | "ferry/pkg/logger"
6 | "ferry/tools/config"
7 |
8 | "github.com/casbin/casbin/v2"
9 | gormadapter "github.com/casbin/gorm-adapter/v2"
10 | "github.com/go-kit/kit/endpoint"
11 | _ "github.com/go-sql-driver/mysql"
12 | )
13 |
14 | var _ endpoint.Middleware
15 |
16 | func Casbin() (*casbin.Enforcer, error) {
17 | conn := orm.MysqlConn
18 | Apter, err := gormadapter.NewAdapter(config.DatabaseConfig.Dbtype, conn, true)
19 | if err != nil {
20 | return nil, err
21 | }
22 | e, err := casbin.NewEnforcer("config/rbac_model.conf", Apter)
23 | if err != nil {
24 | return nil, err
25 | }
26 | if err := e.LoadPolicy(); err == nil {
27 | return e, err
28 | } else {
29 | logger.Infof("casbin rbac_model or policy init error, message: %v \r\n", err.Error())
30 | return nil, err
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/jsonTime/JSONTime.go:
--------------------------------------------------------------------------------
1 | /*
2 | @Author : lanyulei
3 | */
4 |
5 | package jsonTime
6 |
7 | import (
8 | "database/sql/driver"
9 | "fmt"
10 | "time"
11 | )
12 |
13 | // 重写MarshalJSON实现models json返回的时间格式
14 | type JSONTime struct {
15 | time.Time
16 | }
17 |
18 | func (t JSONTime) MarshalJSON() ([]byte, error) {
19 | formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05"))
20 | return []byte(formatted), nil
21 | }
22 |
23 | func (t JSONTime) Value() (driver.Value, error) {
24 | var zeroTime time.Time
25 | if t.Time.UnixNano() == zeroTime.UnixNano() {
26 | return nil, nil
27 | }
28 | return t.Time, nil
29 | }
30 |
31 | func (t *JSONTime) Scan(v interface{}) error {
32 | value, ok := v.(time.Time)
33 | if ok {
34 | *t = JSONTime{Time: value}
35 | return nil
36 | }
37 | return fmt.Errorf("无法转换 %v 的时间格式", v)
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/ldap/connection.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "crypto/tls"
5 | "errors"
6 | "ferry/pkg/logger"
7 | "fmt"
8 | "time"
9 |
10 | "github.com/spf13/viper"
11 |
12 | "github.com/go-ldap/ldap/v3"
13 | )
14 |
15 | /*
16 | @Author : lanyulei
17 | */
18 |
19 | var conn *ldap.Conn
20 |
21 | // ldap连接
22 | func ldapConnection() (err error) {
23 | var ldapConn = fmt.Sprintf("%v:%v", viper.GetString("settings.ldap.host"), viper.GetString("settings.ldap.port"))
24 |
25 | if viper.GetBool("settings.ldap.tls") {
26 | tlsConf := &tls.Config{
27 | InsecureSkipVerify: true,
28 | }
29 | conn, err = ldap.DialTLS("tcp", ldapConn, tlsConf)
30 | } else {
31 | conn, err = ldap.Dial("tcp", ldapConn)
32 | }
33 | if err != nil {
34 | err = errors.New(fmt.Sprintf("无法连接到ldap服务器,%v", err))
35 | logger.Error(err)
36 | return
37 | }
38 |
39 | //设置超时时间
40 | conn.SetTimeout(5 * time.Second)
41 |
42 | return
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/ldap/ldapFieldsMap.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "ferry/models/system"
5 |
6 | "github.com/go-ldap/ldap/v3"
7 | )
8 |
9 | /*
10 | @Author : lanyulei
11 | */
12 |
13 | func LdapFieldsMap(ldapUserInfo *ldap.Entry) (userInfo system.SysUser, err error) {
14 | var (
15 | ldapFields []map[string]string
16 | )
17 |
18 | ldapFields, err = getLdapFields()
19 | if err != nil {
20 | return
21 | }
22 |
23 | for _, v := range ldapFields {
24 | switch v["local_field_name"] {
25 | case "nick_name":
26 | userInfo.NickName = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
27 | case "phone":
28 | userInfo.Phone = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
29 | case "avatar":
30 | userInfo.Avatar = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
31 | case "sex":
32 | userInfo.Sex = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
33 | case "email":
34 | userInfo.Email = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
35 | case "remark":
36 | userInfo.Remark = ldapUserInfo.GetAttributeValue(v["ldap_field_name"])
37 | }
38 | }
39 |
40 | return
41 | }
42 |
--------------------------------------------------------------------------------
/pkg/ldap/login.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/go-ldap/ldap/v3"
7 | )
8 |
9 | /*
10 | @Author : lanyulei
11 | */
12 |
13 | func LdapLogin(username string, password string) (userInfo *ldap.Entry, err error) {
14 | err = ldapConnection()
15 | if err != nil {
16 | return
17 | }
18 | defer conn.Close()
19 |
20 | userInfo, err = searchRequest(username)
21 | if err != nil {
22 | return
23 | }
24 |
25 | err = conn.Bind(userInfo.DN, password)
26 | if err != nil {
27 | return nil, fmt.Errorf("用户或密码不正确。")
28 | }
29 |
30 | return
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/ldap/updatePwd.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "ferry/pkg/logger"
5 | "fmt"
6 |
7 | "github.com/go-ldap/ldap/v3"
8 | "golang.org/x/text/encoding/unicode"
9 |
10 | "github.com/spf13/viper"
11 | )
12 |
13 | /*
14 | @Author : lanyulei
15 | */
16 |
17 | func LdapUpdatePwd(username string, oldPassword string, newPassword string) (err error) {
18 | err = ldapConnection()
19 | if err != nil {
20 | return
21 | }
22 | defer conn.Close()
23 |
24 | var userDn = fmt.Sprintf("cn=%v,%v", username, viper.GetString("settings.ldap.baseDn"))
25 |
26 | err = conn.Bind(userDn, oldPassword)
27 | if err != nil {
28 | logger.Error("用户或密码错误。", err)
29 | return
30 | }
31 |
32 | sql2 := ldap.NewModifyRequest(userDn, nil)
33 |
34 | utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
35 | pwdEncoded, _ := utf16.NewEncoder().String(newPassword)
36 |
37 | sql2.Replace("unicodePwd", []string{pwdEncoded})
38 | sql2.Replace("userAccountControl", []string{"512"})
39 |
40 | if err = conn.Modify(sql2); err != nil {
41 | logger.Error("密码修改失败,%v", err.Error())
42 | return
43 | }
44 |
45 | return
46 | }
47 |
--------------------------------------------------------------------------------
/pkg/notify/email/email.go:
--------------------------------------------------------------------------------
1 | package email
2 |
3 | /*
4 | @Author : lanyulei
5 | @Desc : 发送邮件
6 | */
7 |
8 | import (
9 | "ferry/pkg/logger"
10 | "strconv"
11 |
12 | "github.com/spf13/viper"
13 |
14 | "gopkg.in/gomail.v2"
15 | )
16 |
17 | func server(mailTo []string, ccTo []string, subject, body string, args ...string) error {
18 | //定义邮箱服务器连接信息,如果是网易邮箱 pass填密码,qq邮箱填授权码
19 | mailConn := map[string]string{
20 | "user": viper.GetString("settings.email.user"),
21 | "pass": viper.GetString("settings.email.pass"),
22 | "host": viper.GetString("settings.email.host"),
23 | "port": viper.GetString("settings.email.port"),
24 | }
25 |
26 | port, _ := strconv.Atoi(mailConn["port"]) //转换端口类型为int
27 |
28 | m := gomail.NewMessage()
29 |
30 | m.SetHeader("From", m.FormatAddress(mailConn["user"], viper.GetString("settings.email.alias"))) //这种方式可以添加别名,即“XX官方”
31 | m.SetHeader("To", mailTo...) //发送给多个用户
32 | m.SetHeader("Cc", ccTo...) //发送给多个用户
33 | m.SetHeader("Subject", subject) //设置邮件主题
34 | m.SetBody("text/html", body) //设置邮件正文
35 |
36 | d := gomail.NewDialer(mailConn["host"], port, mailConn["user"], mailConn["pass"])
37 | err := d.DialAndSend(m)
38 | return err
39 |
40 | }
41 |
42 | func SendMail(mailTo []string, ccTo []string, subject, body string) {
43 | err := server(mailTo, ccTo, subject, body)
44 | if err != nil {
45 | logger.Info(err)
46 | return
47 | }
48 | logger.Info("send successfully")
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/pagination/params.go:
--------------------------------------------------------------------------------
1 | package pagination
2 |
3 | import (
4 | "ferry/pkg/logger"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | /*
10 | @Author : lanyulei
11 | */
12 |
13 | func RequestParams(c *gin.Context) map[string]interface{} {
14 | params := make(map[string]interface{}, 10)
15 |
16 | if c.Request.Form == nil {
17 | if err := c.Request.ParseMultipartForm(32 << 20); err != nil {
18 | logger.Error(err)
19 | }
20 | }
21 |
22 | if len(c.Request.Form) > 0 {
23 | for key, value := range c.Request.Form {
24 | if key == "page" || key == "per_page" || key == "sort" {
25 | continue
26 | }
27 | params[key] = value[0]
28 | }
29 | }
30 |
31 | return params
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/service/getState.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "strconv"
5 | )
6 |
7 | /*
8 | @Author : lanyulei
9 | @Desc : 获取节点数据
10 | */
11 |
12 | type ProcessState struct {
13 | Structure map[string][]map[string]interface{}
14 | }
15 |
16 | // 获取节点信息
17 | func (p *ProcessState) GetNode(stateId string) (nodeValue map[string]interface{}, err error) {
18 | for _, node := range p.Structure["nodes"] {
19 | if node["id"] == stateId {
20 | nodeValue = node
21 | }
22 | }
23 | return
24 | }
25 |
26 | // 获取流转信息
27 | func (p *ProcessState) GetEdge(stateId string, classify string) (edgeValue []map[string]interface{}, err error) {
28 | var (
29 | leftSort int
30 | rightSort int
31 | )
32 |
33 | for _, edge := range p.Structure["edges"] {
34 | if edge[classify] == stateId {
35 | edgeValue = append(edgeValue, edge)
36 | }
37 | }
38 |
39 | // 排序
40 | if len(edgeValue) > 1 {
41 | for i := 0; i < len(edgeValue)-1; i++ {
42 | for j := i + 1; j < len(edgeValue); j++ {
43 | if t, ok := edgeValue[i]["sort"]; ok {
44 | leftSort, _ = strconv.Atoi(t.(string))
45 | }
46 | if t, ok := edgeValue[j]["sort"]; ok {
47 | rightSort, _ = strconv.Atoi(t.(string))
48 | }
49 | if leftSort > rightSort {
50 | edgeValue[j], edgeValue[i] = edgeValue[i], edgeValue[j]
51 | }
52 | }
53 | }
54 | }
55 |
56 | return
57 | }
58 |
--------------------------------------------------------------------------------
/pkg/service/getVariableValue.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "ferry/global/orm"
5 | "ferry/models/system"
6 | )
7 |
8 | /*
9 | @Author : lanyulei
10 | */
11 |
12 | func GetVariableValue(stateList []interface{}, creator int) (err error) {
13 | var (
14 | userInfo system.SysUser
15 | deptInfo system.Dept
16 | )
17 |
18 | // 变量转为实际的数据
19 | for _, stateItem := range stateList {
20 | if stateItem.(map[string]interface{})["process_method"] == "variable" {
21 | for processorIndex, processor := range stateItem.(map[string]interface{})["processor"].([]interface{}) {
22 | if int(processor.(float64)) == 1 {
23 | // 创建者
24 | stateItem.(map[string]interface{})["processor"].([]interface{})[processorIndex] = creator
25 | } else if int(processor.(float64)) == 2 {
26 | // 1. 查询用户信息
27 | err = orm.Eloquent.Model(&userInfo).Where("user_id = ?", creator).Find(&userInfo).Error
28 | if err != nil {
29 | return
30 | }
31 | // 2. 查询部门信息
32 | err = orm.Eloquent.Model(&deptInfo).Where("dept_id = ?", userInfo.DeptId).Find(&deptInfo).Error
33 | if err != nil {
34 | return
35 | }
36 |
37 | // 3. 替换处理人信息
38 | stateItem.(map[string]interface{})["processor"].([]interface{})[processorIndex] = deptInfo.Leader
39 | }
40 | }
41 | stateItem.(map[string]interface{})["process_method"] = "person"
42 | }
43 | }
44 |
45 | return
46 | }
47 |
--------------------------------------------------------------------------------
/pkg/service/task.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "ferry/pkg/task"
5 | "fmt"
6 | "strings"
7 |
8 | "github.com/spf13/viper"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | func ExecTask(taskList []string, params string) {
16 | for _, taskName := range taskList {
17 | filePath := fmt.Sprintf("%v/%v", viper.GetString("script.path"), taskName)
18 | if strings.HasSuffix(filePath, ".py") {
19 | task.Send("python", filePath, params)
20 | } else if strings.HasSuffix(filePath, ".sh") {
21 | task.Send("shell", filePath, params)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/settings/get_content.go:
--------------------------------------------------------------------------------
1 | package settings
2 |
3 | import (
4 | "encoding/json"
5 | "ferry/global/orm"
6 | "ferry/models/system"
7 | )
8 |
9 | func GetContent(classify int) (content map[string]interface{}, err error) {
10 | var (
11 | settings system.Settings
12 | )
13 |
14 | err = orm.Eloquent.Where("classify = ?", classify).Find(&settings).Error
15 | if err != nil {
16 | return
17 | }
18 |
19 | err = json.Unmarshal(settings.Content, &content)
20 | if err != nil {
21 | return
22 | }
23 |
24 | return
25 | }
26 |
27 | func GetContentByKey(classify int, key string) (value interface{}, err error) {
28 | var (
29 | content map[string]interface{}
30 | )
31 |
32 | content, err = GetContent(classify)
33 | if err != nil {
34 | return
35 | }
36 |
37 | value = content[key]
38 |
39 | return
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/task/send.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 |
7 | import (
8 | "context"
9 | "ferry/pkg/task/worker"
10 | )
11 |
12 | func Send(classify string, scriptPath string, params string) {
13 | worker.SendTask(context.Background(), classify, scriptPath, params)
14 | }
15 |
--------------------------------------------------------------------------------
/pkg/task/server.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 |
7 | import (
8 | "ferry/pkg/logger"
9 | "ferry/pkg/task/worker"
10 | )
11 |
12 | func Start() {
13 | // 1. 启动服务,连接redis
14 | worker.StartServer()
15 |
16 | // 2. 启动异步调度
17 | taskWorker := worker.NewAsyncTaskWorker(10)
18 | err := taskWorker.Launch()
19 | if err != nil {
20 | logger.Errorf("启动machinery失败,%v", err.Error())
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/task/worker/worker.go:
--------------------------------------------------------------------------------
1 | package worker
2 |
3 | import (
4 | "ferry/pkg/logger"
5 |
6 | "github.com/spf13/viper"
7 |
8 | "github.com/RichardKnop/machinery/v1"
9 | taskConfig "github.com/RichardKnop/machinery/v1/config"
10 | "github.com/RichardKnop/machinery/v1/tasks"
11 | )
12 |
13 | var AsyncTaskCenter *machinery.Server
14 |
15 | func StartServer() {
16 | tc, err := NewTaskCenter()
17 | if err != nil {
18 | panic(err)
19 | }
20 | AsyncTaskCenter = tc
21 | }
22 |
23 | func NewTaskCenter() (*machinery.Server, error) {
24 | cnf := &taskConfig.Config{
25 | Broker: viper.GetString("settings.redis.url"),
26 | DefaultQueue: "ServerTasksQueue",
27 | ResultBackend: "eager",
28 | }
29 | server, err := machinery.NewServer(cnf)
30 | if err != nil {
31 | return nil, err
32 | }
33 | initAsyncTaskMap()
34 | return server, server.RegisterTasks(asyncTaskMap)
35 | }
36 |
37 | func NewAsyncTaskWorker(concurrency int) *machinery.Worker {
38 | consumerTag := "TaskWorker"
39 | worker := AsyncTaskCenter.NewWorker(consumerTag, concurrency)
40 | errorHandler := func(err error) {
41 | logger.Error("执行失败: ", err)
42 | }
43 | preTaskHandler := func(signature *tasks.Signature) {
44 | logger.Info("开始执行: ", signature.Name)
45 | }
46 | postTaskHandler := func(signature *tasks.Signature) {
47 | logger.Info("执行结束: ", signature.Name)
48 | }
49 | worker.SetPostTaskHandler(postTaskHandler)
50 | worker.SetErrorHandler(errorHandler)
51 | worker.SetPreTaskHandler(preTaskHandler)
52 | return worker
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/utils/file.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "io/ioutil"
5 | "mime/multipart"
6 | "os"
7 | "path"
8 | )
9 |
10 | // 获取文件大小
11 | func GetSize(f multipart.File) (int, error) {
12 | content, err := ioutil.ReadAll(f)
13 |
14 | return len(content), err
15 | }
16 |
17 | // 获取文件后缀
18 | func GetExt(fileName string) string {
19 | return path.Ext(fileName)
20 | }
21 |
22 | //检查文件是否存在
23 | func CheckExist(src string) bool {
24 | _, err := os.Stat(src)
25 |
26 | return os.IsNotExist(err)
27 | }
28 |
29 | // 检查文件权限
30 | func CheckPermission(src string) bool {
31 | _, err := os.Stat(src)
32 |
33 | return os.IsPermission(err)
34 | }
35 |
36 | //如果不存在则新建文件夹
37 | func IsNotExistMkDir(src string) error {
38 | if exist := CheckExist(src); exist == false {
39 | if err := MkDir(src); err != nil {
40 | return err
41 | }
42 | }
43 |
44 | return nil
45 | }
46 |
47 | //新建文件夹
48 | func MkDir(src string) error {
49 | err := os.MkdirAll(src, os.ModePerm)
50 | if err != nil {
51 | return err
52 | }
53 |
54 | return nil
55 | }
56 |
57 | // 打开文件
58 | func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
59 | f, err := os.OpenFile(name, flag, perm)
60 | if err != nil {
61 | return nil, err
62 | }
63 |
64 | return f, nil
65 | }
66 |
--------------------------------------------------------------------------------
/router/dashboard/dashboard.go:
--------------------------------------------------------------------------------
1 | package dashboard
2 |
3 | import (
4 | "ferry/apis/dashboard"
5 | "ferry/middleware"
6 | jwt "ferry/pkg/jwtauth"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | func RegisterDashboardRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
16 | classify := v1.Group("/dashboard").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
17 | {
18 | classify.GET("", dashboard.InitData)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/router/init_router.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | "ferry/handler"
5 | "ferry/middleware"
6 | _ "ferry/pkg/jwtauth"
7 | "ferry/tools"
8 | config2 "ferry/tools/config"
9 |
10 | "github.com/gin-gonic/gin"
11 | )
12 |
13 | func InitRouter() *gin.Engine {
14 |
15 | r := gin.New()
16 | if config2.ApplicationConfig.IsHttps {
17 | r.Use(handler.TlsHandler())
18 | }
19 | middleware.InitMiddleware(r)
20 | // the jwt middleware
21 | authMiddleware, err := middleware.AuthInit()
22 | tools.HasError(err, "JWT Init Error", 500)
23 |
24 | // 注册系统路由
25 | InitSysRouter(r, authMiddleware)
26 |
27 | return r
28 | }
29 |
--------------------------------------------------------------------------------
/router/process/classify.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 |
7 | import (
8 | "ferry/apis/process"
9 | "ferry/middleware"
10 | jwt "ferry/pkg/jwtauth"
11 |
12 | "github.com/gin-gonic/gin"
13 | )
14 |
15 | func RegisterClassifyRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
16 | classify := v1.Group("/classify").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
17 | {
18 | classify.GET("", process.ClassifyList)
19 | classify.POST("", process.CreateClassify)
20 | classify.PUT("", process.UpdateClassify)
21 | classify.DELETE("", process.DeleteClassify)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/router/process/process.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | /*
4 | @Author : lanyulei
5 | */
6 |
7 | import (
8 | "ferry/apis/process"
9 | "ferry/middleware"
10 | jwt "ferry/pkg/jwtauth"
11 |
12 | "github.com/gin-gonic/gin"
13 | )
14 |
15 | func RegisterProcessRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
16 | processRouter := v1.Group("/process").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
17 | {
18 | processRouter.GET("/classify", process.ClassifyProcessList)
19 | processRouter.GET("", process.ProcessList)
20 | processRouter.POST("", process.CreateProcess)
21 | processRouter.PUT("", process.UpdateProcess)
22 | processRouter.DELETE("", process.DeleteProcess)
23 | processRouter.GET("/details", process.ProcessDetails)
24 | processRouter.POST("/clone/:id", process.CloneProcess)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/router/process/task.go:
--------------------------------------------------------------------------------
1 | package process
2 |
3 | import (
4 | "ferry/apis/process"
5 | "ferry/middleware"
6 | jwt "ferry/pkg/jwtauth"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | /*
12 | @Author : lanyulei
13 | */
14 |
15 | func RegisterTaskRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
16 | taskRouter := v1.Group("/task").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
17 | {
18 | taskRouter.GET("", process.TaskList)
19 | taskRouter.GET("/details", process.TaskDetails)
20 | taskRouter.POST("", process.CreateTask)
21 | taskRouter.PUT("", process.UpdateTask)
22 | taskRouter.DELETE("", process.DeleteTask)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/router/process/tpl.go:
--------------------------------------------------------------------------------
1 | /*
2 | @Author : lanyulei
3 | */
4 |
5 | package process
6 |
7 | import (
8 | "ferry/apis/process"
9 | "ferry/middleware"
10 |
11 | //"ferry/apis/process"
12 | //"ferry/middleware"
13 | jwt "ferry/pkg/jwtauth"
14 |
15 | "github.com/gin-gonic/gin"
16 | )
17 |
18 | func RegisterTplRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
19 | tplRouter := v1.Group("/tpl").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
20 | {
21 | tplRouter.GET("", process.TemplateList)
22 | tplRouter.POST("", process.CreateTemplate)
23 | tplRouter.PUT("", process.UpdateTemplate)
24 | tplRouter.DELETE("", process.DeleteTemplate)
25 | tplRouter.GET("/details", process.TemplateDetails)
26 | tplRouter.POST("/clone/:id", process.CloneTemplate)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/router/process/workOrder.go:
--------------------------------------------------------------------------------
1 | /*
2 | @Author : lanyulei
3 | */
4 |
5 | package process
6 |
7 | import (
8 | "ferry/apis/process"
9 | "ferry/middleware"
10 | jwt "ferry/pkg/jwtauth"
11 |
12 | "github.com/gin-gonic/gin"
13 | )
14 |
15 | func RegisterWorkOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
16 | workOrderRouter := v1.Group("/work-order").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
17 | {
18 | workOrderRouter.GET("/process-structure", process.ProcessStructure)
19 | workOrderRouter.POST("/create", process.CreateWorkOrder)
20 | workOrderRouter.GET("/list", process.WorkOrderList)
21 | workOrderRouter.POST("/handle", process.ProcessWorkOrder)
22 | workOrderRouter.GET("/unity", process.UnityWorkOrder)
23 | workOrderRouter.POST("/inversion", process.InversionWorkOrder)
24 | workOrderRouter.GET("/urge", process.UrgeWorkOrder)
25 | workOrderRouter.PUT("/active-order/:id", process.ActiveOrder)
26 | workOrderRouter.DELETE("/delete/:id", process.DeleteWorkOrder)
27 | workOrderRouter.POST("/reopen/:id", process.ReopenWorkOrder)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/static/scripts/echo_test-4171bc7f4a05-admin.sh:
--------------------------------------------------------------------------------
1 | echo "test"
--------------------------------------------------------------------------------
/static/scripts/print_hello_world-d266ee2a8029-admin.py:
--------------------------------------------------------------------------------
1 | print("Hello, World!")
--------------------------------------------------------------------------------
/static/template/email.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ferry
6 |
7 |
8 |
9 | {{ .Description }}:
10 |
11 |
12 |
13 |
14 | 标题: |
15 | {{ .Title }} |
16 |
17 |
18 | 申请人: |
19 | {{ .Creator }} |
20 |
21 |
22 | 优先级: |
23 | {{ .PriorityValue }} |
24 |
25 |
26 | 申请时间: |
27 | {{ .CreatedAt }} |
28 |
29 |
30 |
31 |
32 | 点击此处跳转到工单详情
33 |
34 |
44 |
--------------------------------------------------------------------------------
/static/web/036680d9c1d332cf478c5823cd2a47db.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/groovy"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/06d453ace473034cd357edb758d539ab.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/csound_document",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# \n\
5 | snippet synth\n\
6 | \n\
7 | \n\
8 | ${1}\n\
9 | \n\
10 | \n\
11 | e\n\
12 | \n\
13 | \n\
14 | ";
15 | exports.scope = "csound_document";
16 |
17 | }); (function() {
18 | ace.require(["ace/snippets/csound_document"], function(m) {
19 | if (typeof module == "object" && typeof exports == "object" && module) {
20 | module.exports = m;
21 | }
22 | });
23 | })();
24 |
--------------------------------------------------------------------------------
/static/web/0870bcf868f8d64dc9a6226a6c8b341d.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/snippets",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# snippets for making snippets :)\n\
5 | snippet snip\n\
6 | snippet ${1:trigger}\n\
7 | ${2}\n\
8 | snippet msnip\n\
9 | snippet ${1:trigger} ${2:description}\n\
10 | ${3}\n\
11 | snippet v\n\
12 | {VISUAL}\n\
13 | ";
14 | exports.scope = "snippets";
15 |
16 | }); (function() {
17 | ace.require(["ace/snippets/snippets"], function(m) {
18 | if (typeof module == "object" && typeof exports == "object" && module) {
19 | module.exports = m;
20 | }
21 | });
22 | })();
23 |
--------------------------------------------------------------------------------
/static/web/0c2b3b3b66a73e289e2ca47cf22ef150.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/csp"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/0dc486b4415f7cbd7ddde8f32b6f12f1.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/drools",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "\n\
5 | snippet rule\n\
6 | rule \"${1?:rule_name}\"\n\
7 | when\n\
8 | ${2:// when...} \n\
9 | then\n\
10 | ${3:// then...}\n\
11 | end\n\
12 | \n\
13 | snippet query\n\
14 | query ${1?:query_name}\n\
15 | ${2:// find} \n\
16 | end\n\
17 | \n\
18 | snippet declare\n\
19 | declare ${1?:type_name}\n\
20 | ${2:// attributes} \n\
21 | end\n\
22 | \n\
23 | ";
24 | exports.scope = "drools";
25 |
26 | }); (function() {
27 | ace.require(["ace/snippets/drools"], function(m) {
28 | if (typeof module == "object" && typeof exports == "object" && module) {
29 | module.exports = m;
30 | }
31 | });
32 | })();
33 |
--------------------------------------------------------------------------------
/static/web/0dd0f45c3dde9af3fcf9706e6a2a1edd.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/slim"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/119d8ff08e82b0f391f59f1fe657130f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/verilog"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1295d4470d348d3ff8ea442b1dcef3d3.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/maze",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet >\n\
5 | description assignment\n\
6 | scope maze\n\
7 | -> ${1}= ${2}\n\
8 | \n\
9 | snippet >\n\
10 | description if\n\
11 | scope maze\n\
12 | -> IF ${2:**} THEN %${3:L} ELSE %${4:R}\n\
13 | ";
14 | exports.scope = "maze";
15 |
16 | }); (function() {
17 | ace.require(["ace/snippets/maze"], function(m) {
18 | if (typeof module == "object" && typeof exports == "object" && module) {
19 | module.exports = m;
20 | }
21 | });
22 | })();
23 |
--------------------------------------------------------------------------------
/static/web/13b157cfddcb9a76ae0800b47a8f0122.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/handlebars"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/142d258626093a8c3187029538e32bbc.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/stylus"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/144991c48dbba89bfe10e886aaaed32a.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/sql",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet tbl\n\
5 | create table ${1:table} (\n\
6 | ${2:columns}\n\
7 | );\n\
8 | snippet col\n\
9 | ${1:name} ${2:type} ${3:default ''} ${4:not null}\n\
10 | snippet ccol\n\
11 | ${1:name} varchar2(${2:size}) ${3:default ''} ${4:not null}\n\
12 | snippet ncol\n\
13 | ${1:name} number ${3:default 0} ${4:not null}\n\
14 | snippet dcol\n\
15 | ${1:name} date ${3:default sysdate} ${4:not null}\n\
16 | snippet ind\n\
17 | create index ${3:$1_$2} on ${1:table}(${2:column});\n\
18 | snippet uind\n\
19 | create unique index ${1:name} on ${2:table}(${3:column});\n\
20 | snippet tblcom\n\
21 | comment on table ${1:table} is '${2:comment}';\n\
22 | snippet colcom\n\
23 | comment on column ${1:table}.${2:column} is '${3:comment}';\n\
24 | snippet addcol\n\
25 | alter table ${1:table} add (${2:column} ${3:type});\n\
26 | snippet seq\n\
27 | create sequence ${1:name} start with ${2:1} increment by ${3:1} minvalue ${4:1};\n\
28 | snippet s*\n\
29 | select * from ${1:table}\n\
30 | ";
31 | exports.scope = "sql";
32 |
33 | }); (function() {
34 | ace.require(["ace/snippets/sql"], function(m) {
35 | if (typeof module == "object" && typeof exports == "object" && module) {
36 | module.exports = m;
37 | }
38 | });
39 | })();
40 |
--------------------------------------------------------------------------------
/static/web/155500be4d3113e94dca99f997defb7a.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/sparql"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/17c85759d562794da4d2ff11f1b9b3bd.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/julia"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1840080076c4078d157a5b05d0d95551.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/objectivec"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/18a893070398343ab529fdb7b62f1b6d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/less"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1afe87852eca4b28294075c659ff8c45.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/apex"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1c9874850164cfdaa7e1d212d09124a7.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/tsx"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1cb8df3a3416707163473b1ee9268faf.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/livescript"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/1f1abd5e247cf6b2e9a3db6303277572.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/batchfile"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/2031467f3d02be43b638c5e3ccba3996.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/scala"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/20f8061729d26f9786679bbf7af0b87a.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/gherkin"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/214a729dcea91ee8a56f8ef43e17243a.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/cobol"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/21dca974f7343f200597e43a55766c6e.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mushcode"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/21fab653998af15bced8d4890e41bebc.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/perl6"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/242fb5a92733d151e9ca303fcd3ae7ff.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/scss"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/2681042a598b029b51d51f7669b81c4d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/text"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/28f7c5b28bbad7b0bac0cc3cc5b89bad.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/red"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/2ac58492ad5a1b5244deb0fef1e5a773.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/sass"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/2bba99eb717e1aa22e45284a964ca73f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/pig"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/31459a657ac30dcaa54765c6d76d8c81.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/soy_template"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/318f90759f2ff0d2a437350e87578172.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/dot"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/31bcb02e59d84ce2e38b85616a0b44db.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/redshift"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/31f3f1c32b27587832d28b634351325c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/forth"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/330543be2120b9dcc9bec41ba5e05805.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/json5"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/34f05dc84111ffe37a1d5b5aacff7488.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/jade"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/35858a47038a7be957df49854e8e5eea.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/elixir"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/35dc4119f9e28cb9baba1475537460bb.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/visualforce"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/37e37aa178d97ffcd94eeee1e1a25967.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/abc",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "\n\
5 | snippet zupfnoter.print\n\
6 | %%%%hn.print {\"startpos\": ${1:pos_y}, \"t\":\"${2:title}\", \"v\":[${3:voices}], \"s\":[[${4:syncvoices}1,2]], \"f\":[${5:flowlines}], \"sf\":[${6:subflowlines}], \"j\":[${7:jumplines}]}\n\
7 | \n\
8 | snippet zupfnoter.note\n\
9 | %%%%hn.note {\"pos\": [${1:pos_x},${2:pos_y}], \"text\": \"${3:text}\", \"style\": \"${4:style}\"}\n\
10 | \n\
11 | snippet zupfnoter.annotation\n\
12 | %%%%hn.annotation {\"id\": \"${1:id}\", \"pos\": [${2:pos}], \"text\": \"${3:text}\"}\n\
13 | \n\
14 | snippet zupfnoter.lyrics\n\
15 | %%%%hn.lyrics {\"pos\": [${1:x_pos},${2:y_pos}]}\n\
16 | \n\
17 | snippet zupfnoter.legend\n\
18 | %%%%hn.legend {\"pos\": [${1:x_pos},${2:y_pos}]}\n\
19 | \n\
20 | \n\
21 | \n\
22 | snippet zupfnoter.target\n\
23 | \"^:${1:target}\"\n\
24 | \n\
25 | snippet zupfnoter.goto\n\
26 | \"^@${1:target}@${2:distance}\"\n\
27 | \n\
28 | snippet zupfnoter.annotationref\n\
29 | \"^#${1:target}\"\n\
30 | \n\
31 | snippet zupfnoter.annotation\n\
32 | \"^!${1:text}@${2:x_offset},${3:y_offset}\"\n\
33 | \n\
34 | \n\
35 | ";
36 | exports.scope = "abc";
37 |
38 | }); (function() {
39 | ace.require(["ace/snippets/abc"], function(m) {
40 | if (typeof module == "object" && typeof exports == "object" && module) {
41 | module.exports = m;
42 | }
43 | });
44 | })();
45 |
--------------------------------------------------------------------------------
/static/web/38528de2a5c097da375fd0a076667441.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/matlab"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3baeab62d681338ba3287f0a50e5dad1.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/gitignore"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3c58f68d787710c79906a2cd6d248295.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/yaml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3cab7110c6a090f72c540dcc1cfbe3b5.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/csound_score"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3cce0c7e1a8e1148f97de59a4b1ee73f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/lisp"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3cf64ec91a700bfa1dece0957c49c7dc.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/autohotkey"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/3e6808cd6eefd1be1040403985581374.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/prolog"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/40505d6c2f34fc08502d3e596573c7f8.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/xml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/41f85ea0c545f0539b6ae2753eb1f79c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/smarty"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/43a9bcfc200d80676bc68fe9a3c8ab6d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mysql"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/4705b919138245a5b454d25f8e418435.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/rst",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# rst\n\
5 | \n\
6 | snippet :\n\
7 | :${1:field name}: ${2:field body}\n\
8 | snippet *\n\
9 | *${1:Emphasis}*\n\
10 | snippet **\n\
11 | **${1:Strong emphasis}**\n\
12 | snippet _\n\
13 | \\`${1:hyperlink-name}\\`_\n\
14 | .. _\\`$1\\`: ${2:link-block}\n\
15 | snippet =\n\
16 | ${1:Title}\n\
17 | =====${2:=}\n\
18 | ${3}\n\
19 | snippet -\n\
20 | ${1:Title}\n\
21 | -----${2:-}\n\
22 | ${3}\n\
23 | snippet cont:\n\
24 | .. contents::\n\
25 | \n\
26 | ";
27 | exports.scope = "rst";
28 |
29 | }); (function() {
30 | ace.require(["ace/snippets/rst"], function(m) {
31 | if (typeof module == "object" && typeof exports == "object" && module) {
32 | module.exports = m;
33 | }
34 | });
35 | })();
36 |
--------------------------------------------------------------------------------
/static/web/47cd5c7d174e6b624e55510c4e503600.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/fsl",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText =undefined;
5 | exports.scope = "";
6 |
7 | }); (function() {
8 | ace.require(["ace/snippets/fsl"], function(m) {
9 | if (typeof module == "object" && typeof exports == "object" && module) {
10 | module.exports = m;
11 | }
12 | });
13 | })();
14 |
--------------------------------------------------------------------------------
/static/web/4cbd6f8a4f52821c1d3476139078797d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/powershell"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/4d694d41a0c1b3eaad752a8352c5661c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/logtalk"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/5094b30d2471cc7312746173d8a4bb25.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/plain_text"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/51e6918f996813eafa4b1491d9dd343b.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/mode/plain_text",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/behaviour"], function(require, exports, module) {
2 | "use strict";
3 |
4 | var oop = require("../lib/oop");
5 | var TextMode = require("./text").Mode;
6 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
7 | var Behaviour = require("./behaviour").Behaviour;
8 |
9 | var Mode = function() {
10 | this.HighlightRules = TextHighlightRules;
11 | this.$behaviour = new Behaviour();
12 | };
13 |
14 | oop.inherits(Mode, TextMode);
15 |
16 | (function() {
17 | this.type = "text";
18 | this.getNextLineIndent = function(state, line, tab) {
19 | return '';
20 | };
21 | this.$id = "ace/mode/plain_text";
22 | }).call(Mode.prototype);
23 |
24 | exports.Mode = Mode;
25 | }); (function() {
26 | ace.require(["ace/mode/plain_text"], function(m) {
27 | if (typeof module == "object" && typeof exports == "object" && module) {
28 | module.exports = m;
29 | }
30 | });
31 | })();
32 |
--------------------------------------------------------------------------------
/static/web/51e6ccd3ea9d7443949b155b113eebd5.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/puppet"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/540bba54b49ea7a6ec513270449132db.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/php_laravel_blade"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/553aa6bb3b625428f4df57f5885d50f3.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/hjson"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/57c2d2eb6a844a8c9ecd932c6d4067b0.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/assembly_x86"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/5bd58f2ebad7e63ff72a891fb43e2b38.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/svg"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/5eeee1acc01b04328cf42db0715bb7f5.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/pgsql"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/5f6f5026d13b2a9b884a8144a119cf9e.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/vbscript"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/60fc15a66fa7ba74ccd248f85b50fbe5.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/aql"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/64f93b6b093bba4147485023263cf65f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/ada"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/68cf9a0e1eaff7cc991e970a855108f8.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/nim"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/697c2df91bf7c729d317c620a3cd77bd.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/scad"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/6e88d3943f4c3a068493aad131cd4898.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/gcode"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/6e9ca56e0fa3e784eab3da45f8d0d8ac.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/rust"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/6f0543453c605ea6d673a3bd31dd1090.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/rhtml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/727184c92f9da8d8b0c013fd79cf32fe.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/haxe"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/74973bbb728e661679e49a16773535a4.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/haml",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet t\n\
5 | %table\n\
6 | %tr\n\
7 | %th\n\
8 | ${1:headers}\n\
9 | %tr\n\
10 | %td\n\
11 | ${2:headers}\n\
12 | snippet ul\n\
13 | %ul\n\
14 | %li\n\
15 | ${1:item}\n\
16 | %li\n\
17 | snippet =rp\n\
18 | = render :partial => '${1:partial}'\n\
19 | snippet =rpl\n\
20 | = render :partial => '${1:partial}', :locals => {}\n\
21 | snippet =rpc\n\
22 | = render :partial => '${1:partial}', :collection => @$1\n\
23 | \n\
24 | ";
25 | exports.scope = "haml";
26 |
27 | }); (function() {
28 | ace.require(["ace/snippets/haml"], function(m) {
29 | if (typeof module == "object" && typeof exports == "object" && module) {
30 | module.exports = m;
31 | }
32 | });
33 | })();
34 |
--------------------------------------------------------------------------------
/static/web/7af5865535fb306e7d0364a9ff81f389.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/diff",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# DEP-3 (http://dep.debian.net/deps/dep3/) style patch header\n\
5 | snippet header DEP-3 style header\n\
6 | Description: ${1}\n\
7 | Origin: ${2:vendor|upstream|other}, ${3:url of the original patch}\n\
8 | Bug: ${4:url in upstream bugtracker}\n\
9 | Forwarded: ${5:no|not-needed|url}\n\
10 | Author: ${6:`g:snips_author`}\n\
11 | Reviewed-by: ${7:name and email}\n\
12 | Last-Update: ${8:`strftime(\"%Y-%m-%d\")`}\n\
13 | Applied-Upstream: ${9:upstream version|url|commit}\n\
14 | \n\
15 | ";
16 | exports.scope = "diff";
17 |
18 | }); (function() {
19 | ace.require(["ace/snippets/diff"], function(m) {
20 | if (typeof module == "object" && typeof exports == "object" && module) {
21 | module.exports = m;
22 | }
23 | });
24 | })();
25 |
--------------------------------------------------------------------------------
/static/web/7cef38946c33fa981d6d2c86c62428e0.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/fsharp"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/7d46cd8e5efaac33d5bf823ed4268841.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/c9search"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/7e98c4d98664d6f7bcc52a07f21a1f9f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/html_elixir"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/7f10fe526aec57bd522af77ea6ac2b62.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/dockerfile"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/817d52a47a4657b8a4dab79e057f5fb0.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/cirru"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/833b242747fd7b098d46011e4289bc3f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/abap"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/83ea78d42f1a8e5f7346f3a30140ebfb.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/apache_conf"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/867fb2b26eef123915aff8634c0bbf4a.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/glsl"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/8681f562786fa45bebe8ee7ed2461026.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/textile",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# Jekyll post header\n\
5 | snippet header\n\
6 | ---\n\
7 | title: ${1:title}\n\
8 | layout: post\n\
9 | date: ${2:date} ${3:hour:minute:second} -05:00\n\
10 | ---\n\
11 | \n\
12 | # Image\n\
13 | snippet img\n\
14 | !${1:url}(${2:title}):${3:link}!\n\
15 | \n\
16 | # Table\n\
17 | snippet |\n\
18 | |${1}|${2}\n\
19 | \n\
20 | # Link\n\
21 | snippet link\n\
22 | \"${1:link text}\":${2:url}\n\
23 | \n\
24 | # Acronym\n\
25 | snippet (\n\
26 | (${1:Expand acronym})${2}\n\
27 | \n\
28 | # Footnote\n\
29 | snippet fn\n\
30 | [${1:ref number}] ${3}\n\
31 | \n\
32 | fn$1. ${2:footnote}\n\
33 | \n\
34 | ";
35 | exports.scope = "textile";
36 |
37 | }); (function() {
38 | ace.require(["ace/snippets/textile"], function(m) {
39 | if (typeof module == "object" && typeof exports == "object" && module) {
40 | module.exports = m;
41 | }
42 | });
43 | })();
44 |
--------------------------------------------------------------------------------
/static/web/8833a126ef9d8892bfb372d227f7f088.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/lucene"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/8870430db332faf22d90e12f1620ee84.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/turtle"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/89859a411a50c90f1e669deaf8a6775f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/jssm"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/89a47a0051ac0b3885ef8af2476526f0.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/asl"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/90643b9da87302fef490f3f48af806e2.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/asciidoc"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/92cf63e9a949f08d97a74d9ed17392ed.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/qml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/94a0179602c94d55621a35e41c97ed5c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/haskell_cabal"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/985b400088bf5e23fb83e70d9948eccb.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/nix"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/998c5f13555e18b42e9bf826578b2e16.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/praat"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/9c202aefac35a5ff49d3d3795e9932bc.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/html_ruby"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/9d0f4f65be2f50ad54488089f126feda.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/eiffel"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/9e357a97da26127713394684a51946b8.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/nunjucks"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/9e69cb39701c3578226b39536edd4dd7.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/twig"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/a26463d029a2515171748a1ebcca53c3.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/ocaml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/a311e02008e0f00a37305a12d479159a.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/coldfusion"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/aa2f98073a8d9f266f3928b5d9c457d1.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/lua",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet #!\n\
5 | #!/usr/bin/env lua\n\
6 | $1\n\
7 | snippet local\n\
8 | local ${1:x} = ${2:1}\n\
9 | snippet fun\n\
10 | function ${1:fname}(${2:...})\n\
11 | ${3:-- body}\n\
12 | end\n\
13 | snippet for\n\
14 | for ${1:i}=${2:1},${3:10} do\n\
15 | ${4:print(i)}\n\
16 | end\n\
17 | snippet forp\n\
18 | for ${1:i},${2:v} in pairs(${3:table_name}) do\n\
19 | ${4:-- body}\n\
20 | end\n\
21 | snippet fori\n\
22 | for ${1:i},${2:v} in ipairs(${3:table_name}) do\n\
23 | ${4:-- body}\n\
24 | end\n\
25 | ";
26 | exports.scope = "lua";
27 |
28 | }); (function() {
29 | ace.require(["ace/snippets/lua"], function(m) {
30 | if (typeof module == "object" && typeof exports == "object" && module) {
31 | module.exports = m;
32 | }
33 | });
34 | })();
35 |
--------------------------------------------------------------------------------
/static/web/ab16c1237e6e04bbf0024ee2bae42130.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/d"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/acc30207efba7ab5b7b509b599f37e6f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/nsis"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/acc7448b80728a73c9a4046b3ec4407f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/golang"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/adbb57fa182dce548204311d3be6dffa.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/jack"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/b02513e1d0cc664936e1ba9cb5a923af.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/logiql"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/b131314d1ea62fa7bba91a4da8360298.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/zeek"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/b26738d581e044c69f7a4392906e6843.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/makefile",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet ifeq\n\
5 | ifeq (${1:cond0},${2:cond1})\n\
6 | ${3:code}\n\
7 | endif\n\
8 | ";
9 | exports.scope = "makefile";
10 |
11 | }); (function() {
12 | ace.require(["ace/snippets/makefile"], function(m) {
13 | if (typeof module == "object" && typeof exports == "object" && module) {
14 | module.exports = m;
15 | }
16 | });
17 | })();
18 |
--------------------------------------------------------------------------------
/static/web/b435aebcb57d65080cfd510e0a9d5d9d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/prisma"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/b830d88aa22a866a208be27af90526a7.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/swift"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/bae95bdb1bbcc0969e0e40fb72539df3.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/applescript"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/bbd62124f6d03e01eb4332f55ead999d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/ext/error_marker"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/bc26ab0797e975ba01e701683935864b.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/fortran"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/bd98610e395f3b4c7915cf3fbe854f6f.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/csound_orchestra",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# else\n\
5 | snippet else\n\
6 | else\n\
7 | ${1:/* statements */}\n\
8 | # elseif\n\
9 | snippet elseif\n\
10 | elseif ${1:/* condition */} then\n\
11 | ${2:/* statements */}\n\
12 | # if\n\
13 | snippet if\n\
14 | if ${1:/* condition */} then\n\
15 | ${2:/* statements */}\n\
16 | endif\n\
17 | # instrument block\n\
18 | snippet instr\n\
19 | instr ${1:name}\n\
20 | ${2:/* statements */}\n\
21 | endin\n\
22 | # i-time while loop\n\
23 | snippet iwhile\n\
24 | i${1:Index} = ${2:0}\n\
25 | while i${1:Index} < ${3:/* count */} do\n\
26 | ${4:/* statements */}\n\
27 | i${1:Index} += 1\n\
28 | od\n\
29 | # k-rate while loop\n\
30 | snippet kwhile\n\
31 | k${1:Index} = ${2:0}\n\
32 | while k${1:Index} < ${3:/* count */} do\n\
33 | ${4:/* statements */}\n\
34 | k${1:Index} += 1\n\
35 | od\n\
36 | # opcode\n\
37 | snippet opcode\n\
38 | opcode ${1:name}, ${2:/* output types */ 0}, ${3:/* input types */ 0}\n\
39 | ${4:/* statements */}\n\
40 | endop\n\
41 | # until loop\n\
42 | snippet until\n\
43 | until ${1:/* condition */} do\n\
44 | ${2:/* statements */}\n\
45 | od\n\
46 | # while loop\n\
47 | snippet while\n\
48 | while ${1:/* condition */} do\n\
49 | ${2:/* statements */}\n\
50 | od\n\
51 | ";
52 | exports.scope = "csound_orchestra";
53 |
54 | }); (function() {
55 | ace.require(["ace/snippets/csound_orchestra"], function(m) {
56 | if (typeof module == "object" && typeof exports == "object" && module) {
57 | module.exports = m;
58 | }
59 | });
60 | })();
61 |
--------------------------------------------------------------------------------
/static/web/be2fbe775b19bdc18e4f78de18beb433.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/velocity",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# macro\n\
5 | snippet #macro\n\
6 | #macro ( ${1:macroName} ${2:\\$var1, [\\$var2, ...]} )\n\
7 | ${3:## macro code}\n\
8 | #end\n\
9 | # foreach\n\
10 | snippet #foreach\n\
11 | #foreach ( ${1:\\$item} in ${2:\\$collection} )\n\
12 | ${3:## foreach code}\n\
13 | #end\n\
14 | # if\n\
15 | snippet #if\n\
16 | #if ( ${1:true} )\n\
17 | ${0}\n\
18 | #end\n\
19 | # if ... else\n\
20 | snippet #ife\n\
21 | #if ( ${1:true} )\n\
22 | ${2}\n\
23 | #else\n\
24 | ${0}\n\
25 | #end\n\
26 | #import\n\
27 | snippet #import\n\
28 | #import ( \"${1:path/to/velocity/format}\" )\n\
29 | # set\n\
30 | snippet #set\n\
31 | #set ( $${1:var} = ${0} )\n\
32 | ";
33 | exports.scope = "velocity";
34 | exports.includeScopes = ["html", "javascript", "css"];
35 |
36 | }); (function() {
37 | ace.require(["ace/snippets/velocity"], function(m) {
38 | if (typeof module == "object" && typeof exports == "object" && module) {
39 | module.exports = m;
40 | }
41 | });
42 | })();
43 |
--------------------------------------------------------------------------------
/static/web/c23b1f80ab9746b425f3848bdaacc144.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/rdoc"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c38a3226f3858a47ba9fb788dc7b44fc.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/ini"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c3b0cd15adcc12a549e7ac5d165ac1f4.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/vhdl"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c6d4a590e14107a8a5ad505d66241032.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/csharp"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c6f608398c43e25821557ee65cda5e58.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/pascal"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c7d3b0afe7600a632fbf44ee8d84996e.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mixal"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/c7fb0ccebacccfb5c2f7b2f6023ebe4a.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/graphqlschema",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "# Type Snippet\n\
5 | trigger type\n\
6 | snippet type\n\
7 | type ${1:type_name} {\n\
8 | ${2:type_siblings}\n\
9 | }\n\
10 | \n\
11 | # Input Snippet\n\
12 | trigger input\n\
13 | snippet input\n\
14 | input ${1:input_name} {\n\
15 | ${2:input_siblings}\n\
16 | }\n\
17 | \n\
18 | # Interface Snippet\n\
19 | trigger interface\n\
20 | snippet interface\n\
21 | interface ${1:interface_name} {\n\
22 | ${2:interface_siblings}\n\
23 | }\n\
24 | \n\
25 | # Interface Snippet\n\
26 | trigger union\n\
27 | snippet union\n\
28 | union ${1:union_name} = ${2:type} | ${3: type}\n\
29 | \n\
30 | # Enum Snippet\n\
31 | trigger enum\n\
32 | snippet enum\n\
33 | enum ${1:enum_name} {\n\
34 | ${2:enum_siblings}\n\
35 | }\n\
36 | ";
37 | exports.scope = "graphqlschema";
38 |
39 | }); (function() {
40 | ace.require(["ace/snippets/graphqlschema"], function(m) {
41 | if (typeof module == "object" && typeof exports == "object" && module) {
42 | module.exports = m;
43 | }
44 | });
45 | })();
46 |
--------------------------------------------------------------------------------
/static/web/ca1483809659f6c87cc6f588891d2bd4.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mel"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/cf0a04afa21ac9ba23a1de0416a03105.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/scheme"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/css/chunk-05a99c67.b1dd7a76.css:
--------------------------------------------------------------------------------
1 | .errPage-container[data-v-35ca77fc]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-35ca77fc]{background:#008489;color:#fff;border:none!important}.errPage-container .pan-gif[data-v-35ca77fc]{margin:0 auto;display:block}.errPage-container .pan-img[data-v-35ca77fc]{display:block;margin:0 auto;width:100%}.errPage-container .text-jumbo[data-v-35ca77fc]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-35ca77fc]{font-size:14px}.errPage-container .list-unstyled li[data-v-35ca77fc]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-35ca77fc]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-35ca77fc]:hover{text-decoration:underline}
--------------------------------------------------------------------------------
/static/web/d465c0a35c6ef244bf587b0e6bdb4019.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/terraform"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/d750a8dbf9dd09c0a33b9986e79e3c8c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mediawiki"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/d754905fe54aac6f3c350df34f51a0b6.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/ejs"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/d7889907dbb51f58ceadb3e1eec03a5d.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/mask"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/dd40dfc7840568927fdef65087a233ed.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/properties"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/e0e2b1267a5d4acb4dda3a4a598cd8a5.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/curly"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/e1dbe800b2d3f5d74b2b5480ea2b897a.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/razor",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText = "snippet if\n\
5 | (${1} == ${2}) {\n\
6 | ${3}\n\
7 | }";
8 | exports.scope = "razor";
9 |
10 | }); (function() {
11 | ace.require(["ace/snippets/razor"], function(m) {
12 | if (typeof module == "object" && typeof exports == "object" && module) {
13 | module.exports = m;
14 | }
15 | });
16 | })();
17 |
--------------------------------------------------------------------------------
/static/web/e2792218bae78a6aef6764de4e61fd82.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/json"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/e4d51c8b4202d444cb39db4e7642d7d9.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/crystal"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/e745f8fb4f054a3f5b66ccad100a1217.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/latex"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/efc508c36f4e417ec6bd5ec72989443b.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/ftl"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f2195d2eae3dbef7e3798e115209dcd7.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/nginx"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f2cfc0e604350e23bfcd7c78165b1411.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/jsx"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f3a0f6e7e442de2ae51eddbf4eb98d97.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/mode/text"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f50d7c4ce743ce495230d19bd33fefab.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/space"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f5292be525fc36a337ce7bfb792070de.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/luapage"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f61f1aaed3f32a7dabd977a6f47ecd5f.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/protobuf"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f7443e8232a7e4289b9f2ed4a512750c.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/kotlin"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f80c6eb0f52a68464b21211240e3d6e6.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/elm"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/f88127ad8950e3c94c3af6c65a7120fa.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/toml"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/fa1618cda4da7d5362c381ea2d5f7321.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/typescript"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/faf460076b3383fdc3ecc224068964cf.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/sjs"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/favicon.ico
--------------------------------------------------------------------------------
/static/web/fffbc895129cdb3efeafa5b234743aa0.js:
--------------------------------------------------------------------------------
1 |
2 | ; (function() {
3 | ace.require(["ace/snippets/alda"], function(m) {
4 | if (typeof module == "object" && typeof exports == "object" && module) {
5 | module.exports = m;
6 | }
7 | });
8 | })();
9 |
--------------------------------------------------------------------------------
/static/web/fonts/eiconfont.016bbe3f.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/eiconfont.016bbe3f.woff
--------------------------------------------------------------------------------
/static/web/fonts/eiconfont.0ff67604.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/eiconfont.0ff67604.ttf
--------------------------------------------------------------------------------
/static/web/fonts/eiconfont.ae6bc167.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/eiconfont.ae6bc167.eot
--------------------------------------------------------------------------------
/static/web/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/static/web/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/static/web/fonts/fontawesome-webfont.674f50d2.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/fontawesome-webfont.674f50d2.eot
--------------------------------------------------------------------------------
/static/web/fonts/fontawesome-webfont.af7ae505.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/fontawesome-webfont.af7ae505.woff2
--------------------------------------------------------------------------------
/static/web/fonts/fontawesome-webfont.b06871f2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/fontawesome-webfont.b06871f2.ttf
--------------------------------------------------------------------------------
/static/web/fonts/fontawesome-webfont.fee66e71.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/fontawesome-webfont.fee66e71.woff
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.34ea3475.34ea3475.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.34ea3475.34ea3475.woff
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.34ea3475.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.34ea3475.woff
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.4d5a9051.4d5a9051.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.4d5a9051.4d5a9051.ttf
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.4d5a9051.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.4d5a9051.ttf
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.8efbc988.8efbc988.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.8efbc988.8efbc988.eot
--------------------------------------------------------------------------------
/static/web/fonts/iconfont.8efbc988.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/fonts/iconfont.8efbc988.eot
--------------------------------------------------------------------------------
/static/web/img/401.089007e7.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/img/401.089007e7.gif
--------------------------------------------------------------------------------
/static/web/img/404.a57b6f31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/img/404.a57b6f31.png
--------------------------------------------------------------------------------
/static/web/img/404_cloud.0f4bc32b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/img/404_cloud.0f4bc32b.png
--------------------------------------------------------------------------------
/static/web/img/end.9687f898.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/static/web/img/exclusive-gateway.56b82dfd.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
--------------------------------------------------------------------------------
/static/web/img/icon_java.d3cc233a.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_mail.0f68d5c7.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_message.01031aed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_receive.a6c46918.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_script.07c7423e.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_signal.0e96b3b6.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_timer.b4fcbba6.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/icon_user.2b39cf22.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/web/img/login.ede1cdb8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lanyulei/ferry/fbffecffcbacc0e0572a312656cde8f28af8035b/static/web/img/login.ede1cdb8.png
--------------------------------------------------------------------------------
/static/web/img/parallel-gateway.dfb4ebaf.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
--------------------------------------------------------------------------------
/static/web/img/receive-task.e1131038.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
22 |
--------------------------------------------------------------------------------
/static/web/img/start.894f1842.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/static/web/img/user-task.90bd34cf.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
--------------------------------------------------------------------------------
/static/web/js/chunk-2d2105d3.b54ad484.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2105d3"],{b829:function(n,e,o){"use strict";o.r(e);o("386d");var t,c,a={name:"AuthRedirect",created:function(){var n=window.location.search.slice(1);window.localStorage&&(window.localStorage.setItem("x-admin-oauth-code",n),window.close())},render:function(n){return n()}},d=a,i=o("2877"),l=Object(i["a"])(d,t,c,!1,null,null,null);e["default"]=l.exports}}]);
--------------------------------------------------------------------------------
/static/web/js/chunk-2d230fe7.19def69d.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230fe7"],{ef3c:function(e,r,n){"use strict";n.r(r);n("a481");var t,u,a={created:function(){var e=this.$route,r=e.params,n=e.query,t=r.path;this.$router.replace({path:"/"+t,query:n})},render:function(e){return e()}},c=a,o=n("2877"),p=Object(o["a"])(c,t,u,!1,null,null,null);r["default"]=p.exports}}]);
--------------------------------------------------------------------------------
/static/web/js/chunk-39b1e937.3a2314ea.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-39b1e937"],{"1db4":function(t,s,i){"use strict";i.r(s);var a=function(){var t=this,s=t.$createElement,i=t._self._c||s;return i("div",{staticClass:"wscn-http404-container"},[i("div",{staticClass:"wscn-http404"},[t._m(0),t._v(" "),i("div",{staticClass:"bullshit"},[i("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._v(" "),i("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),t._v(" "),i("div",{staticClass:"bullshit__info"},[t._v("请检查您访问的地址是否正确,通常在切换用户时,若您的用户没有上个用户退出时的页面权限,也会触发此报错,请知悉,或者点击一下按钮返回首页。")]),t._v(" "),i("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("返回首页")])])])])},c=[function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"pic-404"},[a("img",{staticClass:"pic-404__parent",attrs:{src:i("a36b"),alt:"404"}}),t._v(" "),a("img",{staticClass:"pic-404__child left",attrs:{src:i("26fc"),alt:"404"}}),t._v(" "),a("img",{staticClass:"pic-404__child mid",attrs:{src:i("26fc"),alt:"404"}}),t._v(" "),a("img",{staticClass:"pic-404__child right",attrs:{src:i("26fc"),alt:"404"}})])}],l={name:"Page404",computed:{message:function(){return"抱歉,您找的页面不存在。"}}},e=l,n=(i("3f88"),i("2877")),_=Object(n["a"])(e,a,c,!1,null,"171d498a",null);s["default"]=_.exports},"26fc":function(t,s,i){t.exports=i.p+"static/web/img/404_cloud.0f4bc32b.png"},"3f88":function(t,s,i){"use strict";i("6b50")},"6b50":function(t,s,i){},a36b:function(t,s,i){t.exports=i.p+"static/web/img/404.a57b6f31.png"}}]);
--------------------------------------------------------------------------------
/template/js.go.template:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | // 查询{{.ClassName}}列表
4 | export function list{{.ClassName}}(query) {
5 | return request({
6 | url: '/api/v1/{{.ModuleName}}List',
7 | method: 'get',
8 | params: query
9 | })
10 | }
11 |
12 | // 查询{{.ClassName}}详细
13 | export function get{{.ClassName}} ({{.PkJsonField}}) {
14 | return request({
15 | url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}},
16 | method: 'get'
17 | })
18 | }
19 |
20 |
21 | // 新增{{.ClassName}}
22 | export function add{{.ClassName}}(data) {
23 | return request({
24 | url: '/api/v1/{{.ModuleName}}',
25 | method: 'post',
26 | data: data
27 | })
28 | }
29 |
30 | // 修改{{.ClassName}}
31 | export function update{{.ClassName}}(data) {
32 | return request({
33 | url: '/api/v1/{{.ModuleName}}',
34 | method: 'put',
35 | data: data
36 | })
37 | }
38 |
39 | // 删除{{.ClassName}}
40 | export function del{{.ClassName}}({{.PkJsonField}}) {
41 | return request({
42 | url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}},
43 | method: 'delete'
44 | })
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/template/router.go.template:
--------------------------------------------------------------------------------
1 |
2 | // 需认证的路由代码
3 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
4 |
5 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
6 | {
7 | r.GET("/:{{.PkJsonField}}", {{.ModuleName}}.Get{{.ClassName}})
8 | r.POST("", {{.ModuleName}}.Insert{{.ClassName}})
9 | r.PUT("", {{.ModuleName}}.Update{{.ClassName}})
10 | r.DELETE("/:{{.PkJsonField}}", {{.ModuleName}}.Delete{{.ClassName}})
11 | }
12 |
13 | l := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
14 | {
15 | l.GET("/{{.ModuleName}}List",{{.ModuleName}}.Get{{.ClassName}}List)
16 | }
17 |
18 | }
19 |
20 | // 无需认证的路由代码
21 | func register{{.ClassName}}Router(v1 *gin.RouterGroup) {
22 |
23 | v1.GET("/{{.ModuleName}}List",{{.ModuleName}}.Get{{.ClassName}}List)
24 |
25 | r := v1.Group("/{{.ModuleName}}")
26 | {
27 | r.GET("/:{{.PkJsonField}}", {{.ModuleName}}.Get{{.ClassName}})
28 | r.POST("", {{.ModuleName}}.Insert{{.ClassName}})
29 | r.PUT("", {{.ModuleName}}.Update{{.ClassName}})
30 | r.DELETE("/:{{.PkJsonField}}", {{.ModuleName}}.Delete{{.ClassName}})
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/tools/app/model.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | type Response struct {
4 | // 代码
5 | Code int `json:"code" example:"200"`
6 | // 数据集
7 | Data interface{} `json:"data"`
8 | // 消息
9 | Msg string `json:"msg"`
10 | }
11 |
12 | type Page struct {
13 | List interface{} `json:"list"`
14 | Count int `json:"count"`
15 | PageIndex int `json:"pageIndex"`
16 | PageSize int `json:"pageSize"`
17 | }
18 |
19 | type PageResponse struct {
20 | // 代码
21 | Code int `json:"code" example:"200"`
22 | // 数据集
23 | Data Page `json:"data"`
24 | // 消息
25 | Msg string `json:"msg"`
26 | }
27 |
28 |
29 | func (res *Response) ReturnOK() *Response {
30 | res.Code = 200
31 | return res
32 | }
33 |
34 | func (res *Response) ReturnError(code int) *Response {
35 | res.Code = code
36 | return res
37 | }
38 |
39 |
40 | func (res *PageResponse) ReturnOK() *PageResponse {
41 | res.Code = 200
42 | return res
43 | }
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/tools/app/msg/message.go:
--------------------------------------------------------------------------------
1 | package msg
2 |
3 | var (
4 | CreatedSuccess = "创建成功!"
5 | UpdatedSuccess = "更新成功!"
6 | DeletedSuccess = "删除成功!"
7 | GetSuccess = "查询成功!"
8 | NotFound = "未找到相关内容或者数据为空!"
9 | )
10 |
--------------------------------------------------------------------------------
/tools/app/return.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "ferry/pkg/logger"
5 | "net/http"
6 |
7 | "github.com/gin-gonic/gin"
8 | )
9 |
10 | // 失败数据处理
11 | func Error(c *gin.Context, code int, err error, msg string) {
12 | var res Response
13 | res.Msg = err.Error()
14 | if msg != "" {
15 | res.Msg = msg
16 | }
17 | logger.Error(res.Msg)
18 | c.JSON(http.StatusOK, res.ReturnError(code))
19 | }
20 |
21 | // 通常成功数据处理
22 | func OK(c *gin.Context, data interface{}, msg string) {
23 | var res Response
24 | res.Data = data
25 | if msg != "" {
26 | res.Msg = msg
27 | }
28 | c.JSON(http.StatusOK, res.ReturnOK())
29 | }
30 |
31 | // 分页数据处理
32 | func PageOK(c *gin.Context, result interface{}, count int, pageIndex int, pageSize int, msg string) {
33 | var res PageResponse
34 | res.Data.List = result
35 | res.Data.Count = count
36 | res.Data.PageIndex = pageIndex
37 | res.Data.PageSize = pageSize
38 | if msg != "" {
39 | res.Msg = msg
40 | }
41 | c.JSON(http.StatusOK, res.ReturnOK())
42 | }
43 |
44 | // 兼容函数
45 | func Custum(c *gin.Context, data gin.H) {
46 | c.JSON(http.StatusOK, data)
47 | }
48 |
--------------------------------------------------------------------------------
/tools/captcha/captcha.go:
--------------------------------------------------------------------------------
1 | package captcha
2 |
3 | import (
4 | "github.com/google/uuid"
5 | "github.com/mojocn/base64Captcha"
6 | )
7 |
8 | var store = base64Captcha.DefaultMemStore
9 |
10 | // configJsonBody json request body.
11 | type configJsonBody struct {
12 | Id string
13 | CaptchaType string
14 | VerifyValue string
15 | DriverAudio *base64Captcha.DriverAudio
16 | DriverString *base64Captcha.DriverString
17 | DriverChinese *base64Captcha.DriverChinese
18 | DriverMath *base64Captcha.DriverMath
19 | DriverDigit *base64Captcha.DriverDigit
20 | }
21 |
22 | func DriverDigitFunc() (id, b64s, answer string, err error) {
23 | e := configJsonBody{}
24 | e.Id = uuid.New().String()
25 | e.DriverDigit = base64Captcha.NewDriverDigit(80, 240, 4, 0.7, 80)
26 | driver := e.DriverDigit
27 | captcha := base64Captcha.NewCaptcha(driver, store)
28 | return captcha.Generate()
29 | }
30 |
--------------------------------------------------------------------------------
/tools/config/application.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "github.com/spf13/viper"
4 |
5 | type Application struct {
6 | ReadTimeout int
7 | WriterTimeout int
8 | Host string
9 | Port string
10 | Name string
11 | JwtSecret string
12 | Mode string
13 | DemoMsg string
14 | Domain string
15 | IsHttps bool
16 | }
17 |
18 | func InitApplication(cfg *viper.Viper) *Application {
19 | return &Application{
20 | ReadTimeout: cfg.GetInt("readTimeout"),
21 | WriterTimeout: cfg.GetInt("writerTimeout"),
22 | Host: cfg.GetString("host"),
23 | Port: portDefault(cfg),
24 | Name: cfg.GetString("name"),
25 | JwtSecret: viper.GetString("settings.jwt.secret"),
26 | Mode: cfg.GetString("mode"),
27 | DemoMsg: cfg.GetString("demoMsg"),
28 | Domain: cfg.GetString("domain"),
29 | IsHttps: cfg.GetBool("ishttps"),
30 | }
31 | }
32 |
33 | var ApplicationConfig = new(Application)
34 |
35 | func portDefault(cfg *viper.Viper) string {
36 | if cfg.GetString("port") == "" {
37 | return "8000"
38 | } else {
39 | return cfg.GetString("port")
40 | }
41 | }
42 |
43 | func isHttpsDefault(cfg *viper.Viper) bool {
44 | if cfg.GetString("ishttps") == "" || cfg.GetBool("ishttps") == false {
45 | return false
46 | } else {
47 | return true
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tools/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "ferry/pkg/logger"
5 | "fmt"
6 | "os"
7 | "strings"
8 |
9 | "github.com/spf13/viper"
10 | )
11 |
12 | var cfgDatabase *viper.Viper
13 | var cfgApplication *viper.Viper
14 | var cfgJwt *viper.Viper
15 | var cfgSsl *viper.Viper
16 |
17 | // ConfigSetup 载入配置文件
18 | func ConfigSetup(path string) {
19 | viper.SetConfigFile(path)
20 | content, err := os.ReadFile(path)
21 | if err != nil {
22 | logger.Fatal(fmt.Sprintf("Read config file fail: %s", err.Error()))
23 | }
24 |
25 | //Replace environment variables
26 | err = viper.ReadConfig(strings.NewReader(os.ExpandEnv(string(content))))
27 | if err != nil {
28 | logger.Fatal(fmt.Sprintf("Parse config file fail: %s", err.Error()))
29 | }
30 |
31 | // 数据库初始化
32 | cfgDatabase = viper.Sub("settings.database")
33 | if cfgDatabase == nil {
34 | panic("config not found settings.database")
35 | }
36 | DatabaseConfig = InitDatabase(cfgDatabase)
37 |
38 | // 启动参数
39 | cfgApplication = viper.Sub("settings.application")
40 | if cfgApplication == nil {
41 | panic("config not found settings.application")
42 | }
43 | ApplicationConfig = InitApplication(cfgApplication)
44 |
45 | // Jwt初始化
46 | cfgJwt = viper.Sub("settings.jwt")
47 | if cfgJwt == nil {
48 | panic("config not found settings.jwt")
49 | }
50 | JwtConfig = InitJwt(cfgJwt)
51 |
52 | // ssl 配置
53 | cfgSsl = viper.Sub("settings.ssl")
54 | if cfgSsl == nil {
55 | panic("config not found settings.ssl")
56 | }
57 | SslConfig = InitSsl(cfgSsl)
58 |
59 | // 日志配置
60 | logger.Init()
61 | }
62 |
63 | func SetConfig(configPath string, key string, value interface{}) {
64 | viper.AddConfigPath(configPath)
65 | viper.Set(key, value)
66 | _ = viper.WriteConfig()
67 | }
68 |
--------------------------------------------------------------------------------
/tools/config/database.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "github.com/spf13/viper"
4 |
5 | type Database struct {
6 | Dbtype string
7 | Host string
8 | Port int
9 | Name string
10 | Username string
11 | Password string
12 | }
13 |
14 | func InitDatabase(cfg *viper.Viper) *Database {
15 | return &Database{
16 | Port: cfg.GetInt("port"),
17 | Dbtype: cfg.GetString("dbType"),
18 | Host: cfg.GetString("host"),
19 | Name: cfg.GetString("name"),
20 | Username: cfg.GetString("username"),
21 | Password: cfg.GetString("password"),
22 | }
23 | }
24 |
25 | var DatabaseConfig = new(Database)
26 |
--------------------------------------------------------------------------------
/tools/config/jwt.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "github.com/spf13/viper"
5 | )
6 |
7 | type Jwt struct {
8 | Secret string
9 | Timeout int64
10 | }
11 |
12 | func InitJwt(cfg *viper.Viper) *Jwt {
13 | return &Jwt{
14 | Secret: cfg.GetString("secret"),
15 | Timeout: cfg.GetInt64("timeout"),
16 | }
17 | }
18 |
19 | var JwtConfig = new(Jwt)
20 |
--------------------------------------------------------------------------------
/tools/config/ssl.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "github.com/spf13/viper"
4 |
5 | type Ssl struct {
6 | KeyStr string
7 | Pem string
8 | }
9 |
10 | func InitSsl(cfg *viper.Viper) *Ssl {
11 | return &Ssl{
12 | KeyStr: cfg.GetString("key"),
13 | Pem: cfg.GetString("pem"),
14 | }
15 | }
16 |
17 | var SslConfig = new(Ssl)
18 |
--------------------------------------------------------------------------------
/tools/env.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | type (
4 | Mode string
5 | )
6 |
7 | const (
8 | ModeDev Mode = "dev" //开发模式
9 | ModeTest Mode = "test" //测试模式
10 | ModeProd Mode = "prod" //生产模式
11 | Mysql = "mysql" //mysql数据库标识
12 | )
13 |
--------------------------------------------------------------------------------
/tools/float64.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import "strconv"
4 |
5 | func Float64ToString(e float64) string {
6 | return strconv.FormatFloat(e, 'E', -1, 64)
7 | }
--------------------------------------------------------------------------------
/tools/int.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import "strconv"
4 |
5 | func IntToString(e int) string {
6 | return strconv.Itoa(e)
7 | }
--------------------------------------------------------------------------------
/tools/int64.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import "strconv"
4 |
5 | func Int64ToString(e int64) string {
6 | return strconv.FormatInt(e, 10)
7 | }
--------------------------------------------------------------------------------
/tools/ip.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 |
9 | "github.com/spf13/viper"
10 | )
11 |
12 | func GetLocation(ip string) string {
13 | var address = "已关闭位置获取"
14 | if viper.GetBool("settings.public.isLocation") {
15 | if ip == "127.0.0.1" || ip == "localhost" {
16 | return "内部IP"
17 | }
18 | resp, err := http.Get("https://restapi.amap.com/v3/ip?ip=" + ip + "&key=3fabc36c20379fbb9300c79b19d5d05e")
19 | if err != nil {
20 | panic(err)
21 | }
22 | defer resp.Body.Close()
23 | s, err := ioutil.ReadAll(resp.Body)
24 |
25 | m := make(map[string]string)
26 |
27 | err = json.Unmarshal(s, &m)
28 | if err != nil {
29 | fmt.Println("Umarshal failed:", err)
30 | }
31 | if m["province"] == "" {
32 | return "未知位置"
33 | }
34 | address = m["province"] + "-" + m["city"]
35 | }
36 | return address
37 | }
38 |
--------------------------------------------------------------------------------
/tools/string.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "github.com/gin-gonic/gin"
7 | "io/ioutil"
8 | "strconv"
9 | "time"
10 | )
11 |
12 | func StringToInt64(e string) (int64, error) {
13 | return strconv.ParseInt(e, 10, 64)
14 | }
15 |
16 | func StringToInt(e string) (int, error) {
17 | return strconv.Atoi(e)
18 | }
19 |
20 |
21 | func GetCurrntTimeStr() string {
22 | return time.Now().Format("2006/01/02 15:04:05")
23 | }
24 |
25 | func GetCurrntTime() time.Time {
26 | return time.Now()
27 | }
28 |
29 |
30 | func StructToJsonStr(e interface{}) (string, error) {
31 | if b, err := json.Marshal(e); err == nil {
32 | return string(b), err
33 | } else {
34 | return "", err
35 | }
36 | }
37 |
38 | func GetBodyString(c *gin.Context) (string, error) {
39 | body, err := ioutil.ReadAll(c.Request.Body)
40 | if err != nil {
41 | fmt.Printf("read body err, %v\n", err)
42 | return string(body), nil
43 | } else {
44 | return "", err
45 | }
46 | }
47 |
48 | func JsonStrToMap(e string) (map[string]interface{}, error) {
49 | var dict map[string]interface{}
50 | if err := json.Unmarshal([]byte(e), &dict); err == nil {
51 | return dict, err
52 | } else {
53 | return nil, err
54 | }
55 | }
56 |
57 | func StructToMap(data interface{}) (map[string]interface{}, error) {
58 | dataBytes, err := json.Marshal(data)
59 | if err != nil {
60 | return nil, err
61 | }
62 | mapData := make(map[string]interface{})
63 | err = json.Unmarshal(dataBytes, &mapData)
64 | if err != nil {
65 | return nil, err
66 | }
67 | return mapData, nil
68 | }
69 |
--------------------------------------------------------------------------------
/tools/url.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "strings"
6 | )
7 |
8 | //获取URL中批量id并解析
9 | func IdsStrToIdsIntGroup(key string, c *gin.Context) []int {
10 | return idsStrToIdsIntGroup(c.Param(key))
11 | }
12 |
13 |
14 | func idsStrToIdsIntGroup(keys string) []int {
15 | IDS := make([]int, 0)
16 | ids := strings.Split(keys, ",")
17 | for i := 0; i < len(ids); i++ {
18 | ID, _ := StringToInt(ids[i])
19 | IDS = append(IDS, ID)
20 | }
21 | return IDS
22 | }
--------------------------------------------------------------------------------
/tools/user.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | jwt "ferry/pkg/jwtauth"
5 | "ferry/pkg/logger"
6 | "fmt"
7 |
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | func ExtractClaims(c *gin.Context) jwt.MapClaims {
12 | claims, exists := c.Get("JWT_PAYLOAD")
13 | if !exists {
14 | return make(jwt.MapClaims)
15 | }
16 |
17 | return claims.(jwt.MapClaims)
18 | }
19 |
20 | func GetUserId(c *gin.Context) int {
21 | data := ExtractClaims(c)
22 | if data["identity"] != nil {
23 | return int((data["identity"]).(float64))
24 | }
25 | logger.Info("********** 路径:" + c.Request.URL.Path + " 请求方法:" + c.Request.Method + " 说明:缺少identity")
26 | return 0
27 | }
28 |
29 | func GetUserIdStr(c *gin.Context) string {
30 | data := ExtractClaims(c)
31 | if data["identity"] != nil {
32 | return Int64ToString(int64((data["identity"]).(float64)))
33 | }
34 | logger.Info("********** 路径:" + c.Request.URL.Path + " 请求方法:" + c.Request.Method + " 缺少identity")
35 | return ""
36 | }
37 |
38 | func GetUserName(c *gin.Context) string {
39 | data := ExtractClaims(c)
40 | if data["nice"] != nil {
41 | return (data["nice"]).(string)
42 | }
43 | fmt.Println("********** 路径:" + c.Request.URL.Path + " 请求方法:" + c.Request.Method + " 缺少nice")
44 | return ""
45 | }
46 |
47 | func GetRoleName(c *gin.Context) string {
48 | data := ExtractClaims(c)
49 | if data["rolekey"] != nil {
50 | return (data["rolekey"]).(string)
51 | }
52 | fmt.Println("********** 路径:" + c.Request.URL.Path + " 请求方法:" + c.Request.Method + " 缺少rolekey")
53 | return ""
54 | }
55 |
56 | func GetRoleId(c *gin.Context) int {
57 | data := ExtractClaims(c)
58 | if data["roleid"] != nil {
59 | i := int((data["roleid"]).(float64))
60 | return i
61 | }
62 | fmt.Println("********** 路径:" + c.Request.URL.Path + " 请求方法:" + c.Request.Method + " 缺少roleid")
63 | return 0
64 | }
65 |
--------------------------------------------------------------------------------
/tools/utils.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "ferry/pkg/logger"
5 | "strconv"
6 |
7 | "golang.org/x/crypto/bcrypt"
8 | )
9 |
10 | func StrToInt(err error, index string) int {
11 | result, err := strconv.Atoi(index)
12 | if err != nil {
13 | HasError(err, "string to int error"+err.Error(), -1)
14 | }
15 | return result
16 | }
17 |
18 | func CompareHashAndPassword(e string, p string) (bool, error) {
19 | err := bcrypt.CompareHashAndPassword([]byte(e), []byte(p))
20 | if err != nil {
21 | logger.Info(err.Error())
22 | return false, err
23 | }
24 | return true, nil
25 | }
26 |
27 | // Assert 条件断言
28 | // 当断言条件为 假 时触发 panic
29 | // 对于当前请求不会再执行接下来的代码,并且返回指定格式的错误信息和错误码
30 | func Assert(condition bool, msg string, code ...int) {
31 | if !condition {
32 | statusCode := 200
33 | if len(code) > 0 {
34 | statusCode = code[0]
35 | }
36 | panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg)
37 | }
38 | }
39 |
40 | // HasError 错误断言
41 | // 当 error 不为 nil 时触发 panic
42 | // 对于当前请求不会再执行接下来的代码,并且返回指定格式的错误信息和错误码
43 | // 若 msg 为空,则默认为 error 中的内容
44 | func HasError(err error, msg string, code ...int) {
45 | if err != nil {
46 | statusCode := 200
47 | if len(code) > 0 {
48 | statusCode = code[0]
49 | }
50 | if msg == "" {
51 | msg = err.Error()
52 | }
53 | logger.Info(err)
54 | panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------