fix: 修复配额说明重复和undefined问题
- 在editStorageForm中初始化oss_storage_quota_value和oss_quota_unit - 删除重复的旧配额说明块,保留新的当前配额设置显示 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
46
backend/node_modules/svg-captcha/lib/ch-to-path.js
generated
vendored
Normal file
46
backend/node_modules/svg-captcha/lib/ch-to-path.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
|
||||
function rndPathCmd(cmd) {
|
||||
const r = (Math.random() * 0.2) - 0.1;
|
||||
|
||||
switch (cmd.type) {
|
||||
case 'M': case 'L':
|
||||
cmd.x += r;
|
||||
cmd.y += r;
|
||||
break;
|
||||
case 'Q': case 'C':
|
||||
cmd.x += r;
|
||||
cmd.y += r;
|
||||
cmd.x1 += r;
|
||||
cmd.y1 += r;
|
||||
break;
|
||||
default:
|
||||
// Close path cmd
|
||||
break;
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
module.exports = function (text, opts) {
|
||||
const ch = text[0];
|
||||
assert(ch, 'expect a string');
|
||||
|
||||
const fontSize = opts.fontSize;
|
||||
const fontScale = fontSize / opts.font.unitsPerEm;
|
||||
|
||||
const glyph = opts.font.charToGlyph(ch);
|
||||
const width = glyph.advanceWidth ? glyph.advanceWidth * fontScale : 0;
|
||||
const left = opts.x - (width / 2);
|
||||
|
||||
const height = (opts.ascender + opts.descender) * fontScale;
|
||||
const top = opts.y + (height / 2);
|
||||
const path = glyph.getPath(left, top, fontSize);
|
||||
// Randomize path commands
|
||||
path.commands.forEach(rndPathCmd);
|
||||
|
||||
const pathData = path.toPathData();
|
||||
|
||||
return pathData;
|
||||
};
|
||||
3
backend/node_modules/svg-captcha/lib/char-preset.js
generated
vendored
Normal file
3
backend/node_modules/svg-captcha/lib/char-preset.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
91
backend/node_modules/svg-captcha/lib/index.js
generated
vendored
Normal file
91
backend/node_modules/svg-captcha/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
const chToPath = require('./ch-to-path');
|
||||
const random = require('./random');
|
||||
const optionMngr = require('./option-manager');
|
||||
|
||||
const opts = optionMngr.options;
|
||||
|
||||
const getLineNoise = function (width, height, options) {
|
||||
const hasColor = options.color;
|
||||
const noiseLines = [];
|
||||
const min = options.inverse ? 7 : 1;
|
||||
const max = options.inverse ? 15 : 9;
|
||||
let i = -1;
|
||||
|
||||
while (++i < options.noise) {
|
||||
const start = `${random.int(1, 21)} ${random.int(1, height - 1)}`;
|
||||
const end = `${random.int(width - 21, width - 1)} ${random.int(1, height - 1)}`;
|
||||
const mid1 = `${random.int((width / 2) - 21, (width / 2) + 21)} ${random.int(1, height - 1)}`;
|
||||
const mid2 = `${random.int((width / 2) - 21, (width / 2) + 21)} ${random.int(1, height - 1)}`;
|
||||
const color = hasColor ? random.color() : random.greyColor(min, max);
|
||||
noiseLines.push(`<path d="M${start} C${mid1},${mid2},${end}" stroke="${color}" fill="none"/>`);
|
||||
}
|
||||
|
||||
return noiseLines;
|
||||
};
|
||||
|
||||
const getText = function (text, width, height, options) {
|
||||
const len = text.length;
|
||||
const spacing = (width - 2) / (len + 1);
|
||||
const min = options.inverse ? 10 : 0;
|
||||
const max = options.inverse ? 14 : 4;
|
||||
let i = -1;
|
||||
const out = [];
|
||||
|
||||
while (++i < len) {
|
||||
const x = spacing * (i + 1);
|
||||
const y = height / 2;
|
||||
const charPath = chToPath(text[i], Object.assign({x, y}, options));
|
||||
|
||||
const color = options.color ?
|
||||
random.color(options.background) : random.greyColor(min, max);
|
||||
out.push(`<path fill="${color}" d="${charPath}"/>`);
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
const createCaptcha = function (text, options) {
|
||||
text = text || random.captchaText();
|
||||
options = Object.assign({}, opts, options);
|
||||
const width = options.width;
|
||||
const height = options.height;
|
||||
const bg = options.background;
|
||||
if (bg) {
|
||||
options.color = true;
|
||||
}
|
||||
|
||||
const bgRect = bg ?
|
||||
`<rect width="100%" height="100%" fill="${bg}"/>` : '';
|
||||
const paths =
|
||||
[].concat(getLineNoise(width, height, options))
|
||||
.concat(getText(text, width, height, options))
|
||||
.sort(() => Math.random() - 0.5)
|
||||
.join('');
|
||||
const start = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0,0,${width},${height}">`;
|
||||
const xml = `${start}${bgRect}${paths}</svg>`;
|
||||
|
||||
return xml;
|
||||
};
|
||||
|
||||
const create = function (options) {
|
||||
const text = random.captchaText(options);
|
||||
const data = createCaptcha(text, options);
|
||||
|
||||
return {text, data};
|
||||
};
|
||||
|
||||
const createMathExpr = function (options) {
|
||||
const expr = random.mathExpr(options.mathMin, options.mathMax, options.mathOperator);
|
||||
const text = expr.text;
|
||||
const data = createCaptcha(expr.equation, options);
|
||||
|
||||
return {text, data};
|
||||
};
|
||||
|
||||
module.exports = createCaptcha;
|
||||
module.exports.randomText = random.captchaText;
|
||||
module.exports.create = create;
|
||||
module.exports.createMathExpr = createMathExpr;
|
||||
module.exports.options = opts;
|
||||
module.exports.loadFont = optionMngr.loadFont;
|
||||
32
backend/node_modules/svg-captcha/lib/option-manager.js
generated
vendored
Normal file
32
backend/node_modules/svg-captcha/lib/option-manager.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
const path = require('path');
|
||||
const opentype = require('opentype.js');
|
||||
const charPreset = require('./char-preset');
|
||||
|
||||
const fontPath = path.join(__dirname, '../fonts/Comismsh.ttf');
|
||||
const font = opentype.loadSync(fontPath);
|
||||
const ascender = font.ascender;
|
||||
const descender = font.descender;
|
||||
|
||||
const options = {
|
||||
width: 150,
|
||||
height: 50,
|
||||
noise: 1,
|
||||
color: false,
|
||||
background: '',
|
||||
size: 4,
|
||||
ignoreChars: '',
|
||||
fontSize: 56,
|
||||
charPreset, font, ascender, descender
|
||||
};
|
||||
|
||||
const loadFont = filepath => {
|
||||
const font = opentype.loadSync(filepath);
|
||||
options.font = font;
|
||||
options.ascender = font.ascender;
|
||||
options.descender = font.descender;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
options, loadFont
|
||||
};
|
||||
148
backend/node_modules/svg-captcha/lib/random.js
generated
vendored
Normal file
148
backend/node_modules/svg-captcha/lib/random.js
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
const opts = require('./option-manager').options;
|
||||
|
||||
const randomInt = function (min, max) {
|
||||
return Math.round(min + (Math.random() * (max - min)));
|
||||
};
|
||||
|
||||
const stripCharsFromString = function (string, chars) {
|
||||
return string.split('').filter(char => chars.indexOf(char) === -1);
|
||||
};
|
||||
|
||||
exports.int = randomInt;
|
||||
|
||||
exports.greyColor = function (min, max) {
|
||||
min = min || 1;
|
||||
max = max || 9;
|
||||
const int = randomInt(min, max).toString(16);
|
||||
|
||||
return `#${int}${int}${int}`;
|
||||
};
|
||||
|
||||
exports.captchaText = function (options) {
|
||||
if (typeof options === 'number') {
|
||||
options = {size: options};
|
||||
}
|
||||
options = options || {};
|
||||
|
||||
const size = options.size || 4;
|
||||
const ignoreChars = options.ignoreChars || '';
|
||||
let i = -1;
|
||||
let out = '';
|
||||
let chars = options.charPreset || opts.charPreset;
|
||||
|
||||
if (ignoreChars) {
|
||||
chars = stripCharsFromString(chars, ignoreChars);
|
||||
}
|
||||
|
||||
const len = chars.length - 1;
|
||||
|
||||
while (++i < size) {
|
||||
out += chars[randomInt(0, len)];
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
const mathExprPlus = function(leftNumber, rightNumber){
|
||||
const text = (leftNumber + rightNumber).toString();
|
||||
const equation = leftNumber + '+' + rightNumber;
|
||||
return {text, equation}
|
||||
}
|
||||
|
||||
const mathExprMinus = function(leftNumber, rightNumber){
|
||||
const text = (leftNumber - rightNumber).toString();
|
||||
const equation = leftNumber + '-' + rightNumber;
|
||||
return {text, equation}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simple math expression using either the + or - operator
|
||||
* @param {number} [min] - The min value of the math expression defaults to 1
|
||||
* @param {number} [max] - The max value of the math expression defaults to 9
|
||||
* @param {string} [operator] - The operator(s) to use
|
||||
* @returns {{equation: string, text: string}}
|
||||
*/
|
||||
exports.mathExpr = function (min, max, operator) {
|
||||
min = min || 1;
|
||||
max = max || 9;
|
||||
operator = operator || '+';
|
||||
const left = randomInt(min, max);
|
||||
const right = randomInt(min, max);
|
||||
switch(operator){
|
||||
case '+':
|
||||
return mathExprPlus(left, right)
|
||||
case '-':
|
||||
return mathExprMinus(left, right)
|
||||
default:
|
||||
return (randomInt(1, 2) % 2) ? mathExprPlus(left, right) : mathExprMinus(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
// https://github.com/jquery/jquery-color/blob/master/jquery.color.js#L432
|
||||
// The idea here is generate color in hsl first and convert that to rgb color
|
||||
exports.color = function (bgColor) {
|
||||
// Random 24 colors
|
||||
// or based on step
|
||||
const hue = randomInt(0, 24) / 24;
|
||||
|
||||
const saturation = randomInt(60, 80) / 100;
|
||||
const bgLightness = bgColor ? getLightness(bgColor) : 1.0;
|
||||
let minLightness;
|
||||
let maxLightness;
|
||||
if (bgLightness >= 0.5) {
|
||||
minLightness = Math.round(bgLightness * 100) - 45;
|
||||
maxLightness = Math.round(bgLightness * 100) - 25;
|
||||
} else {
|
||||
minLightness = Math.round(bgLightness * 100) + 25;
|
||||
maxLightness = Math.round(bgLightness * 100) + 45;
|
||||
}
|
||||
const lightness = randomInt(minLightness, maxLightness) / 100;
|
||||
|
||||
const q = lightness < 0.5 ?
|
||||
lightness * (lightness + saturation) :
|
||||
lightness + saturation - (lightness * saturation);
|
||||
const p = (2 * lightness) - q;
|
||||
|
||||
const r = Math.floor(hue2rgb(p, q, hue + (1 / 3)) * 255);
|
||||
const g = Math.floor(hue2rgb(p, q, hue) * 255);
|
||||
const b = Math.floor(hue2rgb(p, q, hue - (1 / 3)) * 255);
|
||||
/* eslint-disable no-mixed-operators */
|
||||
const c = ((b | g << 8 | r << 16) | 1 << 24).toString(16).slice(1);
|
||||
|
||||
return '#' + c;
|
||||
};
|
||||
|
||||
function getLightness(rgbColor) {
|
||||
if (rgbColor[0] !== '#') {
|
||||
return 1.0; // Invalid color ?
|
||||
}
|
||||
rgbColor = rgbColor.slice(1);
|
||||
if (rgbColor.length === 3) {
|
||||
rgbColor = rgbColor[0] + rgbColor[0] +
|
||||
rgbColor[1] + rgbColor[1] + rgbColor[2] + rgbColor[2];
|
||||
}
|
||||
|
||||
const hexColor = parseInt(rgbColor, 16);
|
||||
const r = hexColor >> 16;
|
||||
const g = hexColor >> 8 & 255;
|
||||
const b = hexColor & 255;
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
|
||||
return (max + min) / (2 * 255);
|
||||
}
|
||||
|
||||
function hue2rgb(p, q, h) {
|
||||
h = (h + 1) % 1;
|
||||
if (h * 6 < 1) {
|
||||
return p + (q - p) * h * 6;
|
||||
}
|
||||
if (h * 2 < 1) {
|
||||
return q;
|
||||
}
|
||||
if (h * 3 < 2) {
|
||||
return p + (q - p) * ((2 / 3) - h) * 6;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Reference in New Issue
Block a user