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:
2026-01-22 19:39:53 +08:00
commit 4350113979
7649 changed files with 897277 additions and 0 deletions

46
backend/node_modules/svg-captcha/lib/ch-to-path.js generated vendored Normal file
View 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
View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

91
backend/node_modules/svg-captcha/lib/index.js generated vendored Normal file
View 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
View 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
View 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;
}