mirror of
https://github.com/xinliangnote/go-gin-api.git
synced 2024-04-21 12:31:46 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e1ef9c658 | ||
|
|
8a6a34348f | ||
|
|
66a5e29c9c | ||
|
|
84cc0c9cbc |
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(r,e){"object"==typeof exports?module.exports=exports=e(require("./core")):"function"==typeof define&&define.amd?define(["./core"],e):e(r.CryptoJS)}(this,function(r){var s;return s=r.lib.WordArray,r.enc.Base64={stringify:function(r){var e=r.words,t=r.sigBytes,a=this._map;r.clamp();for(var n=[],o=0;o<t;o+=3)for(var i=(e[o>>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,f=0;f<4&&o+.75*f<t;f++)n.push(a.charAt(i>>>6*(3-f)&63));var c=a.charAt(64);if(c)for(;n.length%4;)n.push(c);return n.join("")},parse:function(r){var e=r.length,t=this._map,a=this._reverseMap;if(!a){a=this._reverseMap=[];for(var n=0;n<t.length;n++)a[t.charCodeAt(n)]=n}var o=t.charAt(64);if(o){var i=r.indexOf(o);-1!==i&&(e=i)}return function(r,e,t){for(var a=[],n=0,o=0;o<e;o++)if(o%4){var i=t[r.charCodeAt(o-1)]<<o%4*2,f=t[r.charCodeAt(o)]>>>6-o%4*2,c=i|f;a[n>>>2]|=c<<24-n%4*8,n++}return s.create(a,n)}(r,e,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},r.enc.Base64});
|
||||
@@ -0,0 +1,18 @@
|
||||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./sha256", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacSHA256;
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,78 @@
|
||||
// original:https://locutus.io/php/array/ksort/
|
||||
|
||||
function ksort(inputArr, sort_flags) {
|
||||
var tmp_arr = {},
|
||||
keys = [],
|
||||
sorter, i, k, that = this,
|
||||
strictForIn = false,
|
||||
populateArr = {};
|
||||
|
||||
switch (sort_flags) {
|
||||
case 'SORT_STRING':
|
||||
// compare items as strings
|
||||
sorter = function (a, b) {
|
||||
return that.strnatcmp(a, b);
|
||||
};
|
||||
break;
|
||||
case 'SORT_LOCALE_STRING':
|
||||
// compare items as strings, original by the current locale (set with i18n_loc_set_default() as of PHP6)
|
||||
var loc = this.i18n_loc_get_default();
|
||||
sorter = this.php_js.i18nLocales[loc].sorting;
|
||||
break;
|
||||
case 'SORT_NUMERIC':
|
||||
// compare items numerically
|
||||
sorter = function (a, b) {
|
||||
return ((a + 0) - (b + 0));
|
||||
};
|
||||
break;
|
||||
// case 'SORT_REGULAR': // compare items normally (don't change types)
|
||||
default:
|
||||
sorter = function (a, b) {
|
||||
var aFloat = parseFloat(a),
|
||||
bFloat = parseFloat(b),
|
||||
aNumeric = aFloat + '' === a,
|
||||
bNumeric = bFloat + '' === b;
|
||||
if (aNumeric && bNumeric) {
|
||||
return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
|
||||
} else if (aNumeric && !bNumeric) {
|
||||
return 1;
|
||||
} else if (!aNumeric && bNumeric) {
|
||||
return -1;
|
||||
}
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
// Make a list of key names
|
||||
for (k in inputArr) {
|
||||
if (inputArr.hasOwnProperty(k)) {
|
||||
keys.push(k);
|
||||
}
|
||||
}
|
||||
keys.sort(sorter);
|
||||
|
||||
// BEGIN REDUNDANT
|
||||
this.php_js = this.php_js || {};
|
||||
this.php_js.ini = this.php_js.ini || {};
|
||||
// END REDUNDANT
|
||||
strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js
|
||||
.ini['phpjs.strictForIn'].local_value !== 'off';
|
||||
populateArr = strictForIn ? inputArr : populateArr;
|
||||
|
||||
// Rebuild array with sorted key names
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
k = keys[i];
|
||||
tmp_arr[k] = inputArr[k];
|
||||
if (strictForIn) {
|
||||
delete inputArr[k];
|
||||
}
|
||||
}
|
||||
for (i in tmp_arr) {
|
||||
if (tmp_arr.hasOwnProperty(i)) {
|
||||
populateArr[i] = tmp_arr[i];
|
||||
}
|
||||
}
|
||||
|
||||
return strictForIn || populateArr;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((c=d(d(t,n),d(e,u)))<<(f=o)|c>>>32-f,r);var c,f}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u;n[t>>5]|=128<<t%32,n[14+(t+64>>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h<n.length;h+=16)c=l(r=c,e=f,o=i,u=a,n[h],7,-680876936),a=l(a,c,f,i,n[h+1],12,-389564586),i=l(i,a,c,f,n[h+2],17,606105819),f=l(f,i,a,c,n[h+3],22,-1044525330),c=l(c,f,i,a,n[h+4],7,-176418897),a=l(a,c,f,i,n[h+5],12,1200080426),i=l(i,a,c,f,n[h+6],17,-1473231341),f=l(f,i,a,c,n[h+7],22,-45705983),c=l(c,f,i,a,n[h+8],7,1770035416),a=l(a,c,f,i,n[h+9],12,-1958414417),i=l(i,a,c,f,n[h+10],17,-42063),f=l(f,i,a,c,n[h+11],22,-1990404162),c=l(c,f,i,a,n[h+12],7,1804603682),a=l(a,c,f,i,n[h+13],12,-40341101),i=l(i,a,c,f,n[h+14],17,-1502002290),c=v(c,f=l(f,i,a,c,n[h+15],22,1236535329),i,a,n[h+1],5,-165796510),a=v(a,c,f,i,n[h+6],9,-1069501632),i=v(i,a,c,f,n[h+11],14,643717713),f=v(f,i,a,c,n[h],20,-373897302),c=v(c,f,i,a,n[h+5],5,-701558691),a=v(a,c,f,i,n[h+10],9,38016083),i=v(i,a,c,f,n[h+15],14,-660478335),f=v(f,i,a,c,n[h+4],20,-405537848),c=v(c,f,i,a,n[h+9],5,568446438),a=v(a,c,f,i,n[h+14],9,-1019803690),i=v(i,a,c,f,n[h+3],14,-187363961),f=v(f,i,a,c,n[h+8],20,1163531501),c=v(c,f,i,a,n[h+13],5,-1444681467),a=v(a,c,f,i,n[h+2],9,-51403784),i=v(i,a,c,f,n[h+7],14,1735328473),c=g(c,f=v(f,i,a,c,n[h+12],20,-1926607734),i,a,n[h+5],4,-378558),a=g(a,c,f,i,n[h+8],11,-2022574463),i=g(i,a,c,f,n[h+11],16,1839030562),f=g(f,i,a,c,n[h+14],23,-35309556),c=g(c,f,i,a,n[h+1],4,-1530992060),a=g(a,c,f,i,n[h+4],11,1272893353),i=g(i,a,c,f,n[h+7],16,-155497632),f=g(f,i,a,c,n[h+10],23,-1094730640),c=g(c,f,i,a,n[h+13],4,681279174),a=g(a,c,f,i,n[h],11,-358537222),i=g(i,a,c,f,n[h+3],16,-722521979),f=g(f,i,a,c,n[h+6],23,76029189),c=g(c,f,i,a,n[h+9],4,-640364487),a=g(a,c,f,i,n[h+12],11,-421815835),i=g(i,a,c,f,n[h+15],16,530742520),c=m(c,f=g(f,i,a,c,n[h+2],23,-995338651),i,a,n[h],6,-198630844),a=m(a,c,f,i,n[h+7],10,1126891415),i=m(i,a,c,f,n[h+14],15,-1416354905),f=m(f,i,a,c,n[h+5],21,-57434055),c=m(c,f,i,a,n[h+12],6,1700485571),a=m(a,c,f,i,n[h+3],10,-1894986606),i=m(i,a,c,f,n[h+10],15,-1051523),f=m(f,i,a,c,n[h+1],21,-2054922799),c=m(c,f,i,a,n[h+8],6,1873313359),a=m(a,c,f,i,n[h+15],10,-30611744),i=m(i,a,c,f,n[h+6],15,-1560198380),f=m(f,i,a,c,n[h+13],21,1309151649),c=m(c,f,i,a,n[h+4],6,-145523070),a=m(a,c,f,i,n[h+11],10,-1120210379),i=m(i,a,c,f,n[h+2],15,718787259),f=m(f,i,a,c,n[h+9],21,-343485551),c=d(c,r),f=d(f,e),i=d(i,o),a=d(a,u);return[c,f,i,a]}function a(n){for(var t="",r=32*n.length,e=0;e<r;e+=8)t+=String.fromCharCode(n[e>>5]>>>e%32&255);return t}function h(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e<t.length;e+=1)t[e]=0;for(var r=8*n.length,e=0;e<r;e+=8)t[e>>5]|=(255&n.charCodeAt(e/8))<<e%32;return t}function e(n){for(var t,r="0123456789abcdef",e="",o=0;o<n.length;o+=1)t=n.charCodeAt(o),e+=r.charAt(t>>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return a(i(h(t=r(n)),8*t.length));var t}function u(n,t){return function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16<o.length&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}(r(n),r(t))}function t(n,t,r){return t?r?u(t,n):e(u(t,n)):r?o(n):e(o(n))}"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:n.md5=t}(this);
|
||||
//# sourceMappingURL=md5.min.js.map
|
||||
@@ -0,0 +1,589 @@
|
||||
/* ==========================================================
|
||||
* bootstrap-maxlength.js v1.9.0
|
||||
*
|
||||
* Copyright (c) 2013-2020 Maurizio Napoleoni;
|
||||
*
|
||||
* Licensed under the terms of the MIT license.
|
||||
* See: https://github.com/mimo84/bootstrap-maxlength/blob/master/LICENSE
|
||||
* ========================================================== */
|
||||
/*global jQuery*/
|
||||
|
||||
(function ($) {
|
||||
'use strict';
|
||||
/**
|
||||
* We need an event when the elements are destroyed
|
||||
* because if an input is removed, we have to remove the
|
||||
* maxlength object associated (if any).
|
||||
* From:
|
||||
* http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
|
||||
*/
|
||||
if (!$.event.special.destroyed) {
|
||||
$.event.special.destroyed = {
|
||||
remove: function (o) {
|
||||
if (o.handler) {
|
||||
o.handler();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
$.fn.extend({
|
||||
maxlength: function (options, callback) {
|
||||
var documentBody = $('body'),
|
||||
defaults = {
|
||||
showOnReady: false, // true to always show when indicator is ready
|
||||
alwaysShow: true, // if true the indicator it's always shown.
|
||||
threshold: 0, // Represents how many chars left are needed to show up the counter
|
||||
warningClass: 'small form-text text-muted',
|
||||
limitReachedClass: 'small form-text text-danger',
|
||||
separator: ' / ',
|
||||
preText: '',
|
||||
postText: '',
|
||||
showMaxLength: true,
|
||||
placement: 'bottom-right-inside',
|
||||
message: null, // an alternative way to provide the message text
|
||||
showCharsTyped: true, // show the number of characters typed and not the number of characters remaining
|
||||
validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than the indicated chars, will be prevented.
|
||||
utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters.
|
||||
appendToParent: false, // append the indicator to the input field's parent instead of body
|
||||
twoCharLinebreak: true, // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage.
|
||||
customMaxAttribute: null, // null = use maxlength attribute and browser functionality, string = use specified attribute instead.
|
||||
allowOverMax: false, // Form submit validation is handled on your own. when maxlength has been exceeded 'overmax' class added to element
|
||||
zIndex: 1099
|
||||
};
|
||||
|
||||
if ($.isFunction(options) && !callback) {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
|
||||
/**
|
||||
* Return the byte count of the specified character in UTF8 encoding.
|
||||
* Note: This won't cover UTF-8 characters that are 4 bytes long.
|
||||
*
|
||||
* @param input
|
||||
* @return {number}
|
||||
*/
|
||||
function utf8CharByteCount(character) {
|
||||
var c = character.charCodeAt();
|
||||
// Not c then 0, else c < 128 then 1, else c < 2048 then 2, else 3
|
||||
return !c ? 0 : c < 128 ? 1 : c < 2048 ? 2 : 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the specified input in UTF8 encoding.
|
||||
*
|
||||
* @param input
|
||||
* @return {number}
|
||||
*/
|
||||
function utf8Length(string) {
|
||||
return string.split("")
|
||||
.map(utf8CharByteCount)
|
||||
// Prevent reduce from throwing an error if the string is empty.
|
||||
.concat(0)
|
||||
.reduce(function (sum, val) {
|
||||
return sum + val;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the specified input.
|
||||
*
|
||||
* @param input
|
||||
* @return {number}
|
||||
*/
|
||||
function inputLength(input) {
|
||||
var text = input.val();
|
||||
|
||||
if (options.twoCharLinebreak) {
|
||||
// Count all line breaks as 2 characters
|
||||
text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
|
||||
} else {
|
||||
// Remove all double-character (\r\n) linebreaks, so they're counted only once.
|
||||
text = text.replace(/(?:\r\n|\r|\n)/g, '\n');
|
||||
}
|
||||
|
||||
var currentLength = 0;
|
||||
|
||||
if (options.utf8) {
|
||||
currentLength = utf8Length(text);
|
||||
} else {
|
||||
currentLength = text.length;
|
||||
}
|
||||
|
||||
// Remove "C:\fakepath\" from counter when using file input
|
||||
// Fix https://github.com/mimo84/bootstrap-maxlength/issues/146
|
||||
if (input.prop("type") === "file" && input.val() !== "") {
|
||||
currentLength -= 12;
|
||||
}
|
||||
|
||||
return currentLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the text of the specified input.
|
||||
*
|
||||
* @param input
|
||||
* @param limit
|
||||
*/
|
||||
function truncateChars(input, maxlength) {
|
||||
var text = input.val();
|
||||
|
||||
if (options.twoCharLinebreak) {
|
||||
text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
|
||||
|
||||
if (text[text.length - 1] === '\n') {
|
||||
maxlength -= text.length % 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.utf8) {
|
||||
var indexedSize = text.split("").map(utf8CharByteCount);
|
||||
for (
|
||||
var removedBytes = 0,
|
||||
bytesPastMax = utf8Length(text) - maxlength; removedBytes < bytesPastMax; removedBytes += indexedSize.pop()
|
||||
);
|
||||
maxlength -= (maxlength - indexedSize.length);
|
||||
}
|
||||
|
||||
input.val(text.substr(0, maxlength));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the indicator should be showing up.
|
||||
*
|
||||
* @param input
|
||||
* @param threshold
|
||||
* @param maxlength
|
||||
* @return {number}
|
||||
*/
|
||||
function charsLeftThreshold(input, threshold, maxlength) {
|
||||
var output = true;
|
||||
if (!options.alwaysShow && (maxlength - inputLength(input) > threshold)) {
|
||||
output = false;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many chars are left to complete the fill up of the form.
|
||||
*
|
||||
* @param input
|
||||
* @param maxlength
|
||||
* @return {number}
|
||||
*/
|
||||
function remainingChars(input, maxlength) {
|
||||
var length = maxlength - inputLength(input);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* When called displays the indicator.
|
||||
*
|
||||
* @param indicator
|
||||
*/
|
||||
function showRemaining(currentInput, indicator) {
|
||||
indicator.css({
|
||||
display: 'block'
|
||||
});
|
||||
currentInput.trigger('maxlength.shown');
|
||||
}
|
||||
|
||||
/**
|
||||
* When called shows the indicator.
|
||||
*
|
||||
* @param indicator
|
||||
*/
|
||||
function hideRemaining(currentInput, indicator) {
|
||||
|
||||
if (options.alwaysShow) {
|
||||
return;
|
||||
}
|
||||
|
||||
indicator.css({
|
||||
display: 'none'
|
||||
});
|
||||
currentInput.trigger('maxlength.hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates the value in the indicator
|
||||
*
|
||||
* @param maxLengthThisInput
|
||||
* @param typedChars
|
||||
* @return String
|
||||
*/
|
||||
function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) {
|
||||
var output = '';
|
||||
if (options.message) {
|
||||
if (typeof options.message === 'function') {
|
||||
output = options.message(currentInputText, maxLengthThisInput);
|
||||
} else {
|
||||
output = options.message.replace('%charsTyped%', typedChars)
|
||||
.replace('%charsRemaining%', maxLengthThisInput - typedChars)
|
||||
.replace('%charsTotal%', maxLengthThisInput);
|
||||
}
|
||||
} else {
|
||||
if (options.preText) {
|
||||
output += options.preText;
|
||||
}
|
||||
if (!options.showCharsTyped) {
|
||||
output += maxLengthThisInput - typedChars;
|
||||
} else {
|
||||
output += typedChars;
|
||||
}
|
||||
if (options.showMaxLength) {
|
||||
output += options.separator + maxLengthThisInput;
|
||||
}
|
||||
if (options.postText) {
|
||||
output += options.postText;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates the value of the counter in the indicator.
|
||||
* Wants as parameters: the number of remaining chars, the element currently managed,
|
||||
* the maxLength for the current input and the indicator generated for it.
|
||||
*
|
||||
* @param remaining
|
||||
* @param currentInput
|
||||
* @param maxLengthCurrentInput
|
||||
* @param maxLengthIndicator
|
||||
*/
|
||||
function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) {
|
||||
if (maxLengthIndicator) {
|
||||
maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining)));
|
||||
|
||||
if (remaining > 0) {
|
||||
if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) {
|
||||
showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass).addClass(options.warningClass));
|
||||
} else {
|
||||
hideRemaining(currentInput, maxLengthIndicator);
|
||||
}
|
||||
} else {
|
||||
showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass));
|
||||
}
|
||||
}
|
||||
|
||||
if (options.customMaxAttribute) {
|
||||
// class to use for form validation on custom maxlength attribute
|
||||
if (remaining < 0) {
|
||||
currentInput.addClass('overmax');
|
||||
} else {
|
||||
currentInput.removeClass('overmax');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns an object containing all the
|
||||
* informations about the position of the current input
|
||||
*
|
||||
* @param currentInput
|
||||
* @return object {bottom height left right top width}
|
||||
*
|
||||
*/
|
||||
function getPosition(currentInput) {
|
||||
var el = currentInput[0];
|
||||
return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : {
|
||||
width: el.offsetWidth,
|
||||
height: el.offsetHeight
|
||||
}, currentInput.offset());
|
||||
}
|
||||
|
||||
/**
|
||||
* This function places the maxLengthIndicator based on placement config object.
|
||||
*
|
||||
* @param {object} placement
|
||||
* @param {$} maxLengthIndicator
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
function placeWithCSS(placement, maxLengthIndicator) {
|
||||
if (!placement || !maxLengthIndicator) {
|
||||
return;
|
||||
}
|
||||
|
||||
var POSITION_KEYS = [
|
||||
'top',
|
||||
'bottom',
|
||||
'left',
|
||||
'right',
|
||||
'position'
|
||||
];
|
||||
|
||||
var cssPos = {};
|
||||
|
||||
// filter css properties to position
|
||||
$.each(POSITION_KEYS, function (i, key) {
|
||||
var val = options.placement[key];
|
||||
if (typeof val !== 'undefined') {
|
||||
cssPos[key] = val;
|
||||
}
|
||||
});
|
||||
|
||||
maxLengthIndicator.css(cssPos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function places the maxLengthIndicator at the
|
||||
* top / bottom / left / right of the currentInput
|
||||
*
|
||||
* @param currentInput
|
||||
* @param maxLengthIndicator
|
||||
* @return null
|
||||
*
|
||||
*/
|
||||
function place(currentInput, maxLengthIndicator) {
|
||||
var pos = getPosition(currentInput);
|
||||
|
||||
// Supports custom placement handler
|
||||
if ($.type(options.placement) === 'function') {
|
||||
options.placement(currentInput, maxLengthIndicator, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
// Supports custom placement via css positional properties
|
||||
if ($.isPlainObject(options.placement)) {
|
||||
placeWithCSS(options.placement, maxLengthIndicator);
|
||||
return;
|
||||
}
|
||||
|
||||
var inputOuter = currentInput.outerWidth(),
|
||||
outerWidth = maxLengthIndicator.outerWidth(),
|
||||
actualWidth = maxLengthIndicator.width(),
|
||||
actualHeight = maxLengthIndicator.height();
|
||||
|
||||
// get the right position if the indicator is appended to the input's parent
|
||||
if (options.appendToParent) {
|
||||
pos.top -= currentInput.parent().offset().top;
|
||||
pos.left -= currentInput.parent().offset().left;
|
||||
}
|
||||
|
||||
switch (options.placement) {
|
||||
case 'bottom':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + pos.height,
|
||||
left: pos.left + pos.width / 2 - actualWidth / 2
|
||||
});
|
||||
break;
|
||||
case 'top':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top - actualHeight,
|
||||
left: pos.left + pos.width / 2 - actualWidth / 2
|
||||
});
|
||||
break;
|
||||
case 'left':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + pos.height / 2 - actualHeight / 2,
|
||||
left: pos.left - actualWidth
|
||||
});
|
||||
break;
|
||||
case 'right':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + pos.height / 2 - actualHeight / 2,
|
||||
left: pos.left + pos.width
|
||||
});
|
||||
break;
|
||||
case 'bottom-right':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + pos.height,
|
||||
left: pos.left + pos.width
|
||||
});
|
||||
break;
|
||||
case 'top-right':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top - actualHeight,
|
||||
left: pos.left + inputOuter
|
||||
});
|
||||
break;
|
||||
case 'top-left':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top - actualHeight,
|
||||
left: pos.left - outerWidth
|
||||
});
|
||||
break;
|
||||
case 'bottom-left':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + currentInput.outerHeight(),
|
||||
left: pos.left - outerWidth
|
||||
});
|
||||
break;
|
||||
case 'centered-right':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + (actualHeight / 2),
|
||||
left: pos.left + inputOuter - outerWidth - 3
|
||||
});
|
||||
break;
|
||||
|
||||
// Some more options for placements
|
||||
case 'bottom-right-inside':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + pos.height,
|
||||
left: pos.left + pos.width - outerWidth
|
||||
});
|
||||
break;
|
||||
case 'top-right-inside':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top - actualHeight,
|
||||
left: pos.left + inputOuter - outerWidth
|
||||
});
|
||||
break;
|
||||
case 'top-left-inside':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top - actualHeight,
|
||||
left: pos.left
|
||||
});
|
||||
break;
|
||||
case 'bottom-left-inside':
|
||||
maxLengthIndicator.css({
|
||||
top: pos.top + currentInput.outerHeight(),
|
||||
left: pos.left
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns true if the indicator position needs to
|
||||
* be recalculated when the currentInput changes
|
||||
*
|
||||
* @return {boolean}
|
||||
*
|
||||
*/
|
||||
function isPlacementMutable() {
|
||||
return options.placement === 'bottom-right-inside' || options.placement === 'top-right-inside' || typeof options.placement === 'function' || (options.message && typeof options.message === 'function');
|
||||
}
|
||||
|
||||
/**
|
||||
* This function retrieves the maximum length of currentInput
|
||||
*
|
||||
* @param currentInput
|
||||
* @return {number}
|
||||
*
|
||||
*/
|
||||
function getMaxLength(currentInput) {
|
||||
var max = currentInput.attr('maxlength') || options.customMaxAttribute;
|
||||
|
||||
if (options.customMaxAttribute && !options.allowOverMax) {
|
||||
var custom = currentInput.attr(options.customMaxAttribute);
|
||||
if (!max || custom < max) {
|
||||
max = custom;
|
||||
}
|
||||
}
|
||||
|
||||
if (!max) {
|
||||
max = currentInput.attr('size');
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var currentInput = $(this),
|
||||
maxLengthCurrentInput,
|
||||
maxLengthIndicator;
|
||||
|
||||
$(window).resize(function () {
|
||||
if (maxLengthIndicator) {
|
||||
place(currentInput, maxLengthIndicator);
|
||||
}
|
||||
});
|
||||
|
||||
function firstInit() {
|
||||
var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0');
|
||||
maxLengthCurrentInput = getMaxLength(currentInput);
|
||||
|
||||
if (!maxLengthIndicator) {
|
||||
maxLengthIndicator = $('<span class="bootstrap-maxlength"></span>').css({
|
||||
display: 'none',
|
||||
position: 'absolute',
|
||||
whiteSpace: 'nowrap',
|
||||
zIndex: options.zIndex
|
||||
}).html(maxlengthContent);
|
||||
}
|
||||
|
||||
// We need to detect resizes if we are dealing with a textarea:
|
||||
if (currentInput.is('textarea')) {
|
||||
currentInput.data('maxlenghtsizex', currentInput.outerWidth());
|
||||
currentInput.data('maxlenghtsizey', currentInput.outerHeight());
|
||||
|
||||
currentInput.mouseup(function () {
|
||||
if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) {
|
||||
place(currentInput, maxLengthIndicator);
|
||||
}
|
||||
|
||||
currentInput.data('maxlenghtsizex', currentInput.outerWidth());
|
||||
currentInput.data('maxlenghtsizey', currentInput.outerHeight());
|
||||
});
|
||||
}
|
||||
|
||||
if (options.appendToParent) {
|
||||
currentInput.parent().append(maxLengthIndicator);
|
||||
currentInput.parent().css('position', 'relative');
|
||||
} else {
|
||||
documentBody.append(maxLengthIndicator);
|
||||
}
|
||||
|
||||
var remaining = remainingChars(currentInput, getMaxLength(currentInput));
|
||||
manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
|
||||
place(currentInput, maxLengthIndicator);
|
||||
}
|
||||
|
||||
if (options.showOnReady) {
|
||||
currentInput.ready(function () {
|
||||
firstInit();
|
||||
});
|
||||
} else {
|
||||
currentInput.focus(function () {
|
||||
firstInit();
|
||||
});
|
||||
}
|
||||
|
||||
currentInput.on('maxlength.reposition', function () {
|
||||
place(currentInput, maxLengthIndicator);
|
||||
});
|
||||
|
||||
|
||||
currentInput.on('destroyed', function () {
|
||||
if (maxLengthIndicator) {
|
||||
maxLengthIndicator.remove();
|
||||
}
|
||||
});
|
||||
|
||||
currentInput.on('blur', function () {
|
||||
if (maxLengthIndicator && !options.showOnReady) {
|
||||
maxLengthIndicator.remove();
|
||||
}
|
||||
});
|
||||
|
||||
currentInput.on('input', function () {
|
||||
var maxlength = getMaxLength(currentInput),
|
||||
remaining = remainingChars(currentInput, maxlength),
|
||||
output = true;
|
||||
|
||||
if (options.validate && remaining < 0) {
|
||||
truncateChars(currentInput, maxlength);
|
||||
output = false;
|
||||
} else {
|
||||
manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
|
||||
}
|
||||
|
||||
if (isPlacementMutable()) {
|
||||
place(currentInput, maxLengthIndicator);
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,104 @@
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/ksort.js"></script>');
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/crypto-js.min.js"></script>');
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/hmac-sha256.js"></script>');
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/enc-base64.min.js"></script>');
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/jquery.cookie.min.js"></script>');
|
||||
|
||||
|
||||
function GenerateAuthorization(path, method, params) {
|
||||
let key = "admin";
|
||||
let secret = "12878dd962115106db6d";
|
||||
|
||||
let date = new Date();
|
||||
let datetime = date.getFullYear() + "-" // "年"
|
||||
+ ((date.getMonth() + 1) > 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
|
||||
+ (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " " // "日"
|
||||
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" // "小时"
|
||||
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":" // "分钟"
|
||||
+ (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()); // "秒"
|
||||
|
||||
let sortParamsEncode = decodeURIComponent(jQuery.param(ksort(params)));
|
||||
let encryptStr = path + "|" + method.toUpperCase() + "|" + sortParamsEncode + "|" + datetime;
|
||||
let digest = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(encryptStr, secret));
|
||||
return {authorization: key + " " + digest, date: datetime};
|
||||
}
|
||||
|
||||
function IsJson(str) {
|
||||
if (typeof str == 'string') {
|
||||
try {
|
||||
let obj = JSON.parse(str);
|
||||
if (typeof obj == 'object' && obj) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error:' + str + '!!!' + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
console.log('It is not a string!')
|
||||
}
|
||||
|
||||
function AjaxError(response) {
|
||||
let errCode = response.status;
|
||||
let errMsg = response.responseText;
|
||||
|
||||
if (errCode === 401) { // 跳转到登录页
|
||||
// 关闭当前界面
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsJson(response.responseText)) {
|
||||
const errInfo = JSON.parse(response.responseText);
|
||||
errCode = errInfo.code;
|
||||
errMsg = errInfo.message;
|
||||
}
|
||||
|
||||
$.alert({
|
||||
title: '错误提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'red',
|
||||
content: '错误码:' + errCode + '<br/>' + '错误信息:' + errMsg,
|
||||
});
|
||||
}
|
||||
|
||||
function AjaxForm(method, url, params, beforeSendFunction, successFunction, errorFunction) {
|
||||
let authorizationData = GenerateAuthorization(url, method, params);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: method,
|
||||
data: params,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'Authorization': authorizationData.authorization,
|
||||
'Authorization-Date': authorizationData.date,
|
||||
'Token': $.cookie("_login_token_"),
|
||||
},
|
||||
beforeSend: beforeSendFunction,
|
||||
success: successFunction,
|
||||
error: errorFunction,
|
||||
});
|
||||
}
|
||||
|
||||
function AjaxPostJson(url, params, beforeSendFunction, successFunction, errorFunction) {
|
||||
let authorizationData = GenerateAuthorization(url, "POST", params);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: JSON.stringify(params),
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'Authorization': authorizationData.authorization,
|
||||
'Authorization-Date': authorizationData.date,
|
||||
'Token': $.cookie("_login_token_"),
|
||||
},
|
||||
beforeSend: beforeSendFunction,
|
||||
success: successFunction,
|
||||
error: errorFunction,
|
||||
});
|
||||
}
|
||||
Vendored
+9
-4
@@ -113,22 +113,27 @@
|
||||
// 选项卡
|
||||
$('#iframe-content').multitabs({
|
||||
iframe : true,
|
||||
refresh : 'no', // iframe中页面是否刷新,'no':'从不刷新','nav':'点击菜单刷新','all':'菜单和tab点击都刷新'
|
||||
refresh : 'nav', // iframe中页面是否刷新,'no':'从不刷新','nav':'点击菜单刷新','all':'菜单和tab点击都刷新'
|
||||
nav: {
|
||||
backgroundColor: '#ffffff',
|
||||
maxTabs : 35, // 选项卡最大值
|
||||
},
|
||||
init : [{
|
||||
type : 'main',
|
||||
title : '仪表盘',
|
||||
url : '/dashboard'
|
||||
title : $.cookie('_nav_title_') ? $.cookie('_nav_title_') : '仪表盘',
|
||||
url : $.cookie('_nav_url_') ? $.cookie('_nav_url_') : '/dashboard',
|
||||
}]
|
||||
});
|
||||
|
||||
|
||||
$(document).on('click', '.nav-item .multitabs', function() {
|
||||
$('.nav-item').removeClass('active');
|
||||
$('.nav-subnav li').removeClass('active');
|
||||
$(this).parent('li').addClass('active');
|
||||
$(this).parents('.nav-item-has-subnav').addClass('open').first().addClass('active');
|
||||
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + 24 * 60 * 60 * 1000); // 24 * 60 * 60 * 1000 表示 24 小时
|
||||
$.cookie('_nav_url_', $(this).attr('href'), {expires: date});
|
||||
$.cookie('_nav_title_', $(this).text(), {expires: date});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,292 @@
|
||||
/**
|
||||
* pagination.js 1.5.1
|
||||
* A jQuery plugin to provide simple yet fully customisable pagination.
|
||||
* @version 1.5.1
|
||||
* @author mss
|
||||
* @url https://github.com/Maxiaoxiang/jQuery-plugins
|
||||
*
|
||||
* @调用方法
|
||||
* $(selector).pagination(option, callback);
|
||||
* -此处callback是初始化调用,option里的callback是点击页码后调用
|
||||
*
|
||||
* -- example --
|
||||
* $(selector).pagination({
|
||||
* ... // 配置参数
|
||||
* callback: function(api) {
|
||||
* console.log('点击页码调用该回调'); //切换页码时执行一次回调
|
||||
* }
|
||||
* }, function(){
|
||||
* console.log('初始化'); //插件初始化时调用该方法,比如请求第一次接口来初始化分页配置
|
||||
* });
|
||||
*/
|
||||
;
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && (define.amd || define.cmd) && !jQuery) {
|
||||
// AMD或CMD
|
||||
define(["jquery"], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// Node/CommonJS
|
||||
module.exports = function (root, jQuery) {
|
||||
if (jQuery === undefined) {
|
||||
if (typeof window !== 'undefined') {
|
||||
jQuery = require('jquery');
|
||||
} else {
|
||||
jQuery = require('jquery')(root);
|
||||
}
|
||||
}
|
||||
factory(jQuery);
|
||||
return jQuery;
|
||||
};
|
||||
} else {
|
||||
//Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
//配置参数
|
||||
var defaults = {
|
||||
totalData: 0, //数据总条数
|
||||
showData: 0, //每页显示的条数
|
||||
pageCount: 9, //总页数,默认为9
|
||||
current: 1, //当前第几页
|
||||
prevCls: 'prev', //上一页class
|
||||
nextCls: 'next', //下一页class
|
||||
prevContent: '<', //上一页内容
|
||||
nextContent: '>', //下一页内容
|
||||
activeCls: 'active', //当前页选中状态
|
||||
coping: false, //首页和尾页
|
||||
isHide: false, //当前页数为0页或者1页时不显示分页
|
||||
homePage: '', //首页节点内容
|
||||
endPage: '', //尾页节点内容
|
||||
keepShowPN: false, //是否一直显示上一页下一页
|
||||
mode: 'unfixed', //分页模式,unfixed:不固定页码数量,fixed:固定页码数量
|
||||
count: 4, //mode为unfixed时显示当前选中页前后页数,mode为fixed显示页码总数
|
||||
jump: false, //跳转到指定页数
|
||||
jumpIptCls: 'jump-ipt', //文本框内容
|
||||
jumpBtnCls: 'jump-btn', //跳转按钮
|
||||
jumpBtn: '跳转', //跳转按钮文本
|
||||
callback: function () {} //回调
|
||||
};
|
||||
|
||||
var Pagination = function (element, options) {
|
||||
//全局变量
|
||||
var opts = options, //配置
|
||||
current, //当前页
|
||||
$document = $(document),
|
||||
$obj = $(element); //容器
|
||||
|
||||
/**
|
||||
* 设置总页数
|
||||
* @param {int} page 页码
|
||||
* @return opts.pageCount 总页数配置
|
||||
*/
|
||||
this.setPageCount = function (page) {
|
||||
return opts.pageCount = page;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取总页数
|
||||
* 如果配置了总条数和每页显示条数,将会自动计算总页数并略过总页数配置,反之
|
||||
* @return {int} 总页数
|
||||
*/
|
||||
this.getPageCount = function () {
|
||||
return opts.totalData && opts.showData ? Math.ceil(parseInt(opts.totalData) / opts.showData) : opts.pageCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前页
|
||||
* @return {int} 当前页码
|
||||
*/
|
||||
this.getCurrent = function () {
|
||||
return current;
|
||||
};
|
||||
|
||||
/**
|
||||
* 填充数据
|
||||
* @param {int} 页码
|
||||
*/
|
||||
this.filling = function (index) {
|
||||
var html = '';
|
||||
current = parseInt(index) || parseInt(opts.current); //当前页码
|
||||
var pageCount = this.getPageCount(); //获取的总页数
|
||||
switch (opts.mode) { //配置模式
|
||||
case 'fixed': //固定按钮模式
|
||||
html += '<li class="page-item"><a href="javascript:;" class="page-link ' + opts.prevCls + '">' + opts.prevContent + '</a></li>';
|
||||
if (opts.coping) {
|
||||
var home = opts.coping && opts.homePage ? opts.homePage : '1';
|
||||
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="1">' + home + '</a></li>';
|
||||
}
|
||||
var start = current > opts.count - 1 ? current + opts.count - 1 > pageCount ? current - (opts.count - (pageCount - current)) : current - 2 : 1;
|
||||
var end = current + opts.count - 1 > pageCount ? pageCount : start + opts.count;
|
||||
for (; start <= end; start++) {
|
||||
if (start != current) {
|
||||
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="' + start + '">' + start + '</a></li>';
|
||||
} else {
|
||||
html += '<li class="page-item active"><span class="page-link ' + opts.activeCls + '">' + start + '</span></li>';
|
||||
}
|
||||
}
|
||||
if (opts.coping) {
|
||||
var _end = opts.coping && opts.endPage ? opts.endPage : pageCount;
|
||||
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="' + pageCount + '">' + _end + '</a></li>';
|
||||
}
|
||||
html += '<li class="page-item"><a href="javascript:;" class="page-link ' + opts.nextCls + '">' + opts.nextContent + '</a></li>';
|
||||
break;
|
||||
|
||||
// if (opts.keepShowPN || current > 1) { //上一页
|
||||
// html += '<a href="javascript:;" class="' + opts.prevCls + '">' + opts.prevContent + '</a>';
|
||||
// } else {
|
||||
// if (opts.keepShowPN == false) {
|
||||
// $obj.find('.' + opts.prevCls) && $obj.find('.' + opts.prevCls).remove();
|
||||
// }
|
||||
// }
|
||||
// if (current >= opts.count + 2 && current != 1 && pageCount != opts.count) {
|
||||
// var home = opts.coping && opts.homePage ? opts.homePage : '1';
|
||||
// html += opts.coping ? '<a href="javascript:;" data-page="1">' + home + '</a><span>...</span>' : '';
|
||||
// }
|
||||
// var start = (current - opts.count) <= 1 ? 1 : (current - opts.count);
|
||||
// var end = (current + opts.count) >= pageCount ? pageCount : (current + opts.count);
|
||||
// for (; start <= end; start++) {
|
||||
// if (start <= pageCount && start >= 1) {
|
||||
// if (start != current) {
|
||||
// html += '<a href="javascript:;" data-page="' + start + '">' + start + '</a>';
|
||||
// } else {
|
||||
// html += '<span class="' + opts.activeCls + '">' + start + '</span>';
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (current + opts.count < pageCount && current >= 1 && pageCount > opts.count) {
|
||||
// var end = opts.coping && opts.endPage ? opts.endPage : pageCount;
|
||||
// html += opts.coping ? '<span>...</span><a href="javascript:;" data-page="' + pageCount + '">' + end + '</a>' : '';
|
||||
// }
|
||||
// if (opts.keepShowPN || current < pageCount) { //下一页
|
||||
// html += '<a href="javascript:;" class="' + opts.nextCls + '">' + opts.nextContent + '</a>';
|
||||
// } else {
|
||||
// if (opts.keepShowPN == false) {
|
||||
// $obj.find('.' + opts.nextCls) && $obj.find('.' + opts.nextCls).remove();
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
case 'unfixed': //不固定按钮模式
|
||||
if (opts.keepShowPN || current > 1) { //上一页
|
||||
html += '<a href="javascript:;" class="' + opts.prevCls + '">' + opts.prevContent + '</a>';
|
||||
} else {
|
||||
if (opts.keepShowPN == false) {
|
||||
$obj.find('.' + opts.prevCls) && $obj.find('.' + opts.prevCls).remove();
|
||||
}
|
||||
}
|
||||
if (current >= opts.count + 2 && current != 1 && pageCount != opts.count) {
|
||||
var home = opts.coping && opts.homePage ? opts.homePage : '1';
|
||||
html += opts.coping ? '<a href="javascript:;" data-page="1">' + home + '</a><span>...</span>' : '';
|
||||
}
|
||||
var start = (current - opts.count) <= 1 ? 1 : (current - opts.count);
|
||||
var end = (current + opts.count) >= pageCount ? pageCount : (current + opts.count);
|
||||
for (; start <= end; start++) {
|
||||
if (start <= pageCount && start >= 1) {
|
||||
if (start != current) {
|
||||
html += '<a href="javascript:;" data-page="' + start + '">' + start + '</a>';
|
||||
} else {
|
||||
html += '<span class="' + opts.activeCls + '">' + start + '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current + opts.count < pageCount && current >= 1 && pageCount > opts.count) {
|
||||
var end = opts.coping && opts.endPage ? opts.endPage : pageCount;
|
||||
html += opts.coping ? '<span>...</span><a href="javascript:;" data-page="' + pageCount + '">' + end + '</a>' : '';
|
||||
}
|
||||
if (opts.keepShowPN || current < pageCount) { //下一页
|
||||
html += '<a href="javascript:;" class="' + opts.nextCls + '">' + opts.nextContent + '</a>';
|
||||
} else {
|
||||
if (opts.keepShowPN == false) {
|
||||
$obj.find('.' + opts.nextCls) && $obj.find('.' + opts.nextCls).remove();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'easy': //简单模式
|
||||
break;
|
||||
default:
|
||||
}
|
||||
html += opts.jump ? '<input type="text" class="' + opts.jumpIptCls + '"><a href="javascript:;" class="' + opts.jumpBtnCls + '">' + opts.jumpBtn + '</a>' : '';
|
||||
$obj.empty().html(html);
|
||||
};
|
||||
|
||||
//绑定事件
|
||||
this.eventBind = function () {
|
||||
var that = this;
|
||||
var pageCount = that.getPageCount(); //总页数
|
||||
var index = 1;
|
||||
$obj.off().on('click', 'a', function () {
|
||||
if ($(this).hasClass(opts.nextCls)) {
|
||||
if (parseInt($obj.find('.' + opts.activeCls).text()) >= pageCount) {
|
||||
$(this).addClass('disabled');
|
||||
return false;
|
||||
} else {
|
||||
index = parseInt($obj.find('.' + opts.activeCls).text()) + 1;
|
||||
}
|
||||
} else if ($(this).hasClass(opts.prevCls)) {
|
||||
if (parseInt($obj.find('.' + opts.activeCls).text()) <= 1) {
|
||||
$(this).addClass('disabled');
|
||||
return false;
|
||||
} else {
|
||||
index = parseInt($obj.find('.' + opts.activeCls).text()) - 1;
|
||||
}
|
||||
} else if ($(this).hasClass(opts.jumpBtnCls)) {
|
||||
if ($obj.find('.' + opts.jumpIptCls).val() !== '') {
|
||||
index = parseInt($obj.find('.' + opts.jumpIptCls).val());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
index = parseInt($(this).data('page'));
|
||||
}
|
||||
that.filling(index);
|
||||
typeof opts.callback === 'function' && opts.callback(that);
|
||||
});
|
||||
//输入跳转的页码
|
||||
$obj.on('input propertychange', '.' + opts.jumpIptCls, function () {
|
||||
var $this = $(this);
|
||||
var val = $this.val();
|
||||
var reg = /[^\d]/g;
|
||||
if (reg.test(val)) $this.val(val.replace(reg, ''));
|
||||
(parseInt(val) > pageCount) && $this.val(pageCount);
|
||||
if (parseInt(val) === 0) $this.val(1); //最小值为1
|
||||
});
|
||||
//回车跳转指定页码
|
||||
$document.keydown(function (e) {
|
||||
if (e.keyCode == 13 && $obj.find('.' + opts.jumpIptCls).val()) {
|
||||
var index = parseInt($obj.find('.' + opts.jumpIptCls).val());
|
||||
that.filling(index);
|
||||
typeof opts.callback === 'function' && opts.callback(that);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//初始化
|
||||
this.init = function () {
|
||||
this.filling(opts.current);
|
||||
this.eventBind();
|
||||
if (opts.isHide && this.getPageCount() == '1' || this.getPageCount() == '0') {
|
||||
$obj.hide();
|
||||
} else {
|
||||
$obj.show();
|
||||
}
|
||||
};
|
||||
this.init();
|
||||
};
|
||||
|
||||
$.fn.pagination = function (parameter, callback) {
|
||||
if (typeof parameter == 'function') { //重载
|
||||
callback = parameter;
|
||||
parameter = {};
|
||||
} else {
|
||||
parameter = parameter || {};
|
||||
callback = callback || function () {};
|
||||
}
|
||||
var options = $.extend({}, defaults, parameter);
|
||||
return this.each(function () {
|
||||
var pagination = new Pagination(this, options);
|
||||
callback(pagination);
|
||||
});
|
||||
};
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,164 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">新增管理员</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label>用户名</label>
|
||||
<input type="text" class="form-control" maxlength="10" id="username"
|
||||
placeholder="请输入用户名">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>昵称</label>
|
||||
<input type="text" class="form-control" maxlength="10" id="nickname"
|
||||
placeholder="请输入昵称">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>手机号</label>
|
||||
<input type="text" class="form-control" maxlength="11" id="mobile"
|
||||
placeholder="请输入手机号">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>密码</label>
|
||||
<input type="password" class="form-control" maxlength="20" id="password"
|
||||
placeholder="请输入密码">
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$("input#username").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("input#nickname").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("input#mobile").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("input#password").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const username = $("#username").val();
|
||||
if (username === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入用户名。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const nickname = $("#nickname").val();
|
||||
if (nickname === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入昵称。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const password = $("#password").val();
|
||||
if (password === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
username: username,
|
||||
nickname: nickname,
|
||||
mobile: $("#mobile").val(),
|
||||
password: md5(password),
|
||||
};
|
||||
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/admin",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 创建完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.href = "/admin/list";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,328 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar d-flex flex-column flex-md-row">
|
||||
<div class="toolbar-btn-action">
|
||||
<a class="btn btn-primary m-r-5" href="/admin/add"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>用户名</th>
|
||||
<th>昵称</th>
|
||||
<th>手机号</th>
|
||||
<th>创建日期</th>
|
||||
<th>更新日期</th>
|
||||
<th style="text-align: center; ">状态</th>
|
||||
<th style="text-align: center; ">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="tbody">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
<ul class="pagination" id="paginationDiv">
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
// 加载列表页数据
|
||||
getPageListData();
|
||||
|
||||
function getPageListData(page = 0, page_size = 0) {
|
||||
|
||||
if (parseInt(page) < 1) {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
if (parseInt(page_size) < 1) {
|
||||
page_size = 10;
|
||||
}
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/admin",
|
||||
{page: page, page_size: page_size},
|
||||
function () {},
|
||||
function (data) {
|
||||
if (data.list.length > 0) {
|
||||
var totalNum = data.pagination.total; //总条数
|
||||
var pageNum = Math.ceil(totalNum / data.pagination.pre_page_count); //分页的总页数
|
||||
|
||||
$("#paginationDiv").pagination({
|
||||
current: data.pagination.current_page,
|
||||
pageCount: pageNum,
|
||||
coping: true,
|
||||
homePage: '首页',
|
||||
endPage: '末页',
|
||||
mode: 'fixed',
|
||||
prevContent: '上一页',
|
||||
nextContent: '下一页',
|
||||
activeCls: 'pageActive',
|
||||
prevCls: 'pagePrev',
|
||||
nextCls: 'pageNext',
|
||||
callback: function (api) {
|
||||
$(".tbody").html("");
|
||||
getPageListData(api.getCurrent());
|
||||
}
|
||||
});
|
||||
|
||||
$.each(data.list, function (index, value) {
|
||||
var showUsedBadge = "";
|
||||
var optionUsedName = "";
|
||||
|
||||
if (value.is_used === 1) {
|
||||
optionUsedName = '禁用';
|
||||
showUsedBadge = '<span class="badge badge-success">启用</span></td>'
|
||||
}
|
||||
|
||||
if (value.is_used === -1) {
|
||||
optionUsedName = '启用';
|
||||
showUsedBadge = '<span class="badge badge-danger">禁用</span></td>'
|
||||
}
|
||||
|
||||
const tr = '<tr>\n' +
|
||||
'<td>' + value.id + '</td>\n' +
|
||||
'<td>' + value.username + '</td>\n' +
|
||||
'<td>' + value.nickname + '</td>\n' +
|
||||
'<td>' + value.mobile + '</td>\n' +
|
||||
'<td>' + value.created_at + '</td>\n' +
|
||||
'<td>' + value.updated_at + '</td>\n' +
|
||||
'<td style="text-align: center; ">' + showUsedBadge + '</td>\n' +
|
||||
'<td style="text-align: center; ">\n' +
|
||||
'<div class="btn-group">\n' +
|
||||
' <a class="btn btn-xs btn-default btn-option" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-is-used="' + value.is_used + '"' +
|
||||
' data-toggle="tooltip" data-original-title="' + optionUsedName + '">' + optionUsedName + '</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-resetPassword" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="重置密码">重置密码</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-confirm" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="删除">删除</a>\n' +
|
||||
'</div>\n' +
|
||||
'</td>\n' +
|
||||
'</tr>';
|
||||
|
||||
$(".tbody").append(tr);
|
||||
})
|
||||
} else {
|
||||
// 数据为空
|
||||
const tr = '<tr><td colspan="8" style="text-align: center">暂无数据</td></tr>';
|
||||
$(".tbody").append(tr);
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
// 启用/禁用
|
||||
$(document).on('click', '.btn-option', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
const isUsed = $(this).attr('data-is-used');
|
||||
|
||||
var tipMessage = "";
|
||||
var wantUsed = 0;
|
||||
if (isUsed === "1") { // 1=当前为启用状态,需要改成禁用
|
||||
tipMessage = "禁用";
|
||||
wantUsed = -1;
|
||||
}
|
||||
if (isUsed === "-1") { // -1=当前为禁用状态,需要改成启用
|
||||
tipMessage = "启用";
|
||||
wantUsed = 1;
|
||||
}
|
||||
|
||||
const patchData = {
|
||||
id: id,
|
||||
used: wantUsed,
|
||||
};
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">' + tipMessage + '</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/admin/used",
|
||||
patchData,
|
||||
function () {},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 已' + tipMessage + '。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 重置密码
|
||||
$(document).on('click', '.btn-resetPassword', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">重置密码</strong> 吗?' + '<hr>' + '重置后密码为:123456',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
'/api/admin/reset_password/' + id,
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 密码重置完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 删除
|
||||
$(document).on('click', '.btn-confirm', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">删除</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"DELETE",
|
||||
'/api/admin/' + id,
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 已删除。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
|
||||
<title>登录页面</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="bootstrap/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/style.min.css">
|
||||
|
||||
<style>
|
||||
.login-form .has-feedback {
|
||||
position: relative;
|
||||
}
|
||||
.login-form .has-feedback .form-control {
|
||||
padding-left: 36px;
|
||||
}
|
||||
.login-form .has-feedback .mdi {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: auto;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
z-index: 4;
|
||||
color: #dcdcdc;
|
||||
display: block;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.login-form .has-feedback.row .mdi {
|
||||
left: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="center-vh">
|
||||
<div class="card card-shadowed p-5 w-420 mb-0 mr-2 ml-2">
|
||||
<div class="text-center mb-3">
|
||||
<img src="../../bootstrap/images/logo-sidebar.png">
|
||||
</div>
|
||||
<form class="login-form">
|
||||
<div class="form-group has-feedback">
|
||||
<span class="mdi mdi-account" aria-hidden="true"></span>
|
||||
<input type="text" class="form-control" id="username" placeholder="用户名">
|
||||
</div>
|
||||
|
||||
<div class="form-group has-feedback">
|
||||
<span class="mdi mdi-lock" aria-hidden="true"></span>
|
||||
<input type="password" class="form-control" id="password" placeholder="密码">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button class="btn btn-block btn-primary" id="btnOk" type="button">立即登录</button>
|
||||
</div>
|
||||
<div class="alert alert-primary" style="text-align: center;" role="alert">
|
||||
默认
|
||||
<span class="mdi mdi-account" aria-hidden="true"></span> admin
|
||||
<span class="mdi mdi-lock" aria-hidden="true"></span> admin
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#btnOk').on('click', function () {
|
||||
const username = $("#username").val();
|
||||
if (username === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入用户名。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const password = $("#password").val();
|
||||
if (password === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
username: username,
|
||||
password: md5(password),
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/login/web",
|
||||
postData,
|
||||
function () {},
|
||||
function (data) {
|
||||
let date = new Date();
|
||||
date.setTime(date.getTime() + 24 * 60 * 60 * 1000); // 24 * 60 * 60 * 1000 表示 24 小时
|
||||
$.cookie('_login_token_', data.token, {expires: date});
|
||||
|
||||
location.href = "/";
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">个人信息</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<form class="site-form">
|
||||
<div class="form-group">
|
||||
<label>用户名</label>
|
||||
<input type="text" class="form-control" id="username" disabled="disabled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>昵称</label>
|
||||
<input type="text" class="form-control" maxlength="10" id="nickname" placeholder="输入您的昵称">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>手机号</label>
|
||||
<input type="text" class="form-control" maxlength="11" id="mobile" placeholder="请输入您的手机号">
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">保存</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$("input#nickname, input#mobile").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/admin/info",
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$("#username").val(data.username);
|
||||
$("#nickname").val(data.nickname);
|
||||
$("#mobile").val(data.mobile);
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const nickname = $("#nickname").val();
|
||||
if (nickname === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入您的昵称。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
nickname: nickname,
|
||||
mobile: $("#mobile").val(),
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/admin/modify_personal_info",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function () {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '信息修改成功。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">新增管理员</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label>旧密码</label>
|
||||
<input type="password" class="form-control" maxlength="20" id="old_password"
|
||||
placeholder="输入账号的原登录密码">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>新密码</label>
|
||||
<input type="password" class="form-control" maxlength="20" id="new_password"
|
||||
placeholder="输入新的密码">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>确认新密码</label>
|
||||
<input type="password" class="form-control" maxlength="20" id="confirm_password"
|
||||
placeholder="再次输入新的密码">
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$("input#old_password, input#new_password, input#confirm_password").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const old_password = $("#old_password").val();
|
||||
if (old_password === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入账号的原登录密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const new_password = $("#new_password").val();
|
||||
if (new_password === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入新的密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const confirm_password = $("#confirm_password").val();
|
||||
if (confirm_password === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请再次输入新的密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (new_password !== confirm_password) {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请确认两次密码一致。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
old_password: md5(old_password),
|
||||
new_password: md5(new_password),
|
||||
};
|
||||
|
||||
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/admin/modify_password",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function () {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '密码修改成功。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">新增调用方</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="formGroupExampleInput">调用方</label>
|
||||
<input type="text" class="form-control" maxlength="25" id="business_key"
|
||||
placeholder="请输入调用方标识">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="formGroupExampleInput2">调用方对接人</label>
|
||||
<input type="text" class="form-control" maxlength="50" id="business_developer"
|
||||
placeholder="请输入调用方对接人">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="exampleFormControlTextarea1">备注</label>
|
||||
<textarea class="form-control" maxlength="225" rows="3" id="remark"
|
||||
placeholder="备注"></textarea>
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$("input#business_key").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("input#business_developer").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("textarea#remark").maxlength({
|
||||
threshold: 255,
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const businessKey = $("#business_key").val();
|
||||
if (businessKey === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入调用方标识。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const businessDeveloper = $("#business_developer").val();
|
||||
if (businessDeveloper === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入调用方对接人。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
business_key: businessKey,
|
||||
business_developer: businessDeveloper,
|
||||
remark: $("#remark").val(),
|
||||
};
|
||||
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/authorized",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 创建完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.href = "/authorized/list";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,259 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">接口授权</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="alert alert-warning" role="alert">
|
||||
接口地址支持通配符(*),其中 * 表示 1 级,** 表示 n 级。
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="request_method">选择请求方式</label>
|
||||
</div>
|
||||
<select class="custom-select" id="request_method">
|
||||
<option value="GET">GET</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="DELETE">DELETE</option>
|
||||
<option value="PATCH">PATCH</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="inputGroup-sizing-default">输入接口地址</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" maxlength="60" id="request_api"
|
||||
placeholder="接口地址">
|
||||
</div>
|
||||
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">已授权接口</div>
|
||||
</header>
|
||||
<div class="card-body apis">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
const hash_id = {{ .HashID }}
|
||||
|
||||
$("input#request_api").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
// 加载列表页数据
|
||||
getListData();
|
||||
|
||||
function getListData() {
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/authorized_api",
|
||||
{id: hash_id},
|
||||
function () {
|
||||
|
||||
},
|
||||
function (data) {
|
||||
if (data.list.length > 0) {
|
||||
var badgeMethodClass = "";
|
||||
|
||||
$.each(data.list, function (index, value) {
|
||||
if (value.method === "GET") {
|
||||
badgeMethodClass = "badge-primary";
|
||||
} else if (value.method === "POST") {
|
||||
badgeMethodClass = "badge-success";
|
||||
} else if (value.method === "DELETE") {
|
||||
badgeMethodClass = "badge-danger";
|
||||
} else if (value.method === "PUT") {
|
||||
badgeMethodClass = "badge-yellow";
|
||||
} else if (value.method === "PATCH") {
|
||||
badgeMethodClass = "badge-cyan";
|
||||
} else {
|
||||
badgeMethodClass = "badge-dark";
|
||||
}
|
||||
|
||||
const p = '<p>\n' +
|
||||
'<a href="#!" data-id="' + value.hash_id + '" data-api="' + value.api + '" class="del">' +
|
||||
'<span class="badge badge-dark"><i class="mdi mdi-window-close"></i></span>\n' +
|
||||
'</a>\n' +
|
||||
'<span class="badge ' + badgeMethodClass + '">' + value.method + '</span>\n' + value.api
|
||||
;
|
||||
|
||||
$(".apis").append(p);
|
||||
})
|
||||
} else {
|
||||
// 数据为空
|
||||
const p = '<p>暂无授权接口</p>';
|
||||
$(".apis").append(p);
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const requestMethod = $("#request_method").val();
|
||||
const requestApi = $("#request_api").val();
|
||||
if (requestMethod === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请选择请求方式。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requestApi === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入请求地址。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
method: requestMethod,
|
||||
api: requestApi,
|
||||
id: hash_id,
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/authorized_api",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function () {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '接口:' + requestApi + ' 授权完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$(document).on('click', '.del', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
const api = $(this).attr('data-api');
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">取消授权</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"DELETE",
|
||||
'/api/authorized_api/' + id,
|
||||
"",
|
||||
function () {
|
||||
|
||||
},
|
||||
function () {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '接口:' + api + ' 已取消授权。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,214 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">如何给调用方开通 KEY 和 SECRET?</div>
|
||||
</header>
|
||||
|
||||
<div class="card-body">
|
||||
<p>1. 新增调用方,输入调用方标识、调用方对接人、备注等信息;</p>
|
||||
<p>2. 授权调用方可调用的接口;</p>
|
||||
<p>3. 查看详情,将调用方的 <code>KEY</code>、<code>SECRET</code> 发给调用方;</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">调用方如何传递 Token?</div>
|
||||
</header>
|
||||
|
||||
<div class="card-body">
|
||||
<p>基于 HTTP Header 中的两个参数 <code>Authorization</code>、<code>Authorization-Date</code> 存储签名信息。</p>
|
||||
<p>1. Authorization 存储签名信息,格式:调用方 KEY + 空格分隔符 + 摘要(加密串),例如:</p>
|
||||
<pre>Authorization:blog MjJjMDE1MWFkZjMwOWFmYjFlNzViNDFjYjYwMWFlMmM=</pre>
|
||||
<p>2. Authorization-Date 存储时间信息,格式:0000-00-00 00:00:00,使用 <code>Asia/Shanghai</code> 时区,例如;</p>
|
||||
<pre>Authorization-Date:2021-04-03 21:12:36</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<header class="card-header"><div class="card-title">不同语言生成签名的方法,供参考</div></header>
|
||||
<div class="card-body">
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#go" aria-selected="true">Go 语言</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#php" aria-selected="false">PHP 语言</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#js" aria-selected="false">JS 语言</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade active show" id="go">
|
||||
<pre>
|
||||
func New(key, secret string, ttl time.Duration) Signature {
|
||||
return &signature{
|
||||
key: key,
|
||||
secret: secret,
|
||||
ttl: ttl,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate
|
||||
// path 请求的路径 (不附带 querystring)
|
||||
func (s *signature) Generate(path string, method string, params url.Values) (authorization, date string, err error) {
|
||||
if path == "" {
|
||||
err = errors.New("path required")
|
||||
return
|
||||
}
|
||||
|
||||
if method == "" {
|
||||
err = errors.New("method required")
|
||||
return
|
||||
}
|
||||
|
||||
methodName := strings.ToUpper(method)
|
||||
if !methods[methodName] {
|
||||
err = errors.New("method param error")
|
||||
return
|
||||
}
|
||||
|
||||
// Date
|
||||
date = time_parse.CSTLayoutString()
|
||||
|
||||
// Encode() 方法中自带 sorted by key
|
||||
sortParamsEncode, err := url.QueryUnescape(params.Encode())
|
||||
if err != nil {
|
||||
err = errors.Errorf("url QueryUnescape %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 加密字符串规则
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
buffer.WriteString(path)
|
||||
buffer.WriteString(delimiter)
|
||||
buffer.WriteString(methodName)
|
||||
buffer.WriteString(delimiter)
|
||||
buffer.WriteString(sortParamsEncode)
|
||||
buffer.WriteString(delimiter)
|
||||
buffer.WriteString(date)
|
||||
|
||||
// 对数据进行 sha256 加密,并进行 base64 encode
|
||||
hash := hmac.New(sha256.New, []byte(s.secret))
|
||||
hash.Write(buffer.Bytes())
|
||||
digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
||||
|
||||
authorization = fmt.Sprintf("%s %s", s.key, digest)
|
||||
return
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
const (
|
||||
key = "blog"
|
||||
secret = "i1ydX9RtHyuJTrw7frcu"
|
||||
ttl = time.Minute * 10
|
||||
)
|
||||
|
||||
func TestSignature_Generate(t *testing.T) {
|
||||
path := "/echo"
|
||||
method := "POST"
|
||||
|
||||
params := url.Values{}
|
||||
params.Add("a", "a1")
|
||||
params.Add("d", "d1")
|
||||
params.Add("c", "c1 c2*")
|
||||
|
||||
authorization, date, err := New(key, secret, ttl).Generate(path, method, params)
|
||||
t.Log("authorization:", authorization)
|
||||
t.Log("authorization-date:", date)
|
||||
t.Log("err:", err)
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="php">
|
||||
<pre>
|
||||
// 模拟数据
|
||||
$key = "blog";
|
||||
$secret = "i1ydX9RtHyuJTrw7frcu";
|
||||
|
||||
$path = "/echo";
|
||||
$method = "POST";
|
||||
|
||||
$params['a'] = "a1";
|
||||
$params['d'] = "d1";
|
||||
$params['c'] = "c1 c2*";
|
||||
|
||||
// 对 params key 进行排序
|
||||
ksort($params);
|
||||
|
||||
// 对 sortParams 进行操作
|
||||
$sortParamsEncode = rawurldecode(http_build_query($params, "", "&", PHP_QUERY_RFC3986));
|
||||
|
||||
// 时间 使用 Asia/Shanghai 时区
|
||||
$date = date("Y-m-d H:i:s", time());
|
||||
|
||||
// 加密字符串规则
|
||||
$encryptStr = $path."|".strtoupper($method)."|".$sortParamsEncode."|".$date;
|
||||
|
||||
// 对数据进行 sha256 加密,并进行 base64 encode
|
||||
$digest = base64_encode(hash_hmac("sha256", $encryptStr, $secret, true));
|
||||
|
||||
$authorization = $key." ".$digest;
|
||||
|
||||
echo "authorization:{$authorization}";
|
||||
echo "---";
|
||||
echo "authorization-date:{$date}";
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="js">
|
||||
<pre>
|
||||
let key = "blog";
|
||||
let secret = "i1ydX9RtHyuJTrw7frcu";
|
||||
|
||||
let date = new Date();
|
||||
let datetime = date.getFullYear() + "-" // "年"
|
||||
+ ((date.getMonth() + 1) > 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
|
||||
+ (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " " // "日"
|
||||
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" // "小时"
|
||||
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":" // "分钟"
|
||||
+ (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()); // "秒"
|
||||
|
||||
let path = "/echo";
|
||||
let method = "POST";
|
||||
let params = {a:'a1', d:'d1', c: 'c1 c2*'};
|
||||
|
||||
let sortParamsEncode = decodeURIComponent(jQuery.param(ksort(params)));
|
||||
let encryptStr = path + "|" + method.toUpperCase() + "|" + sortParamsEncode + "|" + datetime;
|
||||
let digest = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(encryptStr, secret));
|
||||
console.log({authorization: key + " " + digest, date: datetime});
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/main.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,294 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar d-flex flex-column flex-md-row">
|
||||
<div class="toolbar-btn-action">
|
||||
<a class="btn btn-primary m-r-5" href="/authorized/add"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>调用方</th>
|
||||
<th>对接人</th>
|
||||
<th>创建日期</th>
|
||||
<th>更新日期</th>
|
||||
<th style="text-align: center; ">状态</th>
|
||||
<th style="text-align: center; ">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="tbody">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
<ul class="pagination" id="paginationDiv">
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
// 加载列表页数据
|
||||
getPageListData();
|
||||
|
||||
function getPageListData(page = 0, page_size = 0) {
|
||||
|
||||
if (parseInt(page) < 1) {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
if (parseInt(page_size) < 1) {
|
||||
page_size = 10;
|
||||
}
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/authorized",
|
||||
{page: page, page_size: page_size},
|
||||
function () {},
|
||||
function (data) {
|
||||
if (data.list.length > 0) {
|
||||
var totalNum = data.pagination.total; //总条数
|
||||
var pageNum = Math.ceil(totalNum / data.pagination.pre_page_count); //分页的总页数
|
||||
|
||||
$("#paginationDiv").pagination({
|
||||
current: data.pagination.current_page,
|
||||
pageCount: pageNum,
|
||||
coping: true,
|
||||
homePage: '首页',
|
||||
endPage: '末页',
|
||||
mode: 'fixed',
|
||||
prevContent: '上一页',
|
||||
nextContent: '下一页',
|
||||
activeCls: 'pageActive',
|
||||
prevCls: 'pagePrev',
|
||||
nextCls: 'pageNext',
|
||||
callback: function (api) {
|
||||
$(".tbody").html("");
|
||||
getPageListData(api.getCurrent());
|
||||
}
|
||||
});
|
||||
|
||||
$.each(data.list, function (index, value) {
|
||||
var showUsedBadge = "";
|
||||
var optionUsedName = "";
|
||||
|
||||
if (value.is_used === 1) {
|
||||
optionUsedName = '禁用';
|
||||
showUsedBadge = '<span class="badge badge-success">启用</span></td>'
|
||||
}
|
||||
|
||||
if (value.is_used === -1) {
|
||||
optionUsedName = '启用';
|
||||
showUsedBadge = '<span class="badge badge-danger">禁用</span></td>'
|
||||
}
|
||||
|
||||
const tr = '<tr>\n' +
|
||||
'<td>' + value.id + '</td>\n' +
|
||||
'<td>' + value.business_key + '</td>\n' +
|
||||
'<td>' + value.business_developer + '</td>\n' +
|
||||
'<td>' + value.created_at + '</td>\n' +
|
||||
'<td>' + value.updated_at + '</td>\n' +
|
||||
'<td style="text-align: center; ">' + showUsedBadge + '</td>\n' +
|
||||
'<td style="text-align: center; ">\n' +
|
||||
'<div class="btn-group">\n' +
|
||||
' <a class="btn btn-xs btn-default btn-detail" href="#!" title=""\n' +
|
||||
' data-business-key="' + value.business_key + '"' +
|
||||
' data-business-secret="' + value.business_secret + '"' +
|
||||
' data-remark="' + value.remark + '"' +
|
||||
' data-toggle="tooltip" data-original-title="详情">详情</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-option" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-is-used="' + value.is_used + '"' +
|
||||
' data-toggle="tooltip" data-original-title="' + optionUsedName + '">' + optionUsedName + '</a>\n' +
|
||||
' <a class="btn btn-xs btn-default" href="/authorized/api/'+value.hashid+'" title=""\n' +
|
||||
' data-toggle="tooltip" data-original-title="接口">接口</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-confirm" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="删除">删除</a>\n' +
|
||||
'</div>\n' +
|
||||
'</td>\n' +
|
||||
'</tr>';
|
||||
|
||||
$(".tbody").append(tr);
|
||||
})
|
||||
} else {
|
||||
// 数据为空
|
||||
const tr = '<tr><td colspan="7" style="text-align: center">暂无数据</td></tr>';
|
||||
$(".tbody").append(tr);
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
// 详情
|
||||
$(document).on('click', '.btn-detail', function () {
|
||||
const business_key = $(this).attr('data-business-key');
|
||||
const business_secret = $(this).attr('data-business-secret');
|
||||
const business_remark = $(this).attr('data-remark');
|
||||
|
||||
$.alert({
|
||||
title: '详情',
|
||||
content: '调用方 KEY :' + business_key + '<br/>调用方 SECRET :' + business_secret + '<br/>备注:' + business_remark,
|
||||
type: 'green',
|
||||
animation: 'scale',
|
||||
draggable: true,
|
||||
});
|
||||
});
|
||||
|
||||
// 启用/禁用
|
||||
$(document).on('click', '.btn-option', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
const isUsed = $(this).attr('data-is-used');
|
||||
|
||||
var tipMessage = "";
|
||||
var wantUsed = 0;
|
||||
if (isUsed === "1") { // 1=当前为启用状态,需要改成禁用
|
||||
tipMessage = "禁用";
|
||||
wantUsed = -1;
|
||||
}
|
||||
if (isUsed === "-1") { // -1=当前为禁用状态,需要改成启用
|
||||
tipMessage = "启用";
|
||||
wantUsed = 1;
|
||||
}
|
||||
|
||||
const patchData = {
|
||||
id: id,
|
||||
used: wantUsed,
|
||||
};
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">' + tipMessage + '</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/authorized/used",
|
||||
patchData,
|
||||
function () {},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 已' + tipMessage + '。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 删除
|
||||
$(document).on('click', '.btn-confirm', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">删除</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"DELETE",
|
||||
'/api/authorized/' + id,
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 已删除。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||
<link href="bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
@@ -16,9 +18,10 @@
|
||||
<div class="card-body">
|
||||
<div class="callout callout-warning mb-3">注意:请在 <code>Mac</code> 或 <code>Linux</code> 环境执行。</div>
|
||||
<p>初始化项目所需信息:</p>
|
||||
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>user_demo</code> ;</span></p>
|
||||
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>authorized</code> ;</span></p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>authorized_api</code> ;</span></p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>admin</code> ;</span></p>
|
||||
<p>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
@@ -44,6 +47,7 @@
|
||||
|
||||
<script type="text/javascript" src="bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#btnOk").click(function(){
|
||||
@@ -56,9 +60,34 @@
|
||||
$("#resultDiv").text(data);
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
if (getQueryString("init")) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '初始化完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '系统首页',
|
||||
action: function () {
|
||||
location.href = "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
function getQueryString(name) {
|
||||
let reg = new RegExp('(?:(?:&|\\?)' + name + '=([^&]*))|(?:/' + name + '/([^/]*))', 'i');
|
||||
let r = window.location.href.match(reg);
|
||||
if (r != null)
|
||||
return decodeURI(r[1] || r[2]);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/js/bootstrap-multitabs/multitabs.min.css">
|
||||
@@ -32,21 +33,44 @@
|
||||
|
||||
<nav class="sidebar-main">
|
||||
<ul class="nav-drawer">
|
||||
<li class="nav-item active"> <a class="multitabs" href="/dashboard"><i class="mdi mdi-home"></i> <span>仪表盘</span></a> </li>
|
||||
<li class="nav-item"> <a class="multitabs" href="/configinfo"><i class="mdi mdi-settings-box"></i> <span>配置信息</span></a> </li>
|
||||
<li class="nav-item active"> <a class="multitabs" href="/dashboard"><i class="mdi mdi-home"></i> <span>仪表盘</span></a> </li>
|
||||
<li class="nav-item"> <a class="multitabs" href="/configinfo"><i class="mdi mdi-settings-box"></i> <span>配置信息</span></a> </li>
|
||||
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-code-not-equal-variant"></i> <span>代码生成</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/init">初始化</a> </li>
|
||||
<li> <a class="multitabs" href="/gormgen">gormgen</a> </li>
|
||||
<li> <a class="multitabs" href="/handlergen">handlergen</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-code-not-equal-variant"></i> <span>代码生成器</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/init">初始化</a> </li>
|
||||
<li> <a class="multitabs" href="/gormgen">gormgen</a> </li>
|
||||
<li> <a class="multitabs" href="/handlergen">handlergen</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item"> <a href="/swagger/index.html" target="_blank" ><i class="mdi mdi-file-document-box"></i> <span>接口文档</span></a> </li>
|
||||
<li class="nav-item"> <a href="/graphql" target="_blank" ><i class="mdi mdi-file-document-box-search"></i> <span>GraphQL</span></a> </li>
|
||||
<li class="nav-item"> <a href="/metrics" target="_blank" ><i class="mdi mdi-speedometer"></i> <span>接口指标</span></a> </li>
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-playlist-check"></i> <span>授权调用方</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/authorized/list">调用方</a> </li>
|
||||
<li> <a class="multitabs" href="/authorized/demo">使用说明</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-account"></i> <span>系统管理员</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/admin/list">管理员</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-tools"></i> <span>实用工具箱</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/tool/hashids">Hashids</a> </li>
|
||||
<li> <a class="multitabs" href="/tool/logs">调用日志</a> </li>
|
||||
<li> <a target="_blank" href="/swagger/index.html">接口文档</a> </li>
|
||||
<li> <a target="_blank" href="/graphql">GraphQL</a> </li>
|
||||
<li> <a target="_blank" href="/metrics">接口指标</a> </li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -183,6 +207,31 @@
|
||||
</li>
|
||||
<!--切换主题配色-->
|
||||
|
||||
<li class="dropdown dropdown-profile">
|
||||
<a href="javascript:void(0)" data-toggle="dropdown" class="dropdown-toggle">
|
||||
<img class="img-avatar img-avatar-48 m-r-10" src="bootstrap/images/users/avatar.png">
|
||||
<span id="nickname"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li>
|
||||
<a class="multitabs dropdown-item" data-url="/admin/modify_info" href="javascript:void(0)">
|
||||
<i class="mdi mdi-account"></i> 个人信息
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="multitabs dropdown-item" data-url="/admin/modify_password" href="javascript:void(0)">
|
||||
<i class="mdi mdi-lock-outline"></i> 修改密码
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown-divider"></li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="javascript:void(0)" id="logout">
|
||||
<i class="mdi mdi-logout-variant"></i> 退出登录
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
@@ -206,6 +255,45 @@
|
||||
<script type="text/javascript" src="bootstrap/js/perfect-scrollbar.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/jquery.cookie.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/index.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/admin/info",
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$("#nickname").html(data.nickname);
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
|
||||
$("#logout").on('click', function () {
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/admin/logout",
|
||||
"",
|
||||
function () {},
|
||||
function () {
|
||||
// 清空 cookie
|
||||
$.cookie('_nav_url_', '');
|
||||
$.cookie('_nav_title_', '');
|
||||
$.cookie('_login_token_', '');
|
||||
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,161 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">hashids 加密</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">数字</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="number" maxlength="10" placeholder="需加密的数字">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" >密文</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" disabled id="NumberToEncodeValue">
|
||||
</div>
|
||||
|
||||
<button type="button" id="btnEncode" class="btn btn-primary">执行</button>
|
||||
<button type="button" id="btnEncodeLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">hashids 解密</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">密文</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="encodeValue" placeholder="需解密的密文">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" >数字</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" disabled id="DecodeValueToNumber">
|
||||
</div>
|
||||
|
||||
<button type="button" id="btnDecode" class="btn btn-primary">执行</button>
|
||||
<button type="button" id="btnDecodeLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$("input#number").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$('#btnEncode').on('click', function () {
|
||||
const number = $("#number").val();
|
||||
if (number === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入需加密的数字。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/tool/hashids/encode/" + number,
|
||||
"",
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnEncodeLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnEncodeLoading").hide();
|
||||
$("#btnEncode").show();
|
||||
$("#NumberToEncodeValue").val(data.val)
|
||||
},
|
||||
function (response) {
|
||||
$("#btnEncodeLoading").hide();
|
||||
$("#btnEncode").show();
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#btnDecode').on('click', function () {
|
||||
const encodeValue = $("#encodeValue").val();
|
||||
if (encodeValue === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入需解密的密文。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/tool/hashids/decode/" + encodeValue,
|
||||
"",
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnDecodeLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnDecodeLoading").hide();
|
||||
$("#btnDecode").show();
|
||||
$("#DecodeValueToNumber").val(data.val)
|
||||
},
|
||||
function (response) {
|
||||
$("#btnDecodeLoading").hide();
|
||||
$("#btnDecode").show();
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
|
||||
<div class="alert alert-info alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>推荐使用: <code>ELK 组件</code> ,本功能仅仅是读取文本进行展示。</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">日志列表 <code>仅展示最新的 100 条日志。</code></div>
|
||||
<ul class="card-actions">
|
||||
<li>
|
||||
<a href="#!" onclick="location.reload();" data-toggle="tooltip" title="" data-original-title="刷新"><i class="mdi mdi-refresh"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<div class="accordion">
|
||||
{{range $key, $value := .Logs}}
|
||||
{{$badgeLevelClass := ""}}
|
||||
{{$badgeMethodClass := ""}}
|
||||
{{$badgeCodeClass := ""}}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
{{if eq $value.Level "info"}}
|
||||
{{$badgeLevelClass = "badge-info"}}
|
||||
{{else if eq $value.Level "error"}}
|
||||
{{$badgeLevelClass = "badge-danger"}}
|
||||
{{else if eq $value.Level "warn"}}
|
||||
{{$badgeLevelClass = "badge-warning"}}
|
||||
{{else}}
|
||||
{{$badgeLevelClass = "badge-dark"}}
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Method "GET"}}
|
||||
{{$badgeMethodClass = "badge-primary"}}
|
||||
{{else if eq $value.Method "POST"}}
|
||||
{{$badgeMethodClass = "badge-success"}}
|
||||
{{else if eq $value.Method "DELETE"}}
|
||||
{{$badgeMethodClass = "badge-danger"}}
|
||||
{{else if eq $value.Method "PUT"}}
|
||||
{{$badgeMethodClass = "badge-yellow"}}
|
||||
{{else if eq $value.Method "PATCH"}}
|
||||
{{$badgeMethodClass = "badge-cyan"}}
|
||||
{{else}}
|
||||
{{$badgeMethodClass = "badge-dark"}}
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.HTTPCode 200}}
|
||||
{{$badgeCodeClass = "badge-success"}}
|
||||
{{else}}
|
||||
{{$badgeCodeClass = "badge-dark"}}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{if eq $value.HTTPCode 0}}
|
||||
<a data-toggle="collapse" data-target="#collapse{{$key}}" aria-expanded="false" href="#!" class="collapsed">
|
||||
<span class="badge {{$badgeLevelClass}}">{{$value.Level}}</span>
|
||||
<span class="badge badge-brown">{{$value.Time}}</span>
|
||||
<code>{{$value.Msg}}</code>
|
||||
</a>
|
||||
{{else}}
|
||||
<a data-toggle="collapse" data-target="#collapse{{$key}}" aria-expanded="false" href="#!" class="collapsed">
|
||||
<span class="badge {{$badgeLevelClass}}">{{$value.Level}}</span>
|
||||
<span class="badge badge-brown">{{$value.Time}}</span>
|
||||
<span class="badge {{$badgeMethodClass}}">{{$value.Method}}</span>
|
||||
<span class="badge {{$badgeCodeClass}}">{{$value.HTTPCode}}</span>
|
||||
<span class="badge badge-muted">{{$value.TraceID}}</span>
|
||||
<span class="badge badge-purple-light">{{$value.CostSeconds}} s</span>
|
||||
<code>{{$value.Path}}</code>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="collapse{{$key}}" class="collapse">
|
||||
<div class="card-body">
|
||||
<pre>{{$value.Content}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+63
-2
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/cmd/init/db/mysql"
|
||||
@@ -42,11 +44,70 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
// 开启事务
|
||||
tx := db.GetDb().Begin()
|
||||
|
||||
// 创建 user_demo 表
|
||||
err = db.GetDb().Exec(mysql.CreateUserDemoTableSql()).Error
|
||||
err = tx.Exec(mysql.CreateUserDemoTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create user_demo table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create user_demo table success")
|
||||
|
||||
// 创建 authorized 表
|
||||
err = tx.Exec(mysql.CreateAuthorizedTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAuthorizedTableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized table data success")
|
||||
|
||||
// 创建 authorized_api 表
|
||||
err = tx.Exec(mysql.CreateAuthorizedAPITableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized_api table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized_api table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAuthorizedAPITableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized_api table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized_api table data success")
|
||||
|
||||
// 创建 admin 表
|
||||
err = tx.Exec(mysql.CreateAdminTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create admin table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create admin table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAdminTableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create admin table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create admin table data success")
|
||||
|
||||
// 生成已完成 init 的标识,生成 init_db.lock
|
||||
f, err := os.Create("cmd/init/db/init_db.lock")
|
||||
if err != nil {
|
||||
log.Fatal("create init_db.lock err: ", err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// 完成事务
|
||||
tx.Commit()
|
||||
|
||||
log.Println("create user_demo table success")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package mysql
|
||||
|
||||
//CREATE TABLE `admin` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
//`password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
|
||||
//`nickname` varchar(60) NOT NULL DEFAULT '' COMMENT '昵称',
|
||||
//`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
//`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`),
|
||||
//UNIQUE KEY `unique_username` (`username`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
|
||||
|
||||
func CreateAdminTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `admin` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',"
|
||||
sql += "`password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',"
|
||||
sql += "`nickname` varchar(60) NOT NULL DEFAULT '' COMMENT '昵称',"
|
||||
sql += "`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',"
|
||||
sql += "`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`),"
|
||||
sql += "UNIQUE KEY `unique_username` (`username`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAdminTableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `admin` (`id`, `username`, `password`, `nickname`, `mobile`, `created_user`) VALUES"
|
||||
sql += "(1, 'admin', 'f78382de80cf583cf854bbac0b6e796fbde36fe2739ca4ae072637010f179cb0', '管理员', '13888888888', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package mysql
|
||||
|
||||
//CREATE TABLE `authorized` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`business_key` varchar(32) NOT NULL DEFAULT '' COMMENT '调用方key',
|
||||
//`business_secret` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方secret',
|
||||
//`business_developer` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方对接人',
|
||||
//`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
|
||||
//`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`),
|
||||
//UNIQUE KEY `unique_business_key` (`business_key`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';
|
||||
|
||||
func CreateAuthorizedTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `authorized` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`business_key` varchar(32) NOT NULL DEFAULT '' COMMENT '调用方key',"
|
||||
sql += "`business_secret` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方secret',"
|
||||
sql += "`business_developer` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方对接人',"
|
||||
sql += "`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',"
|
||||
sql += "`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`),"
|
||||
sql += "UNIQUE KEY `unique_business_key` (`business_key`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAuthorizedTableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `authorized` (`id`, `business_key`, `business_secret`, `business_developer`, `remark`, `created_user`) VALUES (1, 'admin', '12878dd962115106db6d', '管理员', '管理面板调用', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package mysql
|
||||
|
||||
//CREATE TABLE `authorized_api` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`business_key` varchar(30) NOT NULL DEFAULT '' COMMENT '调用方key',
|
||||
//`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',
|
||||
//`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址';
|
||||
|
||||
func CreateAuthorizedAPITableSql() (sql string) {
|
||||
sql = "CREATE TABLE `authorized_api` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`business_key` varchar(30) NOT NULL DEFAULT '' COMMENT '调用方key',"
|
||||
sql += "`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',"
|
||||
sql += "`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAuthorizedAPITableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `authorized_api` (`id`, `business_key`, `method`, `api`,`created_user`) VALUES"
|
||||
sql += "(1, 'admin', 'GET', '/api/**', 'init'),"
|
||||
sql += "(2, 'admin', 'POST', '/api/**', 'init'),"
|
||||
sql += "(3, 'admin', 'PUT', '/api/**', 'init'),"
|
||||
sql += "(4, 'admin', 'DELETE', '/api/**', 'init'),"
|
||||
sql += "(5, 'admin', 'PATCH', '/api/**', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/koketama/errors"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var stdlib = make(map[string]bool)
|
||||
|
||||
func init() {
|
||||
pkgs, err := packages.Load(nil, "std")
|
||||
if err != nil {
|
||||
log.Fatal("get go stdlib err", zap.Error(err))
|
||||
}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
if !strings.HasPrefix(pkg.ID, "vendor") {
|
||||
stdlib[pkg.ID] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var module string
|
||||
|
||||
func init() {
|
||||
file, err := os.Open("./go.mod")
|
||||
if err != nil {
|
||||
log.Fatal("no go.mod file found", zap.Error(err))
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "module ") {
|
||||
module = strings.TrimSpace(line[7:])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if module == "" {
|
||||
log.Fatal("go.mod illegal")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() || strings.HasPrefix(path, ".") || strings.HasPrefix(path, "vendor") || strings.HasSuffix(path, ".pb.go") || filepath.Ext(path) != ".go" {
|
||||
return nil
|
||||
}
|
||||
|
||||
raw, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "read file %s err", path)
|
||||
}
|
||||
|
||||
digest0 := sha256.Sum256(raw)
|
||||
if raw, err = format.Source(raw); err != nil {
|
||||
return errors.Wrapf(err, "format file %s err", path)
|
||||
}
|
||||
|
||||
file, err := parser.ParseFile(token.NewFileSet(), "", raw, 0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parse file %s err", path)
|
||||
}
|
||||
|
||||
var first, last int
|
||||
var imports []*ast.ImportSpec
|
||||
comments := make(map[string]string)
|
||||
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch spec := n.(type) {
|
||||
case *ast.ImportSpec:
|
||||
if first == 0 {
|
||||
first = int(spec.Pos())
|
||||
}
|
||||
last = int(spec.End())
|
||||
|
||||
imports = append(imports, spec)
|
||||
|
||||
k := last - 1
|
||||
for ; k < len(raw); k++ {
|
||||
if raw[k] == '\r' || raw[k] == '\n' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
comment := string(raw[last-1 : k])
|
||||
if index := strings.Index(comment, "//"); index != -1 {
|
||||
comments[spec.Path.Value] = strings.TrimSpace(comment[index+2:])
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if imports != nil {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
buf.Write(raw[:first-2])
|
||||
buf.WriteString(sort(imports, comments))
|
||||
buf.Write(raw[last-1:])
|
||||
|
||||
if raw, err = format.Source(buf.Bytes()); err != nil {
|
||||
return errors.Wrapf(err, "double format file %s err", path)
|
||||
}
|
||||
}
|
||||
|
||||
digest1 := sha256.Sum256(raw)
|
||||
if !bytes.Equal(digest0[:], digest1[:]) {
|
||||
fmt.Println(path)
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(path, raw, info.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "write file %s err", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal("scan project err", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
func sort(imports []*ast.ImportSpec, comments map[string]string) string {
|
||||
system := bytes.NewBuffer(nil)
|
||||
group := bytes.NewBuffer(nil)
|
||||
others := bytes.NewBuffer(nil)
|
||||
|
||||
for _, pkg := range imports {
|
||||
value := strings.Trim(pkg.Path.Value, `"`)
|
||||
switch {
|
||||
case stdlib[value]:
|
||||
if pkg.Name != nil {
|
||||
system.WriteString(pkg.Name.String())
|
||||
system.WriteString(" ")
|
||||
}
|
||||
|
||||
system.WriteString(pkg.Path.Value)
|
||||
if comment, ok := comments[pkg.Path.Value]; ok {
|
||||
system.WriteString(" ")
|
||||
system.WriteString("// ")
|
||||
system.WriteString(comment)
|
||||
}
|
||||
system.WriteString("\n")
|
||||
|
||||
case strings.HasPrefix(value, module):
|
||||
if pkg.Name != nil {
|
||||
group.WriteString(pkg.Name.String())
|
||||
group.WriteString(" ")
|
||||
}
|
||||
|
||||
group.WriteString(pkg.Path.Value)
|
||||
if comment, ok := comments[pkg.Path.Value]; ok {
|
||||
group.WriteString(" ")
|
||||
group.WriteString("// ")
|
||||
group.WriteString(comment)
|
||||
}
|
||||
group.WriteString("\n")
|
||||
|
||||
default:
|
||||
if pkg.Name != nil {
|
||||
others.WriteString(pkg.Name.String())
|
||||
others.WriteString(" ")
|
||||
}
|
||||
|
||||
others.WriteString(pkg.Path.Value)
|
||||
if comment, ok := comments[pkg.Path.Value]; ok {
|
||||
others.WriteString(" ")
|
||||
others.WriteString("// ")
|
||||
others.WriteString(comment)
|
||||
}
|
||||
others.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s\n%s\n%s", system.String(), group.String(), others.String())
|
||||
}
|
||||
@@ -58,6 +58,11 @@ type Config struct {
|
||||
Secret string `toml:"secret"`
|
||||
ExpireDuration time.Duration `toml:"expireDuration"`
|
||||
} `toml:"urlToken"`
|
||||
|
||||
HashIds struct {
|
||||
Secret string `toml:"secret"`
|
||||
Length int `toml:"length"`
|
||||
} `toml:"hashids"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -89,3 +94,7 @@ func ProjectPort() string {
|
||||
func ProjectLogFile() string {
|
||||
return fmt.Sprintf("./logs/%s-access.log", ProjectName())
|
||||
}
|
||||
|
||||
func InitDBLockFile() string {
|
||||
return "cmd/init/db/init_db.lock"
|
||||
}
|
||||
|
||||
@@ -36,4 +36,8 @@ expireDuration = 24 # JWT ExpiresAt 过期时间(单位:小时)
|
||||
|
||||
[urlToken]
|
||||
secret = 'i1ydX9RtHyuJTrw7frcu' # URL Token secret
|
||||
expireDuration = 10 # URL Token ExpiresAt 过期时间(单位:分钟)
|
||||
expireDuration = 10 # URL Token ExpiresAt 过期时间(单位:分钟)
|
||||
|
||||
[hashids]
|
||||
secret = '6ab6122836cfef95f8db' # hashids secret
|
||||
length = 12 # hashids length
|
||||
+1071
File diff suppressed because it is too large
Load Diff
+1071
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,217 @@
|
||||
definitions:
|
||||
admin_handler.createResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
admin_handler.deleteResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
admin_handler.detailResponse:
|
||||
properties:
|
||||
mobile:
|
||||
description: 手机号
|
||||
type: string
|
||||
nickname:
|
||||
description: 昵称
|
||||
type: string
|
||||
username:
|
||||
description: 用户名
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.listData:
|
||||
properties:
|
||||
created_at:
|
||||
description: 创建时间
|
||||
type: string
|
||||
created_user:
|
||||
description: 创建人
|
||||
type: string
|
||||
hashid:
|
||||
description: hashid
|
||||
type: string
|
||||
id:
|
||||
description: ID
|
||||
type: integer
|
||||
is_used:
|
||||
description: 是否启用 1:是 -1:否
|
||||
type: integer
|
||||
mobile:
|
||||
description: 手机号
|
||||
type: string
|
||||
nickname:
|
||||
description: 昵称
|
||||
type: string
|
||||
updated_at:
|
||||
description: 更新时间
|
||||
type: string
|
||||
updated_user:
|
||||
description: 更新人
|
||||
type: string
|
||||
username:
|
||||
description: 用户名
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.listResponse:
|
||||
properties:
|
||||
list:
|
||||
items:
|
||||
$ref: '#/definitions/admin_handler.listData'
|
||||
type: array
|
||||
pagination:
|
||||
properties:
|
||||
current_page:
|
||||
type: integer
|
||||
pre_page_count:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
admin_handler.loginResponse:
|
||||
properties:
|
||||
token:
|
||||
description: 用户身份标识
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.logoutResponse:
|
||||
properties:
|
||||
username:
|
||||
description: 用户账号
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.modifyPasswordResponse:
|
||||
properties:
|
||||
username:
|
||||
description: 用户账号
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.modifyPersonalInfoResponse:
|
||||
properties:
|
||||
username:
|
||||
description: 用户账号
|
||||
type: string
|
||||
type: object
|
||||
admin_handler.resetPasswordResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
admin_handler.updateUsedResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
authorized_handler.createAPIResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
authorized_handler.createResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
authorized_handler.deleteAPIResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
authorized_handler.deleteResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
authorized_handler.listAPIData:
|
||||
properties:
|
||||
api:
|
||||
description: 调用方对接人
|
||||
type: string
|
||||
business_key:
|
||||
description: 调用方key
|
||||
type: string
|
||||
hash_id:
|
||||
description: hashID
|
||||
type: string
|
||||
method:
|
||||
description: 调用方secret
|
||||
type: string
|
||||
type: object
|
||||
authorized_handler.listAPIResponse:
|
||||
properties:
|
||||
list:
|
||||
items:
|
||||
$ref: '#/definitions/authorized_handler.listAPIData'
|
||||
type: array
|
||||
type: object
|
||||
authorized_handler.listData:
|
||||
properties:
|
||||
business_developer:
|
||||
description: 调用方对接人
|
||||
type: string
|
||||
business_key:
|
||||
description: 调用方key
|
||||
type: string
|
||||
business_secret:
|
||||
description: 调用方secret
|
||||
type: string
|
||||
created_at:
|
||||
description: 创建时间
|
||||
type: string
|
||||
created_user:
|
||||
description: 创建人
|
||||
type: string
|
||||
hashid:
|
||||
description: hashid
|
||||
type: string
|
||||
id:
|
||||
description: ID
|
||||
type: integer
|
||||
is_used:
|
||||
description: 是否启用 1:是 -1:否
|
||||
type: integer
|
||||
remark:
|
||||
description: 备注
|
||||
type: string
|
||||
updated_at:
|
||||
description: 更新时间
|
||||
type: string
|
||||
updated_user:
|
||||
description: 更新人
|
||||
type: string
|
||||
type: object
|
||||
authorized_handler.listResponse:
|
||||
properties:
|
||||
list:
|
||||
items:
|
||||
$ref: '#/definitions/authorized_handler.listData'
|
||||
type: array
|
||||
pagination:
|
||||
properties:
|
||||
current_page:
|
||||
type: integer
|
||||
pre_page_count:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
authorized_handler.updateUsedResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
code.Failure:
|
||||
properties:
|
||||
code:
|
||||
@@ -17,6 +230,18 @@ definitions:
|
||||
description: 过期时间
|
||||
type: integer
|
||||
type: object
|
||||
tool_handler.hashIdsDecodeResponse:
|
||||
properties:
|
||||
val:
|
||||
description: 解密后的值
|
||||
type: integer
|
||||
type: object
|
||||
tool_handler.hashIdsEncodeResponse:
|
||||
properties:
|
||||
val:
|
||||
description: 加密后的值
|
||||
type: string
|
||||
type: object
|
||||
user_handler.createRequest:
|
||||
properties:
|
||||
mobile:
|
||||
@@ -80,6 +305,499 @@ info:
|
||||
title: swagger 接口文档
|
||||
version: "2.0"
|
||||
paths:
|
||||
/api/admin:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 管理员列表
|
||||
parameters:
|
||||
- description: 第几页
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 每页显示条数
|
||||
in: query
|
||||
name: page_size
|
||||
type: string
|
||||
- description: 用户名
|
||||
in: query
|
||||
name: username
|
||||
type: string
|
||||
- description: 昵称
|
||||
in: query
|
||||
name: nickname
|
||||
type: string
|
||||
- description: 手机号
|
||||
in: query
|
||||
name: mobile
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.listResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 管理员列表
|
||||
tags:
|
||||
- API.admin
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 新增管理员
|
||||
parameters:
|
||||
- description: 用户名
|
||||
in: formData
|
||||
name: username
|
||||
required: true
|
||||
type: string
|
||||
- description: 昵称
|
||||
in: formData
|
||||
name: nickname
|
||||
required: true
|
||||
type: string
|
||||
- description: 手机号
|
||||
in: formData
|
||||
name: mobile
|
||||
required: true
|
||||
type: string
|
||||
- description: 密码
|
||||
in: formData
|
||||
name: password
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.createResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 新增管理员
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除管理员
|
||||
parameters:
|
||||
- description: hashId
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.deleteResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 删除管理员
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/info:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 管理员详情
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.detailResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 管理员详情
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/login:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 管理员登出
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.logoutResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 管理员登出
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/modify_password:
|
||||
patch:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 修改个人信息
|
||||
parameters:
|
||||
- description: 昵称
|
||||
in: formData
|
||||
name: nickname
|
||||
required: true
|
||||
type: string
|
||||
- description: 手机号
|
||||
in: formData
|
||||
name: mobile
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.modifyPersonalInfoResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 修改个人信息
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/reset_password/{id}:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 重置密码
|
||||
parameters:
|
||||
- description: hashId
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.resetPasswordResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 重置密码
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/used:
|
||||
patch:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 更新管理员为启用/禁用
|
||||
parameters:
|
||||
- description: Hashid
|
||||
in: formData
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: 是否启用 1:是 -1:否
|
||||
in: formData
|
||||
name: used
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.updateUsedResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 更新管理员为启用/禁用
|
||||
tags:
|
||||
- API.admin
|
||||
/api/authorized:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 调用方列表
|
||||
parameters:
|
||||
- description: 第几页
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 每页显示条数
|
||||
in: query
|
||||
name: page_size
|
||||
type: string
|
||||
- description: 调用方key
|
||||
in: query
|
||||
name: business_key
|
||||
type: string
|
||||
- description: 调用方secret
|
||||
in: query
|
||||
name: business_secret
|
||||
type: string
|
||||
- description: 调用方对接人
|
||||
in: query
|
||||
name: business_developer
|
||||
type: string
|
||||
- description: 备注
|
||||
in: path
|
||||
name: remark
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.listResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 调用方列表
|
||||
tags:
|
||||
- API.authorized
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 新增调用方
|
||||
parameters:
|
||||
- description: 调用方key
|
||||
in: formData
|
||||
name: business_key
|
||||
required: true
|
||||
type: string
|
||||
- description: 调用方对接人
|
||||
in: formData
|
||||
name: business_developer
|
||||
required: true
|
||||
type: string
|
||||
- description: 备注
|
||||
in: formData
|
||||
name: remark
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.createResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 新增调用方
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/authorized/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除调用方
|
||||
parameters:
|
||||
- description: hashId
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.deleteResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 删除调用方
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/authorized/used:
|
||||
patch:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 更新调用方为启用/禁用
|
||||
parameters:
|
||||
- description: Hashid
|
||||
in: formData
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: 是否启用 1:是 -1:否
|
||||
in: formData
|
||||
name: used
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.updateUsedResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 更新调用方为启用/禁用
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/authorized_api:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 调用方接口地址列表
|
||||
parameters:
|
||||
- description: 调用方key
|
||||
in: query
|
||||
name: business_key
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.listAPIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 调用方接口地址列表
|
||||
tags:
|
||||
- API.authorized
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 授权调用方接口地址
|
||||
parameters:
|
||||
- description: HashID
|
||||
in: formData
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: 请求方法
|
||||
in: formData
|
||||
name: method
|
||||
required: true
|
||||
type: string
|
||||
- description: 请求地址
|
||||
in: formData
|
||||
name: api
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.createAPIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 授权调用方接口地址
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/authorized_api/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除调用方接口地址
|
||||
parameters:
|
||||
- description: 主键ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/authorized_handler.deleteAPIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 删除调用方接口地址
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/tool/hashids/decode/{id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: HashIds 解密
|
||||
parameters:
|
||||
- description: 需解密的密文
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/tool_handler.hashIdsDecodeResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: HashIds 解密
|
||||
tags:
|
||||
- API.tool
|
||||
/api/tool/hashids/encode/{id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: HashIds 加密
|
||||
parameters:
|
||||
- description: 需加密的数字
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/tool_handler.hashIdsEncodeResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: HashIds 加密
|
||||
tags:
|
||||
- API.tool
|
||||
/auth/get:
|
||||
post:
|
||||
consumes:
|
||||
|
||||
@@ -16,13 +16,15 @@ require (
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/google/go-cmp v0.5.4 // indirect
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/koketama/errors v1.0.0
|
||||
github.com/koketama/errors v1.0.2
|
||||
github.com/koketama/urltable v0.1.3
|
||||
github.com/onsi/ginkgo v1.14.2 // indirect
|
||||
github.com/onsi/gomega v1.10.4 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v0.9.3
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/shirou/gopsutil v3.21.2+incompatible
|
||||
github.com/speps/go-hashids v2.0.0+incompatible
|
||||
github.com/spf13/cast v1.3.0
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/swaggo/gin-swagger v1.3.0
|
||||
|
||||
@@ -232,8 +232,10 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/koketama/errors v1.0.0 h1:4JO7SGSkBROkTuacd+cgPtBDr7fisixXoajkNh4eW3M=
|
||||
github.com/koketama/errors v1.0.0/go.mod h1:SIU03UGMkhp6tyB5+EvhDI9i9ZDa4rQolJCt9ZrFrbU=
|
||||
github.com/koketama/errors v1.0.2 h1:v8C8MDiz9QHqzQX587dQpD0bjro8n4GPm4leOELYPyo=
|
||||
github.com/koketama/errors v1.0.2/go.mod h1:SIU03UGMkhp6tyB5+EvhDI9i9ZDa4rQolJCt9ZrFrbU=
|
||||
github.com/koketama/urltable v0.1.3 h1:pEuk4/SaqYiTVs70p8GVZeZaLdGCO2Rq8xxKRgMwYwo=
|
||||
github.com/koketama/urltable v0.1.3/go.mod h1:ime2hsHLQKb3AAJTLulUmYMIEb9YsF2RGSixT9z9ChA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -351,6 +353,8 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/speps/go-hashids v2.0.0+incompatible h1:kSfxGfESueJKTx0mpER9Y/1XHl+FVQjtCqRyYcviFbw=
|
||||
github.com/speps/go-hashids v2.0.0+incompatible/go.mod h1:P7hqPzMdnZOfyIk+xrlG1QaSMw+gCBdHKsBDnhpaZvc=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
|
||||
@@ -15,14 +15,36 @@ const (
|
||||
CallHTTPError = 10105
|
||||
ResubmitError = 10106
|
||||
ResubmitMsg = 10107
|
||||
HashIdsDecodeError = 10108
|
||||
SignatureError = 10109
|
||||
|
||||
// 模块级错误码 - 用户模块
|
||||
// 业务模块级错误码
|
||||
// 用户模块
|
||||
IllegalUserName = 20101
|
||||
UserCreateError = 20102
|
||||
UserUpdateError = 20103
|
||||
UserSearchError = 20104
|
||||
|
||||
// ...
|
||||
// 授权调用方
|
||||
AuthorizedCreateError = 20201
|
||||
AuthorizedListError = 20202
|
||||
AuthorizedDeleteError = 20203
|
||||
AuthorizedUpdateError = 20204
|
||||
AuthorizedDetailError = 20205
|
||||
AuthorizedCreateAPIError = 20206
|
||||
AuthorizedListAPIError = 20207
|
||||
AuthorizedDeleteAPIError = 20208
|
||||
|
||||
// 管理员
|
||||
AdminCreateError = 20301
|
||||
AdminListError = 20302
|
||||
AdminDeleteError = 20303
|
||||
AdminUpdateError = 20304
|
||||
AdminResetPasswordError = 20305
|
||||
AdminLoginError = 20307
|
||||
AdminLogOutError = 20308
|
||||
AdminModifyPasswordError = 20309
|
||||
AdminModifyPersonalInfoError = 20310
|
||||
)
|
||||
|
||||
var codeText = map[int]string{
|
||||
@@ -33,11 +55,32 @@ var codeText = map[int]string{
|
||||
CallHTTPError: "调用第三方 HTTP 接口失败",
|
||||
ResubmitError: "Resubmit Error",
|
||||
ResubmitMsg: "请勿重复提交",
|
||||
HashIdsDecodeError: "ID 参数有误",
|
||||
SignatureError: "Signature Error",
|
||||
|
||||
IllegalUserName: "非法用户名",
|
||||
UserCreateError: "创建用户失败",
|
||||
UserUpdateError: "更新用户失败",
|
||||
UserSearchError: "查询用户失败",
|
||||
|
||||
AuthorizedCreateError: "创建调用方失败",
|
||||
AuthorizedListError: "获取调用方列表页失败",
|
||||
AuthorizedDeleteError: "删除调用方失败",
|
||||
AuthorizedUpdateError: "更新调用方失败",
|
||||
AuthorizedDetailError: "获取调用方详情失败",
|
||||
AuthorizedCreateAPIError: "创建调用方API地址失败",
|
||||
AuthorizedListAPIError: "获取调用方API地址列表失败",
|
||||
AuthorizedDeleteAPIError: "删除调用方API地址失败",
|
||||
|
||||
AdminCreateError: "创建管理员失败",
|
||||
AdminListError: "获取管理员列表页失败",
|
||||
AdminDeleteError: "删除管理员失败",
|
||||
AdminUpdateError: "更新管理员失败",
|
||||
AdminResetPasswordError: "重置密码失败",
|
||||
AdminLoginError: "登录失败",
|
||||
AdminLogOutError: "退出失败",
|
||||
AdminModifyPasswordError: "修改密码失败",
|
||||
AdminModifyPersonalInfoError: "修改个人信息失败",
|
||||
}
|
||||
|
||||
func Text(code int) string {
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
Username string `form:"username"` // 用户名
|
||||
Nickname string `form:"nickname"` // 昵称
|
||||
Mobile string `form:"mobile"` // 手机号
|
||||
Password string `form:"password"` // 密码
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Create 新增管理员
|
||||
// @Summary 新增管理员
|
||||
// @Description 新增管理员
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param username formData string true "用户名"
|
||||
// @Param nickname formData string true "昵称"
|
||||
// @Param mobile formData string true "手机号"
|
||||
// @Param password formData string true "密码"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(admin_service.CreateAdminData)
|
||||
createData.Nickname = req.Nickname
|
||||
createData.Username = req.Username
|
||||
createData.Mobile = req.Mobile
|
||||
createData.Password = req.Password
|
||||
|
||||
id, err := h.adminService.Create(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminCreateError,
|
||||
code.Text(code.AdminCreateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
Id string `uri:"id"` // HashID
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Delete 删除管理员
|
||||
// @Summary 删除管理员
|
||||
// @Description 删除管理员
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/{id} [delete]
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.adminService.Delete(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDeleteError,
|
||||
code.Text(code.AdminDeleteError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type detailResponse struct {
|
||||
Username string `json:"username"` // 用户名
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
// Detail 管理员详情
|
||||
// @Summary 管理员详情
|
||||
// @Description 管理员详情
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/info [get]
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
res := new(detailResponse)
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData.Id = cast.ToInt32(c.UserID())
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = info.Username
|
||||
res.Nickname = info.Nickname
|
||||
res.Mobile = info.Mobile
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type listRequest struct {
|
||||
Page int `form:"page"` // 第几页
|
||||
PageSize int `form:"page_size"` // 每页显示条数
|
||||
Username string `form:"username"` // 用户名
|
||||
Nickname string `form:"nickname"` // 昵称
|
||||
Mobile string `form:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
Id int `json:"id"` // ID
|
||||
HashID string `json:"hashid"` // hashid
|
||||
Username string `json:"username"` // 用户名
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
IsUsed int `json:"is_used"` // 是否启用 1:是 -1:否
|
||||
CreatedAt string `json:"created_at"` // 创建时间
|
||||
CreatedUser string `json:"created_user"` // 创建人
|
||||
UpdatedAt string `json:"updated_at"` // 更新时间
|
||||
UpdatedUser string `json:"updated_user"` // 更新人
|
||||
}
|
||||
|
||||
type listResponse struct {
|
||||
List []listData `json:"list"`
|
||||
Pagination struct {
|
||||
Total int `json:"total"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PrePageCount int `json:"pre_page_count"`
|
||||
} `json:"pagination"`
|
||||
}
|
||||
|
||||
// List 管理员列表
|
||||
// @Summary 管理员列表
|
||||
// @Description 管理员列表
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param username query string false "用户名"
|
||||
// @Param nickname query string false "昵称"
|
||||
// @Param mobile query string false "手机号"
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin [get]
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
page := req.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := req.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(admin_service.SearchData)
|
||||
searchData.Page = page
|
||||
searchData.PageSize = pageSize
|
||||
searchData.Username = req.Username
|
||||
searchData.Nickname = req.Nickname
|
||||
searchData.Mobile = req.Mobile
|
||||
|
||||
resListData, err := h.adminService.PageList(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminListError,
|
||||
code.Text(code.AdminListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.adminService.PageListCount(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminListError,
|
||||
code.Text(code.AdminListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
res.Pagination.Total = cast.ToInt(resCountData)
|
||||
res.Pagination.PrePageCount = pageSize
|
||||
res.Pagination.CurrentPage = page
|
||||
res.List = make([]listData, len(resListData))
|
||||
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
h.logger.Info("hashids err", zap.Error(err))
|
||||
}
|
||||
|
||||
data := listData{
|
||||
Id: cast.ToInt(v.Id),
|
||||
HashID: hashId,
|
||||
Username: v.Username,
|
||||
Nickname: v.Nickname,
|
||||
Mobile: v.Mobile,
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
res.List[k] = data
|
||||
}
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type loginRequest struct {
|
||||
Username string `form:"username"` // 用户名
|
||||
Password string `form:"password"` // 密码
|
||||
}
|
||||
|
||||
type loginResponse struct {
|
||||
Token string `json:"token"` // 用户身份标识
|
||||
}
|
||||
|
||||
// Login 管理员登录
|
||||
// @Summary 管理员登录
|
||||
// @Description 管理员登录
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param username formData string true "用户名"
|
||||
// @Param password formData string true "密码"
|
||||
// @Success 200 {object} loginResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/login [post]
|
||||
func (h *handler) Login() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(loginRequest)
|
||||
res := new(loginResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData.Username = req.Username
|
||||
searchOneData.Password = password.GeneratePassword(req.Password)
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if info == nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(errors.New("未查询出符合条件的用户")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
token := password.GenerateLoginToken(info.Id)
|
||||
|
||||
// 用户信息
|
||||
adminJsonInfo, _ := json.Marshal(info)
|
||||
|
||||
// 记录 Redis 中
|
||||
err = h.cache.Set(h.adminService.CacheKeyPrefix()+token, string(adminJsonInfo), time.Hour*24, cache.WithTrace(c.Trace()))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Token = token
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type logoutResponse struct {
|
||||
Username string `json:"username"` // 用户账号
|
||||
}
|
||||
|
||||
// Logout 管理员登出
|
||||
// @Summary 管理员登出
|
||||
// @Description 管理员登出
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} logoutResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/login [post]
|
||||
func (h *handler) Logout() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
res := new(logoutResponse)
|
||||
res.Username = c.UserName()
|
||||
|
||||
if !h.cache.Del(h.adminService.CacheKeyPrefix()+password.GenerateLoginToken(cast.ToInt32(c.UserID())), cache.WithTrace(c.Trace())) {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLogOutError,
|
||||
code.Text(code.AdminLogOutError)).WithErr(errors.New("cache del err")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type modifyPasswordRequest struct {
|
||||
OldPassword string `form:"old_password"` // 旧密码
|
||||
NewPassword string `form:"new_password"` // 新密码
|
||||
}
|
||||
|
||||
type modifyPasswordResponse struct {
|
||||
Username string `json:"username"` // 用户账号
|
||||
}
|
||||
|
||||
// ModifyPassword 修改密码
|
||||
// @Summary 修改密码
|
||||
// @Description 修改密码
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param old_password formData string true "旧密码"
|
||||
// @Param new_password formData string true "新密码"
|
||||
// @Success 200 {object} modifyPasswordResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/modify_password [patch]
|
||||
func (h *handler) ModifyPassword() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(modifyPasswordRequest)
|
||||
res := new(modifyPasswordResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
userId := cast.ToInt32(c.UserID())
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData.Id = userId
|
||||
searchOneData.Password = password.GeneratePassword(req.OldPassword)
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil || info == nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPasswordError,
|
||||
code.Text(code.AdminModifyPasswordError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.adminService.ModifyPassword(c, userId, req.NewPassword); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPasswordError,
|
||||
code.Text(code.AdminModifyPasswordError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = c.UserName()
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type modifyPersonalInfoRequest struct {
|
||||
Nickname string `form:"nickname"` // 昵称
|
||||
Mobile string `form:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
type modifyPersonalInfoResponse struct {
|
||||
Username string `json:"username"` // 用户账号
|
||||
}
|
||||
|
||||
// ModifyPersonalInfo 修改个人信息
|
||||
// @Summary 修改个人信息
|
||||
// @Description 修改个人信息
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param nickname formData string true "昵称"
|
||||
// @Param mobile formData string true "手机号"
|
||||
// @Success 200 {object} modifyPersonalInfoResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/modify_password [patch]
|
||||
func (h *handler) ModifyPersonalInfo() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(modifyPersonalInfoRequest)
|
||||
res := new(modifyPersonalInfoResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
userId := cast.ToInt32(c.UserID())
|
||||
|
||||
modifyData := new(admin_service.ModifyData)
|
||||
modifyData.Nickname = req.Nickname
|
||||
modifyData.Mobile = req.Mobile
|
||||
|
||||
if err := h.adminService.ModifyPersonalInfo(c, userId, modifyData); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPersonalInfoError,
|
||||
code.Text(code.AdminModifyPersonalInfoError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = c.UserName()
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type resetPasswordRequest struct {
|
||||
Id string `uri:"id"` // HashID
|
||||
}
|
||||
|
||||
type resetPasswordResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// ResetPassword 重置密码
|
||||
// @Summary 重置密码
|
||||
// @Description 重置密码
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} resetPasswordResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/reset_password/{id} [patch]
|
||||
func (h *handler) ResetPassword() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(resetPasswordRequest)
|
||||
res := new(resetPasswordResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.adminService.ResetPassword(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminResetPasswordError,
|
||||
code.Text(code.AdminResetPasswordError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
Id string `form:"id"` // 主键ID
|
||||
Used int32 `form:"used"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type updateUsedResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// UpdateUsed 更新管理员为启用/禁用
|
||||
// @Summary 更新管理员为启用/禁用
|
||||
// @Description 更新管理员为启用/禁用
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/used [patch]
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.adminService.UpdateUsed(c, id, req.Used)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminUpdateError,
|
||||
code.Text(code.AdminUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// Login 管理员登录
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/login [post]
|
||||
Login() core.HandlerFunc
|
||||
|
||||
// Logout 管理员登出
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/logout [post]
|
||||
Logout() core.HandlerFunc
|
||||
|
||||
// ModifyPassword 修改密码
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/modify_password [patch]
|
||||
ModifyPassword() core.HandlerFunc
|
||||
|
||||
// Detail 个人信息
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/info [get]
|
||||
Detail() core.HandlerFunc
|
||||
|
||||
// ModifyPersonalInfo 修改个人信息
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/modify_personal_info [patch]
|
||||
ModifyPersonalInfo() core.HandlerFunc
|
||||
|
||||
// Create 新增管理员
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// List 管理员列表
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin [get]
|
||||
List() core.HandlerFunc
|
||||
|
||||
// Delete 删除管理员
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/{id} [delete]
|
||||
Delete() core.HandlerFunc
|
||||
|
||||
// UpdateUsed 更新管理员为启用/禁用
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/used [patch]
|
||||
UpdateUsed() core.HandlerFunc
|
||||
|
||||
// ResetPassword 重置密码
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/reset_password/{id} [patch]
|
||||
ResetPassword() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
hashids hash.Hash
|
||||
adminService admin_service.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
adminService: admin_service.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -0,0 +1,65 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
BusinessKey string `form:"business_key"` // 调用方key
|
||||
BusinessDeveloper string `form:"business_developer"` // 调用方对接人
|
||||
Remark string `form:"remark"` // 备注
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Create 新增调用方
|
||||
// @Summary 新增调用方
|
||||
// @Description 新增调用方
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param business_key formData string true "调用方key"
|
||||
// @Param business_developer formData string true "调用方对接人"
|
||||
// @Param remark formData string true "备注"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(authorized_service.CreateAuthorizedData)
|
||||
createData.BusinessKey = req.BusinessKey
|
||||
createData.BusinessDeveloper = req.BusinessDeveloper
|
||||
createData.Remark = req.Remark
|
||||
|
||||
id, err := h.authorizedService.Create(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedCreateError,
|
||||
code.Text(code.AuthorizedCreateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type createAPIRequest struct {
|
||||
Id string `form:"id"` // HashID
|
||||
Method string `form:"method"` // 请求方法
|
||||
API string `form:"api"` // 请求地址
|
||||
}
|
||||
|
||||
type createAPIResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// CreateAPI 授权调用方接口地址
|
||||
// @Summary 授权调用方接口地址
|
||||
// @Description 授权调用方接口地址
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param id formData string true "HashID"
|
||||
// @Param method formData string true "请求方法"
|
||||
// @Param api formData string true "请求地址"
|
||||
// @Success 200 {object} createAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api [post]
|
||||
func (h *handler) CreateAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createAPIRequest)
|
||||
res := new(createAPIResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
// 通过 id 查询出 business_key
|
||||
authorizedInfo, err := h.authorizedService.Detail(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDetailError,
|
||||
code.Text(code.AuthorizedDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createAPIData := new(authorized_service.CreateAuthorizedAPIData)
|
||||
createAPIData.BusinessKey = authorizedInfo.BusinessKey
|
||||
createAPIData.Method = req.Method
|
||||
createAPIData.API = req.API
|
||||
|
||||
createId, err := h.authorizedService.CreateAPI(c, createAPIData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedCreateAPIError,
|
||||
code.Text(code.AuthorizedCreateAPIError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = createId
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
Id string `uri:"id"` // HashID
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Delete 删除调用方
|
||||
// @Summary 删除调用方
|
||||
// @Description 删除调用方
|
||||
// @Tags API.authorized
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized/{id} [delete]
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.authorizedService.Delete(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDeleteError,
|
||||
code.Text(code.AuthorizedDeleteError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteAPIRequest struct {
|
||||
Id string `uri:"id"` // HashID
|
||||
}
|
||||
|
||||
type deleteAPIResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// DeleteAPI 删除调用方接口地址
|
||||
// @Summary 删除调用方接口地址
|
||||
// @Description 删除调用方接口地址
|
||||
// @Tags API.authorized
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "主键ID"
|
||||
// @Success 200 {object} deleteAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api/{id} [delete]
|
||||
func (h *handler) DeleteAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteAPIRequest)
|
||||
res := new(deleteAPIResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.authorizedService.DeleteAPI(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDeleteAPIError,
|
||||
code.Text(code.AuthorizedDeleteAPIError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type listRequest struct {
|
||||
Page int `form:"page"` // 第几页
|
||||
PageSize int `form:"page_size"` // 每页显示条数
|
||||
BusinessKey string `form:"business_key"` // 调用方key
|
||||
BusinessSecret string `form:"business_secret"` // 调用方secret
|
||||
BusinessDeveloper string `form:"business_developer"` // 调用方对接人
|
||||
Remark string `form:"remark"` // 备注
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
Id int `json:"id"` // ID
|
||||
HashID string `json:"hashid"` // hashid
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
BusinessSecret string `json:"business_secret"` // 调用方secret
|
||||
BusinessDeveloper string `json:"business_developer"` // 调用方对接人
|
||||
Remark string `json:"remark"` // 备注
|
||||
IsUsed int `json:"is_used"` // 是否启用 1:是 -1:否
|
||||
CreatedAt string `json:"created_at"` // 创建时间
|
||||
CreatedUser string `json:"created_user"` // 创建人
|
||||
UpdatedAt string `json:"updated_at"` // 更新时间
|
||||
UpdatedUser string `json:"updated_user"` // 更新人
|
||||
}
|
||||
|
||||
type listResponse struct {
|
||||
List []listData `json:"list"`
|
||||
Pagination struct {
|
||||
Total int `json:"total"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PrePageCount int `json:"pre_page_count"`
|
||||
} `json:"pagination"`
|
||||
}
|
||||
|
||||
// List 调用方列表
|
||||
// @Summary 调用方列表
|
||||
// @Description 调用方列表
|
||||
// @Tags API.authorized
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param business_key query string false "调用方key"
|
||||
// @Param business_secret query string false "调用方secret"
|
||||
// @Param business_developer query string false "调用方对接人"
|
||||
// @Param remark path string false "备注"
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized [get]
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
page := req.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := req.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(authorized_service.SearchData)
|
||||
searchData.Page = page
|
||||
searchData.PageSize = pageSize
|
||||
searchData.BusinessKey = req.BusinessKey
|
||||
searchData.BusinessSecret = req.BusinessSecret
|
||||
searchData.Remark = req.Remark
|
||||
|
||||
resListData, err := h.authorizedService.PageList(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListError,
|
||||
code.Text(code.AuthorizedListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.authorizedService.PageListCount(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListError,
|
||||
code.Text(code.AuthorizedListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
res.Pagination.Total = cast.ToInt(resCountData)
|
||||
res.Pagination.PrePageCount = pageSize
|
||||
res.Pagination.CurrentPage = page
|
||||
res.List = make([]listData, len(resListData))
|
||||
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
h.logger.Info("hashids err", zap.Error(err))
|
||||
}
|
||||
|
||||
data := listData{
|
||||
Id: cast.ToInt(v.Id),
|
||||
HashID: hashId,
|
||||
BusinessKey: v.BusinessKey,
|
||||
BusinessSecret: v.BusinessSecret,
|
||||
BusinessDeveloper: v.BusinessDeveloper,
|
||||
Remark: v.Remark,
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
res.List[k] = data
|
||||
}
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type listAPIRequest struct {
|
||||
Id string `form:"id"` // hashID
|
||||
}
|
||||
|
||||
type listAPIData struct {
|
||||
HashId string `json:"hash_id"` // hashID
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
Method string `json:"method"` // 调用方secret
|
||||
API string `json:"api"` // 调用方对接人
|
||||
}
|
||||
|
||||
type listAPIResponse struct {
|
||||
List []listAPIData `json:"list"`
|
||||
}
|
||||
|
||||
// ListAPI 调用方接口地址列表
|
||||
// @Summary 调用方接口地址列表
|
||||
// @Description 调用方接口地址列表
|
||||
// @Tags API.authorized
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param business_key query string false "调用方key"
|
||||
// @Success 200 {object} listAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api [get]
|
||||
func (h *handler) ListAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listAPIRequest)
|
||||
res := new(listAPIResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
// 通过 id 查询出 business_key
|
||||
authorizedInfo, err := h.authorizedService.Detail(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDetailError,
|
||||
code.Text(code.AuthorizedDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchAPIData := new(authorized_service.SearchAPIData)
|
||||
searchAPIData.BusinessKey = authorizedInfo.BusinessKey
|
||||
|
||||
resListData, err := h.authorizedService.ListAPI(c, searchAPIData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListAPIError,
|
||||
code.Text(code.AuthorizedListAPIError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.List = make([]listAPIData, len(resListData))
|
||||
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
h.logger.Info("hashids err", zap.Error(err))
|
||||
}
|
||||
|
||||
data := listAPIData{
|
||||
HashId: hashId,
|
||||
BusinessKey: v.BusinessKey,
|
||||
Method: v.Method,
|
||||
API: v.Api,
|
||||
}
|
||||
|
||||
res.List[k] = data
|
||||
}
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
Id string `form:"id"` // 主键ID
|
||||
Used int32 `form:"used"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type updateUsedResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// UpdateUsed 更新调用方为启用/禁用
|
||||
// @Summary 更新调用方为启用/禁用
|
||||
// @Description 更新调用方为启用/禁用
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized/used [patch]
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.authorizedService.UpdateUsed(c, id, req.Used)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedUpdateError,
|
||||
code.Text(code.AuthorizedUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package authorized_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// Create 新增调用方
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// CreateAPI 授权调用方接口地址
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized_api [post]
|
||||
CreateAPI() core.HandlerFunc
|
||||
|
||||
// List 调用方列表
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized [get]
|
||||
List() core.HandlerFunc
|
||||
|
||||
// ListAPI 调用方接口地址列表
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized_api [get]
|
||||
ListAPI() core.HandlerFunc
|
||||
|
||||
// Delete 删除调用方
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized/{id} [delete]
|
||||
Delete() core.HandlerFunc
|
||||
|
||||
// DeleteAPI 删除调用方接口地址
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized_api/{id} [delete]
|
||||
DeleteAPI() core.HandlerFunc
|
||||
|
||||
// UpdateUsed 更新调用方为启用/禁用
|
||||
// @Tags API.authorized
|
||||
// @Router /api/authorized/used [patch]
|
||||
UpdateUsed() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
authorizedService authorized_service.Service
|
||||
hashids hash.Hash
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
authorizedService: authorized_service.New(db, cache),
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -0,0 +1,56 @@
|
||||
package tool_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type hashIdsDecodeRequest struct {
|
||||
Id string `uri:"id"` // 需解密的密文
|
||||
}
|
||||
|
||||
type hashIdsDecodeResponse struct {
|
||||
Val int `json:"val"` // 解密后的值
|
||||
}
|
||||
|
||||
// HashIdsDecode HashIds 解密
|
||||
// @Summary HashIds 解密
|
||||
// @Description HashIds 解密
|
||||
// @Tags API.tool
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "需解密的密文"
|
||||
// @Success 200 {object} hashIdsDecodeResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/tool/hashids/decode/{id} [get]
|
||||
func (h *handler) HashIdsDecode() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(hashIdsDecodeRequest)
|
||||
res := new(hashIdsDecodeResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
hashId, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Val = hashId[0]
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package tool_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type hashIdsEncodeRequest struct {
|
||||
Id int32 `uri:"id"` // 需加密的数字
|
||||
}
|
||||
|
||||
type hashIdsEncodeResponse struct {
|
||||
Val string `json:"val"` // 加密后的值
|
||||
}
|
||||
|
||||
// HashIdsEncode HashIds 加密
|
||||
// @Summary HashIds 加密
|
||||
// @Description HashIds 加密
|
||||
// @Tags API.tool
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "需加密的数字"
|
||||
// @Success 200 {object} hashIdsEncodeResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/tool/hashids/encode/{id} [get]
|
||||
func (h *handler) HashIdsEncode() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(hashIdsEncodeRequest)
|
||||
res := new(hashIdsEncodeResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(req.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Val = hashId
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package tool_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// HashIdsEncode HashIds 加密
|
||||
// @Tags API.tool
|
||||
// @Router /api/tool/hashids/encode/{id} [get]
|
||||
HashIdsEncode() core.HandlerFunc
|
||||
|
||||
// HashIdsDecode HashIds 解密
|
||||
// @Tags API.tool
|
||||
// @Router /api/tool/hashids/decode/{id} [get]
|
||||
HashIdsDecode() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
hashids hash.Hash
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
+583
@@ -0,0 +1,583 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package admin_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *Admin {
|
||||
return new(Admin)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *adminRepoQueryBuilder {
|
||||
return new(adminRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *Admin) Create(db *gorm.DB) (id int32, err error) {
|
||||
if err = db.Create(t).Error; err != nil {
|
||||
return 0, errors.Wrap(err, "create err")
|
||||
}
|
||||
return t.Id, nil
|
||||
}
|
||||
|
||||
func (t *Admin) Delete(db *gorm.DB) (err error) {
|
||||
if err = db.Delete(t).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Admin) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
if err = db.Model(&Admin{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type adminRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
|
||||
ret := db
|
||||
for _, where := range qb.where {
|
||||
ret = ret.Where(where.prefix, where.value)
|
||||
}
|
||||
for _, order := range qb.order {
|
||||
ret = ret.Order(order)
|
||||
}
|
||||
ret = ret.Limit(qb.limit).Offset(qb.offset)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&Admin{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) First(db *gorm.DB) (*Admin, error) {
|
||||
ret := &Admin{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) QueryOne(db *gorm.DB) (*Admin, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*Admin, error) {
|
||||
var ret []*Admin
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) Limit(limit int) *adminRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) Offset(offset int) *adminRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIdIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIdNotIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderById(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUsername(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "username", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUsernameIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "username", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUsernameNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "username", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByUsername(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "username "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WherePassword(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "password", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WherePasswordIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "password", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WherePasswordNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "password", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByPassword(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "password "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereNickname(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nickname", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereNicknameIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nickname", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereNicknameNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nickname", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByNickname(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "nickname "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereMobile(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereMobileIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereMobileNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByMobile(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "mobile "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsUsed(p db_repo.Predicate, value int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsUsedIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsUsedNotIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByIsUsed(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_used "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsDeletedIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByIsDeleted(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_deleted "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByCreatedAt(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedUserIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByCreatedUser(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_user "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByUpdatedAt(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedUser(p db_repo.Predicate, value string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedUserIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) WhereUpdatedUserNotIn(value []string) *adminRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *adminRepoQueryBuilder) OrderByUpdatedUser(asc bool) *adminRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_user "+order)
|
||||
return qb
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package admin_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// 管理员表
|
||||
//go:generate gormgen -structs Admin -input .
|
||||
type Admin struct {
|
||||
Id int32 // 主键
|
||||
Username string // 用户名
|
||||
Password string // 密码
|
||||
Nickname string // 昵称
|
||||
Mobile string // 手机号
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
IsDeleted int32 // 是否删除 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
CreatedUser string // 创建人
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
UpdatedUser string // 更新人
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#### go_gin_api.admin
|
||||
管理员表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | username | 用户名 | varchar(32) | UNI | NO | | |
|
||||
| 3 | password | 密码 | varchar(32) | | NO | | |
|
||||
| 4 | nickname | 昵称 | varchar(60) | | NO | | |
|
||||
| 5 | mobile | 手机号 | varchar(20) | | NO | | |
|
||||
| 6 | is_used | 是否启用 1:是 -1:否 | tinyint(1) | | NO | | 1 |
|
||||
| 7 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 8 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
|
||||
| 9 | created_user | 创建人 | varchar(60) | | NO | | |
|
||||
| 10 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
| 11 | updated_user | 更新人 | varchar(60) | | NO | | |
|
||||
@@ -0,0 +1,497 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package authorized_api_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *AuthorizedApi {
|
||||
return new(AuthorizedApi)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *authorizedApiRepoQueryBuilder {
|
||||
return new(authorizedApiRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *AuthorizedApi) Create(db *gorm.DB) (id int32, err error) {
|
||||
if err = db.Create(t).Error; err != nil {
|
||||
return 0, errors.Wrap(err, "create err")
|
||||
}
|
||||
return t.Id, nil
|
||||
}
|
||||
|
||||
func (t *AuthorizedApi) Delete(db *gorm.DB) (err error) {
|
||||
if err = db.Delete(t).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *AuthorizedApi) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
if err = db.Model(&AuthorizedApi{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type authorizedApiRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
|
||||
ret := db
|
||||
for _, where := range qb.where {
|
||||
ret = ret.Where(where.prefix, where.value)
|
||||
}
|
||||
for _, order := range qb.order {
|
||||
ret = ret.Order(order)
|
||||
}
|
||||
ret = ret.Limit(qb.limit).Offset(qb.offset)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&AuthorizedApi{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) First(db *gorm.DB) (*AuthorizedApi, error) {
|
||||
ret := &AuthorizedApi{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) QueryOne(db *gorm.DB) (*AuthorizedApi, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*AuthorizedApi, error) {
|
||||
var ret []*AuthorizedApi
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) Limit(limit int) *authorizedApiRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) Offset(offset int) *authorizedApiRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereIdIn(value []int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereIdNotIn(value []int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderById(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereBusinessKey(p db_repo.Predicate, value string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereBusinessKeyIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereBusinessKeyNotIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByBusinessKey(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "business_key "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereMethod(p db_repo.Predicate, value string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "method", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereMethodIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "method", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereMethodNotIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "method", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByMethod(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "method "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereApi(p db_repo.Predicate, value string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "api", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereApiIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "api", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereApiNotIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "api", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByApi(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "api "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereIsDeletedIn(value []int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByIsDeleted(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_deleted "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByCreatedAt(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedUserIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByCreatedUser(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_user "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByUpdatedAt(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedUser(p db_repo.Predicate, value string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedUserIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) WhereUpdatedUserNotIn(value []string) *authorizedApiRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedApiRepoQueryBuilder) OrderByUpdatedUser(asc bool) *authorizedApiRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_user "+order)
|
||||
return qb
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package authorized_api_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// 已授权的调用方表
|
||||
//go:generate gormgen -structs AuthorizedApi -input .
|
||||
type AuthorizedApi struct {
|
||||
Id int32 // 主键
|
||||
BusinessKey string // 调用方key
|
||||
Method string // 请求方式
|
||||
Api string // 请求地址
|
||||
IsDeleted int32 // 是否删除 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
CreatedUser string // 创建人
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
UpdatedUser string // 更新人
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#### go_gin_api.authorized_api
|
||||
已授权的调用方表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | business_key | 调用方key | varchar(30) | | NO | | |
|
||||
| 3 | method | 请求方式 | varchar(30) | | NO | | |
|
||||
| 4 | api | 请求地址 | varchar(100) | | NO | | |
|
||||
| 5 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 6 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
|
||||
| 7 | created_user | 创建人 | varchar(60) | | NO | | |
|
||||
| 8 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
| 9 | updated_user | 更新人 | varchar(60) | | NO | | |
|
||||
@@ -0,0 +1,583 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package authorized_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *Authorized {
|
||||
return new(Authorized)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *authorizedRepoQueryBuilder {
|
||||
return new(authorizedRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *Authorized) Create(db *gorm.DB) (id int32, err error) {
|
||||
if err = db.Create(t).Error; err != nil {
|
||||
return 0, errors.Wrap(err, "create err")
|
||||
}
|
||||
return t.Id, nil
|
||||
}
|
||||
|
||||
func (t *Authorized) Delete(db *gorm.DB) (err error) {
|
||||
if err = db.Delete(t).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Authorized) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
if err = db.Model(&Authorized{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type authorizedRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
|
||||
ret := db
|
||||
for _, where := range qb.where {
|
||||
ret = ret.Where(where.prefix, where.value)
|
||||
}
|
||||
for _, order := range qb.order {
|
||||
ret = ret.Order(order)
|
||||
}
|
||||
ret = ret.Limit(qb.limit).Offset(qb.offset)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&Authorized{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) First(db *gorm.DB) (*Authorized, error) {
|
||||
ret := &Authorized{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) QueryOne(db *gorm.DB) (*Authorized, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*Authorized, error) {
|
||||
var ret []*Authorized
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) Limit(limit int) *authorizedRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) Offset(offset int) *authorizedRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIdIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIdNotIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderById(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessKey(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessKeyIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessKeyNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_key", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByBusinessKey(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "business_key "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessSecret(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_secret", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessSecretIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_secret", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessSecretNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_secret", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByBusinessSecret(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "business_secret "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessDeveloper(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_developer", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessDeveloperIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_developer", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereBusinessDeveloperNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "business_developer", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByBusinessDeveloper(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "business_developer "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereRemark(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereRemarkIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereRemarkNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByRemark(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "remark "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsUsed(p db_repo.Predicate, value int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsUsedIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsUsedNotIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByIsUsed(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_used "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsDeletedIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByIsDeleted(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_deleted "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByCreatedAt(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedUserIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByCreatedUser(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_user "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByUpdatedAt(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedUser(p db_repo.Predicate, value string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedUserIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) WhereUpdatedUserNotIn(value []string) *authorizedRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *authorizedRepoQueryBuilder) OrderByUpdatedUser(asc bool) *authorizedRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_user "+order)
|
||||
return qb
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package authorized_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// 已授权的调用方表
|
||||
//go:generate gormgen -structs Authorized -input .
|
||||
type Authorized struct {
|
||||
Id int32 // 主键
|
||||
BusinessKey string // 调用方key
|
||||
BusinessSecret string // 调用方secret
|
||||
BusinessDeveloper string // 调用方对接人
|
||||
Remark string // 备注
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
IsDeleted int32 // 是否删除 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
CreatedUser string // 创建人
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
UpdatedUser string // 更新人
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#### go_gin_api.authorized
|
||||
已授权的调用方表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | business_key | 调用方key | varchar(32) | | NO | | |
|
||||
| 3 | business_secret | 调用方secret | varchar(60) | | NO | | |
|
||||
| 4 | business_developer | 调用方对接人 | varchar(60) | | NO | | |
|
||||
| 5 | remark | 备注 | varchar(255) | | NO | | |
|
||||
| 6 | is_used | 是否启用 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 7 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 8 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
|
||||
| 9 | created_user | 创建人 | varchar(60) | | NO | | |
|
||||
| 10 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
| 11 | updated_user | 更新人 | varchar(60) | | NO | | |
|
||||
@@ -0,0 +1,48 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
)
|
||||
|
||||
var _ Service = (*service)(nil)
|
||||
|
||||
// 定义缓存前缀
|
||||
var cacheKeyPrefix = configs.ProjectName() + ":admin:"
|
||||
|
||||
type Service interface {
|
||||
i()
|
||||
CacheKeyPrefix() (pre string)
|
||||
|
||||
Create(ctx core.Context, authorizedData *CreateAdminData) (id int32, err error)
|
||||
PageList(ctx core.Context, searchData *SearchData) (listData []*admin_repo.Admin, err error)
|
||||
PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error)
|
||||
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
|
||||
Delete(ctx core.Context, id int32) (err error)
|
||||
Detail(ctx core.Context, searchOneData *SearchOneData) (info *admin_repo.Admin, err error)
|
||||
ResetPassword(ctx core.Context, id int32) (err error)
|
||||
ModifyPassword(ctx core.Context, id int32, newPassword string) (err error)
|
||||
ModifyPersonalInfo(ctx core.Context, id int32, modifyData *ModifyData) (err error)
|
||||
}
|
||||
|
||||
type service struct {
|
||||
db db.Repo
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func New(db db.Repo, cache cache.Repo) Service {
|
||||
return &service{
|
||||
db: db,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) i() {}
|
||||
|
||||
func (s *service) CacheKeyPrefix() (pre string) {
|
||||
pre = cacheKeyPrefix
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
)
|
||||
|
||||
type CreateAdminData struct {
|
||||
Username string // 用户名
|
||||
Nickname string // 昵称
|
||||
Mobile string // 手机号
|
||||
Password string // 密码
|
||||
}
|
||||
|
||||
func (s *service) Create(ctx core.Context, adminData *CreateAdminData) (id int32, err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Username = adminData.Username
|
||||
model.Password = password.GeneratePassword(adminData.Password)
|
||||
model.Nickname = adminData.Nickname
|
||||
model.Mobile = adminData.Mobile
|
||||
model.CreatedUser = ctx.UserName()
|
||||
model.IsUsed = 1
|
||||
model.IsDeleted = -1
|
||||
|
||||
id, err = model.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
)
|
||||
|
||||
func (s *service) Delete(ctx core.Context, id int32) (err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"is_deleted": 1,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+password.GenerateLoginToken(id), cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchOneData struct {
|
||||
Id int32 // 用户ID
|
||||
Username string // 用户名
|
||||
Nickname string // 昵称
|
||||
Mobile string // 手机号
|
||||
Password string // 密码
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
func (s *service) Detail(ctx core.Context, searchOneData *SearchOneData) (info *admin_repo.Admin, err error) {
|
||||
|
||||
qb := admin_repo.NewQueryBuilder()
|
||||
qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchOneData.Id != 0 {
|
||||
qb.WhereId(db_repo.EqualPredicate, searchOneData.Id)
|
||||
}
|
||||
|
||||
if searchOneData.Username != "" {
|
||||
qb.WhereUsername(db_repo.EqualPredicate, searchOneData.Username)
|
||||
}
|
||||
|
||||
if searchOneData.Nickname != "" {
|
||||
qb.WhereNickname(db_repo.EqualPredicate, searchOneData.Nickname)
|
||||
}
|
||||
|
||||
if searchOneData.Mobile != "" {
|
||||
qb.WhereMobile(db_repo.EqualPredicate, searchOneData.Mobile)
|
||||
}
|
||||
|
||||
if searchOneData.Password != "" {
|
||||
qb.WherePassword(db_repo.EqualPredicate, searchOneData.Password)
|
||||
}
|
||||
|
||||
if searchOneData.IsUsed != 0 {
|
||||
qb.WhereIsUsed(db_repo.EqualPredicate, searchOneData.IsUsed)
|
||||
}
|
||||
|
||||
info, err = qb.QueryOne(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
)
|
||||
|
||||
func (s *service) ModifyPassword(ctx core.Context, id int32, newPassword string) (err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"password": password.GeneratePassword(newPassword),
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+password.GenerateLoginToken(id), cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type ModifyData struct {
|
||||
Nickname string // 昵称
|
||||
Mobile string // 手机号
|
||||
}
|
||||
|
||||
func (s *service) ModifyPersonalInfo(ctx core.Context, id int32, modifyData *ModifyData) (err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"nickname": modifyData.Nickname,
|
||||
"mobile": modifyData.Mobile,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchData struct {
|
||||
Page int // 第几页
|
||||
PageSize int // 每页显示条数
|
||||
Username string // 用户名
|
||||
Nickname string // 昵称
|
||||
Mobile string // 手机号
|
||||
}
|
||||
|
||||
func (s *service) PageList(ctx core.Context, searchData *SearchData) (listData []*admin_repo.Admin, err error) {
|
||||
|
||||
page := searchData.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := searchData.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
qb := admin_repo.NewQueryBuilder()
|
||||
qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchData.Username != "" {
|
||||
qb.WhereUsername(db_repo.EqualPredicate, searchData.Username)
|
||||
}
|
||||
|
||||
if searchData.Nickname != "" {
|
||||
qb.WhereNickname(db_repo.EqualPredicate, searchData.Nickname)
|
||||
}
|
||||
|
||||
if searchData.Mobile != "" {
|
||||
qb.WhereMobile(db_repo.EqualPredicate, searchData.Mobile)
|
||||
}
|
||||
|
||||
listData, err = qb.
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error) {
|
||||
qb := admin_repo.NewQueryBuilder()
|
||||
qb = qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchData.Username != "" {
|
||||
qb.WhereUsername(db_repo.EqualPredicate, searchData.Username)
|
||||
}
|
||||
|
||||
if searchData.Nickname != "" {
|
||||
qb.WhereNickname(db_repo.EqualPredicate, searchData.Nickname)
|
||||
}
|
||||
|
||||
if searchData.Mobile != "" {
|
||||
qb.WhereMobile(db_repo.EqualPredicate, searchData.Mobile)
|
||||
}
|
||||
|
||||
total, err = qb.Count(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
)
|
||||
|
||||
func (s *service) ResetPassword(ctx core.Context, id int32) (err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"password": password.ResetPassword(),
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+password.GenerateLoginToken(id), cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package admin_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
)
|
||||
|
||||
func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error) {
|
||||
model := admin_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"is_used": used,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+password.GenerateLoginToken(id), cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_api_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
)
|
||||
|
||||
var _ Service = (*service)(nil)
|
||||
|
||||
// 定义缓存前缀
|
||||
var cacheKeyPrefix = configs.ProjectName() + ":authorized:"
|
||||
|
||||
type Service interface {
|
||||
i()
|
||||
|
||||
Create(ctx core.Context, authorizedData *CreateAuthorizedData) (id int32, err error)
|
||||
List(ctx core.Context, searchData *SearchData) (listData []*authorized_repo.Authorized, err error)
|
||||
PageList(ctx core.Context, searchData *SearchData) (listData []*authorized_repo.Authorized, err error)
|
||||
PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error)
|
||||
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
|
||||
Delete(ctx core.Context, id int32) (err error)
|
||||
Detail(ctx core.Context, id int32) (info *authorized_repo.Authorized, err error)
|
||||
DetailByKey(ctx core.Context, key string) (data *CacheAuthorizedData, err error)
|
||||
|
||||
CreateAPI(ctx core.Context, authorizedAPIData *CreateAuthorizedAPIData) (id int32, err error)
|
||||
ListAPI(ctx core.Context, searchAPIData *SearchAPIData) (listData []*authorized_api_repo.AuthorizedApi, err error)
|
||||
DeleteAPI(ctx core.Context, id int32) (err error)
|
||||
}
|
||||
|
||||
type service struct {
|
||||
db db.Repo
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func New(db db.Repo, cache cache.Repo) Service {
|
||||
return &service{
|
||||
db: db,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) i() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type CreateAuthorizedData struct {
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
BusinessDeveloper string `json:"business_developer"` // 调用方对接人
|
||||
Remark string `json:"remark"` // 备注
|
||||
}
|
||||
|
||||
func (s *service) Create(ctx core.Context, authorizedData *CreateAuthorizedData) (id int32, err error) {
|
||||
buf := make([]byte, 10)
|
||||
io.ReadFull(rand.Reader, buf)
|
||||
secret := string(hex.EncodeToString(buf))
|
||||
|
||||
model := authorized_repo.NewModel()
|
||||
model.BusinessKey = authorizedData.BusinessKey
|
||||
model.BusinessSecret = secret
|
||||
model.BusinessDeveloper = authorizedData.BusinessDeveloper
|
||||
model.Remark = authorizedData.Remark
|
||||
model.CreatedUser = ctx.UserName()
|
||||
model.IsUsed = 1
|
||||
model.IsDeleted = -1
|
||||
|
||||
id, err = model.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_api_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type CreateAuthorizedAPIData struct {
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
Method string `json:"method"` // 请求方法
|
||||
API string `json:"api"` // 请求地址
|
||||
}
|
||||
|
||||
func (s *service) CreateAPI(ctx core.Context, authorizedAPIData *CreateAuthorizedAPIData) (id int32, err error) {
|
||||
model := authorized_api_repo.NewModel()
|
||||
model.BusinessKey = authorizedAPIData.BusinessKey
|
||||
model.Method = authorizedAPIData.Method
|
||||
model.Api = authorizedAPIData.API
|
||||
model.CreatedUser = ctx.UserName()
|
||||
model.IsDeleted = -1
|
||||
|
||||
id, err = model.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+authorizedAPIData.BusinessKey, cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (s *service) Delete(ctx core.Context, id int32) (err error) {
|
||||
// 先查询 id 是否存在
|
||||
authorizedInfo, err := authorized_repo.NewQueryBuilder().
|
||||
WhereIsDeleted(db_repo.EqualPredicate, -1).
|
||||
WhereId(db_repo.EqualPredicate, id).
|
||||
First(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
model := authorized_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"is_deleted": 1,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+authorizedInfo.BusinessKey, cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_api_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (s *service) DeleteAPI(ctx core.Context, id int32) (err error) {
|
||||
// 先查询 id 是否存在
|
||||
authorizedApiInfo, err := authorized_api_repo.NewQueryBuilder().
|
||||
WhereIsDeleted(db_repo.EqualPredicate, -1).
|
||||
WhereId(db_repo.EqualPredicate, id).
|
||||
First(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
model := authorized_api_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"is_deleted": 1,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+authorizedApiInfo.BusinessKey, cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) Detail(ctx core.Context, id int32) (info *authorized_repo.Authorized, err error) {
|
||||
qb := authorized_repo.NewQueryBuilder()
|
||||
qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
qb.WhereId(db_repo.EqualPredicate, id)
|
||||
|
||||
info, err = qb.First(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_api_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
// 定义缓存结构
|
||||
type CacheAuthorizedData struct {
|
||||
Key string `json:"key"` // 调用方 key
|
||||
Secret string `json:"secret"` // 调用方 secret
|
||||
IsUsed int32 `json:"is_used"` // 调用方启用状态 1=启用 -1=禁用
|
||||
Apis []cacheApiData `json:"apis"` // 调用方授权的 Apis
|
||||
}
|
||||
|
||||
type cacheApiData struct {
|
||||
Method string `json:"method"` // 请求方式
|
||||
Api string `json:"api"` // 请求地址
|
||||
}
|
||||
|
||||
func (s *service) DetailByKey(ctx core.Context, key string) (cacheData *CacheAuthorizedData, err error) {
|
||||
// 查询缓存
|
||||
cacheKey := cacheKeyPrefix + key
|
||||
value, err := s.cache.Get(cacheKey, cache.WithTrace(ctx.RequestContext().Trace))
|
||||
|
||||
cacheData = new(CacheAuthorizedData)
|
||||
if err == nil && json.Unmarshal([]byte(value), cacheData) == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 查询调用方信息
|
||||
authorizedInfo, err := authorized_repo.NewQueryBuilder().
|
||||
WhereIsDeleted(db_repo.EqualPredicate, -1).
|
||||
WhereBusinessKey(db_repo.EqualPredicate, key).
|
||||
First(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询调用方授权 API 信息
|
||||
authorizedApiInfo, err := authorized_api_repo.NewQueryBuilder().
|
||||
WhereIsDeleted(db_repo.EqualPredicate, -1).
|
||||
WhereBusinessKey(db_repo.EqualPredicate, key).
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置缓存 data
|
||||
cacheData = new(CacheAuthorizedData)
|
||||
cacheData.Key = key
|
||||
cacheData.Secret = authorizedInfo.BusinessSecret
|
||||
cacheData.IsUsed = authorizedInfo.IsUsed
|
||||
cacheData.Apis = make([]cacheApiData, len(authorizedApiInfo))
|
||||
|
||||
for k, v := range authorizedApiInfo {
|
||||
data := cacheApiData{
|
||||
Method: v.Method,
|
||||
Api: v.Api,
|
||||
}
|
||||
cacheData.Apis[k] = data
|
||||
}
|
||||
|
||||
cacheDataByte, _ := json.Marshal(cacheData)
|
||||
|
||||
err = s.cache.Set(cacheKey, string(cacheDataByte), 0, cache.WithTrace(ctx.Trace()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) List(ctx core.Context, searchData *SearchData) (listData []*authorized_repo.Authorized, err error) {
|
||||
|
||||
qb := authorized_repo.NewQueryBuilder()
|
||||
qb = qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchData.BusinessKey != "" {
|
||||
qb.WhereBusinessKey(db_repo.EqualPredicate, searchData.BusinessKey)
|
||||
}
|
||||
|
||||
if searchData.BusinessSecret != "" {
|
||||
qb.WhereBusinessSecret(db_repo.EqualPredicate, searchData.BusinessSecret)
|
||||
}
|
||||
|
||||
if searchData.BusinessDeveloper != "" {
|
||||
qb.WhereBusinessDeveloper(db_repo.EqualPredicate, searchData.BusinessDeveloper)
|
||||
}
|
||||
|
||||
listData, err = qb.
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_api_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchAPIData struct {
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
}
|
||||
|
||||
func (s *service) ListAPI(ctx core.Context, searchAPIData *SearchAPIData) (listData []*authorized_api_repo.AuthorizedApi, err error) {
|
||||
|
||||
qb := authorized_api_repo.NewQueryBuilder()
|
||||
qb = qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchAPIData.BusinessKey != "" {
|
||||
qb.WhereBusinessKey(db_repo.EqualPredicate, searchAPIData.BusinessKey)
|
||||
}
|
||||
|
||||
listData, err = qb.
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchData struct {
|
||||
Page int `json:"page"` // 第几页
|
||||
PageSize int `json:"page_size"` // 每页显示条数
|
||||
BusinessKey string `json:"business_key"` // 调用方key
|
||||
BusinessSecret string `json:"business_secret"` // 调用方secret
|
||||
BusinessDeveloper string `json:"business_developer"` // 调用方对接人
|
||||
Remark string `json:"remark"` // 备注
|
||||
}
|
||||
|
||||
func (s *service) PageList(ctx core.Context, searchData *SearchData) (listData []*authorized_repo.Authorized, err error) {
|
||||
|
||||
page := searchData.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := searchData.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
qb := authorized_repo.NewQueryBuilder()
|
||||
qb = qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchData.BusinessKey != "" {
|
||||
qb.WhereBusinessKey(db_repo.EqualPredicate, searchData.BusinessKey)
|
||||
}
|
||||
|
||||
if searchData.BusinessSecret != "" {
|
||||
qb.WhereBusinessSecret(db_repo.EqualPredicate, searchData.BusinessSecret)
|
||||
}
|
||||
|
||||
if searchData.BusinessDeveloper != "" {
|
||||
qb.WhereBusinessDeveloper(db_repo.EqualPredicate, searchData.BusinessDeveloper)
|
||||
}
|
||||
|
||||
listData, err = qb.
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error) {
|
||||
qb := authorized_repo.NewQueryBuilder()
|
||||
qb = qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
|
||||
|
||||
if searchData.BusinessKey != "" {
|
||||
qb.WhereBusinessKey(db_repo.EqualPredicate, searchData.BusinessKey)
|
||||
}
|
||||
|
||||
if searchData.BusinessSecret != "" {
|
||||
qb.WhereBusinessSecret(db_repo.EqualPredicate, searchData.BusinessSecret)
|
||||
}
|
||||
|
||||
if searchData.BusinessDeveloper != "" {
|
||||
qb.WhereBusinessDeveloper(db_repo.EqualPredicate, searchData.BusinessDeveloper)
|
||||
}
|
||||
|
||||
total, err = qb.Count(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package authorized_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/authorized_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error) {
|
||||
authorizedInfo, err := authorized_repo.NewQueryBuilder().
|
||||
WhereIsDeleted(db_repo.EqualPredicate, -1).
|
||||
WhereId(db_repo.EqualPredicate, id).
|
||||
First(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
model := authorized_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"is_used": used,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cache.Del(cacheKeyPrefix+authorizedInfo.BusinessKey, cache.WithTrace(ctx.Trace()))
|
||||
return
|
||||
}
|
||||
Vendored
+20
-5
@@ -33,7 +33,7 @@ type Repo interface {
|
||||
TTL(key string) (time.Duration, error)
|
||||
Expire(key string, ttl time.Duration) bool
|
||||
ExpireAt(key string, ttl time.Time) bool
|
||||
Del(keys ...string) bool
|
||||
Del(key string, options ...Option) bool
|
||||
Exists(keys ...string) bool
|
||||
Incr(key string, options ...Option) int64
|
||||
Close() error
|
||||
@@ -158,13 +158,28 @@ func (c *cacheRepo) Exists(keys ...string) bool {
|
||||
return value > 0
|
||||
}
|
||||
|
||||
// Del del some key from redis
|
||||
func (c *cacheRepo) Del(keys ...string) bool {
|
||||
if len(keys) == 0 {
|
||||
func (c *cacheRepo) Del(key string, options ...Option) bool {
|
||||
ts := time.Now()
|
||||
opt := newOption()
|
||||
defer func() {
|
||||
if opt.Trace != nil {
|
||||
opt.Redis.Timestamp = time_parse.CSTLayoutString()
|
||||
opt.Redis.Handle = "del"
|
||||
opt.Redis.Key = key
|
||||
opt.Redis.CostSeconds = time.Since(ts).Seconds()
|
||||
opt.Trace.AppendRedis(opt.Redis)
|
||||
}
|
||||
}()
|
||||
|
||||
for _, f := range options {
|
||||
f(opt)
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
value, _ := c.client.Del(keys...).Result()
|
||||
value, _ := c.client.Del(key).Result()
|
||||
return value > 0
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
_ "github.com/xinliangnote/go-gin-api/docs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/browser"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/color"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
@@ -48,6 +49,7 @@ type option struct {
|
||||
recordMetrics RecordMetrics
|
||||
enableCors bool
|
||||
enableRate bool
|
||||
enableOpenBrowser string
|
||||
}
|
||||
|
||||
// OnPanicNotify 发生panic时通知用
|
||||
@@ -93,6 +95,13 @@ func WithRecordMetrics(record RecordMetrics) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnableOpenBrowser 启动后在浏览器中打开 uri
|
||||
func WithEnableOpenBrowser(uri string) Option {
|
||||
return func(opt *option) {
|
||||
opt.enableOpenBrowser = uri
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnableCors 开启CORS
|
||||
func WithEnableCors() Option {
|
||||
return func(opt *option) {
|
||||
@@ -311,6 +320,11 @@ func New(logger *zap.Logger, options ...Option) (Mux, error) {
|
||||
}))
|
||||
}
|
||||
|
||||
if opt.enableOpenBrowser != "" {
|
||||
_ = browser.Open(opt.enableOpenBrowser)
|
||||
fmt.Println(color.Green("* [register open browser '" + opt.enableOpenBrowser + "']"))
|
||||
}
|
||||
|
||||
// recover两次,防止处理时发生panic,尤其是在OnPanicNotify中。
|
||||
mux.engine.Use(func(ctx *gin.Context) {
|
||||
defer func() {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package password
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const salt = "qkhPAGA13HocW3GAEWwb"
|
||||
|
||||
const defaultPassword = "123456"
|
||||
|
||||
func GeneratePassword(str string) (password string) {
|
||||
// md5
|
||||
m := md5.New()
|
||||
m.Write([]byte(str))
|
||||
mByte := m.Sum(nil)
|
||||
|
||||
// hmac
|
||||
h := hmac.New(sha256.New, []byte(salt))
|
||||
h.Write(mByte)
|
||||
password = hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func ResetPassword() (password string) {
|
||||
m := md5.New()
|
||||
m.Write([]byte(defaultPassword))
|
||||
mStr := hex.EncodeToString(m.Sum(nil))
|
||||
|
||||
password = GeneratePassword(mStr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GenerateLoginToken(id int32) (token string) {
|
||||
m := md5.New()
|
||||
m.Write([]byte(fmt.Sprintf("%d%s", id, salt)))
|
||||
token = hex.EncodeToString(m.Sum(nil))
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/signature"
|
||||
|
||||
"github.com/koketama/urltable"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const ttl = time.Minute * 2 // 签名超时时间 2 分钟
|
||||
|
||||
var whiteListPath = map[string]bool{
|
||||
"/login/web": true,
|
||||
}
|
||||
|
||||
func (m *middleware) Signature() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
// 签名信息
|
||||
authorization := c.GetHeader("Authorization")
|
||||
if authorization == "" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New("Header 中缺少 Authorization 参数")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 时间信息
|
||||
date := c.GetHeader("Authorization-Date")
|
||||
if date == "" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New("Header 中缺少 Date 参数")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 通过签名信息获取 key
|
||||
authorizationSplit := strings.Split(authorization, " ")
|
||||
if len(authorizationSplit) < 2 {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New("Header 中 Authorization 格式错误")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
key := authorizationSplit[0]
|
||||
|
||||
data, err := m.authorizedService.DetailByKey(c, key)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 cache 是否被调用
|
||||
if data.IsUsed == -1 {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New(key + " 已被禁止调用")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if len(data.Apis) < 1 {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New(key + " 未进行接口授权")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if !whiteListPath[c.Path()] {
|
||||
// 验证 c.Method() + c.Path() 是否授权
|
||||
table := urltable.NewTable()
|
||||
for _, v := range data.Apis {
|
||||
_ = table.Append(v.Method + v.Api)
|
||||
}
|
||||
|
||||
if pattern, _ := table.Mapping(c.Method() + c.Path()); pattern == "" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New(c.Method() + c.Path() + " 未进行接口授权")),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ok, err := signature.New(key, data.Secret, ttl).Verify(authorization, date, c.Path(), c.Method(), c.RequestInputParams())
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if !ok {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.SignatureError,
|
||||
code.Text(code.SignatureError)).WithErr(errors.New("Header 中 Authorization 信息错误")),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (m *middleware) Token(ctx core.Context) (userId int64, userName string, err errno.Error) {
|
||||
token := ctx.GetHeader("Token")
|
||||
if token == "" {
|
||||
err = errno.NewError(
|
||||
http.StatusUnauthorized,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithErr(errors.New("Header 中缺少 Token 参数"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !m.cache.Exists(m.adminService.CacheKeyPrefix() + token) {
|
||||
err = errno.NewError(
|
||||
http.StatusUnauthorized,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithErr(errors.New("请先登录"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cacheData, cacheErr := m.cache.Get(m.adminService.CacheKeyPrefix()+token, cache.WithTrace(ctx.Trace()))
|
||||
if cacheErr != nil {
|
||||
err = errno.NewError(
|
||||
http.StatusUnauthorized,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithErr(cacheErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type userInfo struct {
|
||||
Id int64 `json:"id"` // 用户ID
|
||||
Username string `json:"username"` // 用户名
|
||||
}
|
||||
|
||||
var userData userInfo
|
||||
_ = json.Unmarshal([]byte(cacheData), &userData)
|
||||
|
||||
userId = userData.Id
|
||||
userName = userData.Username
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -22,17 +25,29 @@ type Middleware interface {
|
||||
|
||||
// DisableLog 不记录日志
|
||||
DisableLog() core.HandlerFunc
|
||||
|
||||
// Signature 签名验证,对用签名算法 pkg/signature
|
||||
Signature() core.HandlerFunc
|
||||
|
||||
// Token 签名验证,对登录用户的验证
|
||||
Token(ctx core.Context) (userId int64, userName string, err errno.Error)
|
||||
}
|
||||
|
||||
type middleware struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
db db.Repo
|
||||
authorizedService authorized_service.Service
|
||||
adminService admin_service.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, cache cache.Repo) Middleware {
|
||||
func New(logger *zap.Logger, cache cache.Repo, db db.Repo) Middleware {
|
||||
return &middleware{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
db: db,
|
||||
authorizedService: authorized_service.New(db, cache),
|
||||
adminService: admin_service.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/metrics"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/notify"
|
||||
"github.com/xinliangnote/go-gin-api/internal/router/middleware"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/file"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
@@ -23,12 +25,19 @@ type resource struct {
|
||||
}
|
||||
|
||||
func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) (core.Mux, error) {
|
||||
var openBrowserUri = "http://127.0.0.1:9999"
|
||||
|
||||
_, ok := file.IsExists(configs.InitDBLockFile())
|
||||
if !ok {
|
||||
openBrowserUri = "http://127.0.0.1:9999/init?init=db"
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger required")
|
||||
}
|
||||
|
||||
mux, err := core.New(logger,
|
||||
core.WithEnableOpenBrowser(openBrowserUri),
|
||||
core.WithEnableCors(),
|
||||
core.WithEnableRate(),
|
||||
core.WithPanicNotify(notify.OnPanicNotify),
|
||||
@@ -45,7 +54,7 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.C
|
||||
r.db = db
|
||||
r.cache = cache
|
||||
r.grpConn = grpConn
|
||||
r.middles = middleware.New(logger, cache)
|
||||
r.middles = middleware.New(logger, cache, db)
|
||||
|
||||
// 设置 WEB 路由
|
||||
setWebRouter(r)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/demo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/tool_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
@@ -33,4 +36,44 @@ func setApiRouter(r *resource) {
|
||||
user.PATCH("/delete/:id", userHandler.Delete())
|
||||
user.GET("/info/:username", core.AliasForRecordMetrics("/user/info"), userHandler.Detail())
|
||||
}
|
||||
|
||||
// authorized
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// admin
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// 登录
|
||||
login := r.mux.Group("/login", r.middles.Signature())
|
||||
{
|
||||
login.POST("/web", adminHandler.Login())
|
||||
}
|
||||
|
||||
// api
|
||||
api := r.mux.Group("/api", core.WrapAuthHandler(r.middles.Token), r.middles.Signature())
|
||||
{
|
||||
api.POST("/authorized", authorizedHandler.Create())
|
||||
api.GET("/authorized", authorizedHandler.List())
|
||||
api.PATCH("/authorized/used", authorizedHandler.UpdateUsed())
|
||||
api.DELETE("/authorized/:id", authorizedHandler.Delete())
|
||||
|
||||
api.POST("/authorized_api", authorizedHandler.CreateAPI())
|
||||
api.GET("/authorized_api", authorizedHandler.ListAPI())
|
||||
api.DELETE("/authorized_api/:id", authorizedHandler.DeleteAPI())
|
||||
|
||||
api.POST("/admin", adminHandler.Create())
|
||||
api.GET("/admin", adminHandler.List())
|
||||
api.PATCH("/admin/used", adminHandler.UpdateUsed())
|
||||
api.PATCH("/admin/reset_password/:id", adminHandler.ResetPassword())
|
||||
api.DELETE("/admin/:id", adminHandler.Delete())
|
||||
api.POST("/admin/logout", adminHandler.Logout())
|
||||
api.PATCH("/admin/modify_password", adminHandler.ModifyPassword())
|
||||
api.GET("/admin/info", adminHandler.Detail())
|
||||
api.PATCH("/admin/modify_personal_info", adminHandler.ModifyPersonalInfo())
|
||||
|
||||
// tool
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
api.GET("/tool/hashids/encode/:id", toolHandler.HashIdsEncode())
|
||||
api.GET("/tool/hashids/decode/:id", toolHandler.HashIdsDecode())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/configinfo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/gencode_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/index_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/tool_handler"
|
||||
)
|
||||
|
||||
func setWebRouter(r *resource) {
|
||||
@@ -13,6 +16,9 @@ func setWebRouter(r *resource) {
|
||||
dashboardHandler := dashboard_handler.New(r.logger, r.db, r.cache)
|
||||
genCodeHandler := gencode_handler.New(r.logger, r.db, r.cache)
|
||||
configInfoHandler := configinfo_handler.New(r.logger, r.db, r.cache)
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
web := r.mux.Group("", r.middles.DisableLog())
|
||||
{
|
||||
@@ -35,5 +41,22 @@ func setWebRouter(r *resource) {
|
||||
web.GET("/handlergen", genCodeHandler.HandlerView())
|
||||
web.POST("/handlergen_exec", genCodeHandler.HandlerExecute())
|
||||
|
||||
// 调用方
|
||||
web.GET("/authorized/list", authorizedHandler.ListView())
|
||||
web.GET("/authorized/add", authorizedHandler.AddView())
|
||||
web.GET("/authorized/api/:id", authorizedHandler.ApiView())
|
||||
web.GET("/authorized/demo", authorizedHandler.DemoView())
|
||||
|
||||
// 管理员
|
||||
web.GET("/admin/list", adminHandler.ListView())
|
||||
web.GET("/admin/add", adminHandler.AddView())
|
||||
web.GET("/admin/modify_password", adminHandler.ModifyPasswordView())
|
||||
web.GET("/admin/modify_info", adminHandler.ModifyInfoView())
|
||||
web.GET("/login", adminHandler.LoginView())
|
||||
|
||||
// 工具箱
|
||||
web.GET("/tool/hashids", toolHandler.HashIdsView())
|
||||
web.GET("/tool/logs", toolHandler.LogsView())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package admin_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) AddView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("admin_add", nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package admin_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) ListView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("admin_list", nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package admin_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) LoginView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("admin_login", nil)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user