mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 11:07:06 +00:00
[improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component. (#404)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab. [improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions. [improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager. * [improvement][semantic-fe] Add time granularity setting in the data source configuration. * [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility * [improvement][semantic-fe] Modification of data source creation prompt wording" * [improvement][semantic-fe] metric market experience optimization * [improvement][semantic-fe] enhance the analysis of metric trends * [improvement][semantic-fe] optimize the presentation of metric trend permissions * [improvement][semantic-fe] add metric trend download functionality * [improvement][semantic-fe] fix the dimension initialization issue in metric correlation * [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source. * [improvement][semantic-fe] Optimizing pagination logic and some CSS styles * [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum" * [improvement][semantic-fe] Fixing the default value setting for the indicator list * [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models * [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API * [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators * [improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality * [improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component.
This commit is contained in:
@@ -61,6 +61,9 @@ export default defineConfig({
|
||||
theme: {
|
||||
...themeSettings,
|
||||
},
|
||||
alias: {
|
||||
'antd/es/style': '@/assets/style',
|
||||
},
|
||||
esbuild: {},
|
||||
title: false,
|
||||
ignoreMomentLocale: true,
|
||||
|
||||
@@ -4,8 +4,8 @@ const Settings: LayoutSettings & {
|
||||
pwa?: boolean;
|
||||
logo?: string;
|
||||
} = {
|
||||
navTheme: 'dark',
|
||||
primaryColor: '#296DF3',
|
||||
navTheme: 'light',
|
||||
colorPrimary: '#296DF3',
|
||||
layout: 'top',
|
||||
contentWidth: 'Fluid',
|
||||
fixedHeader: false,
|
||||
|
||||
@@ -52,15 +52,11 @@
|
||||
"not ie <= 10"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ant-design/charts": "^1.3.3",
|
||||
"@ant-design/cssinjs": "^1.10.1",
|
||||
"@ant-design/icons": "^4.7.0",
|
||||
"@ant-design/pro-card": "^1.11.13",
|
||||
"@ant-design/pro-components": "^2.4.4",
|
||||
"@ant-design/pro-descriptions": "^1.0.19",
|
||||
"@ant-design/pro-form": "^1.23.0",
|
||||
"@ant-design/pro-layout": "^6.38.22",
|
||||
"@ant-design/pro-table": "^2.80.6",
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"@ant-design/pro-card": "^2.5.26",
|
||||
"@ant-design/pro-components": "^2.6.41",
|
||||
"@ant-design/pro-layout": "^7.17.15",
|
||||
"@ant-design/pro-table": "^3.13.9",
|
||||
"@antv/dom-util": "^2.0.4",
|
||||
"@antv/g6": "^4.8.14",
|
||||
"@antv/g6-core": "^0.8.23",
|
||||
@@ -73,7 +69,7 @@
|
||||
"@umijs/route-utils": "^1.0.33",
|
||||
"ace-builds": "^1.4.12",
|
||||
"ahooks": "^3.7.7",
|
||||
"antd": "^4.24.8",
|
||||
"antd": "^5.11.0",
|
||||
"classnames": "^2.2.6",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"cross-env": "^7.0.3",
|
||||
|
||||
@@ -133,7 +133,7 @@ export const layout: RunTimeLayoutConfig = (params) => {
|
||||
>
|
||||
{dom}
|
||||
{history.location.pathname !== '/chat' && !isMobile && (
|
||||
<Copilot token={getToken() || ''} isDeveloper />
|
||||
<Copilot token={getAuthToken() || ''} isDeveloper />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~antd/lib/style/themes/default';
|
||||
|
||||
|
||||
// main
|
||||
@primary: #225ace;
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* stylelint-disable */
|
||||
.bezierEasingMixin() {
|
||||
@functions: ~`(function() {
|
||||
var NEWTON_ITERATIONS = 4;
|
||||
var NEWTON_MIN_SLOPE = 0.001;
|
||||
var SUBDIVISION_PRECISION = 0.0000001;
|
||||
var SUBDIVISION_MAX_ITERATIONS = 10;
|
||||
|
||||
var kSplineTableSize = 11;
|
||||
var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
||||
|
||||
var float32ArraySupported = typeof Float32Array === 'function';
|
||||
|
||||
function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
|
||||
function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
|
||||
function C (aA1) { return 3.0 * aA1; }
|
||||
|
||||
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
||||
function calcBezier (aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }
|
||||
|
||||
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
||||
function getSlope (aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }
|
||||
|
||||
function binarySubdivide (aX, aA, aB, mX1, mX2) {
|
||||
var currentX, currentT, i = 0;
|
||||
do {
|
||||
currentT = aA + (aB - aA) / 2.0;
|
||||
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
||||
if (currentX > 0.0) {
|
||||
aB = currentT;
|
||||
} else {
|
||||
aA = currentT;
|
||||
}
|
||||
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
|
||||
return currentT;
|
||||
}
|
||||
|
||||
function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) {
|
||||
for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
|
||||
var currentSlope = getSlope(aGuessT, mX1, mX2);
|
||||
if (currentSlope === 0.0) {
|
||||
return aGuessT;
|
||||
}
|
||||
var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
|
||||
aGuessT -= currentX / currentSlope;
|
||||
}
|
||||
return aGuessT;
|
||||
}
|
||||
|
||||
var BezierEasing = function (mX1, mY1, mX2, mY2) {
|
||||
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
|
||||
throw new Error('bezier x values must be in [0, 1] range');
|
||||
}
|
||||
|
||||
// Precompute samples table
|
||||
var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
|
||||
if (mX1 !== mY1 || mX2 !== mY2) {
|
||||
for (var i = 0; i < kSplineTableSize; ++i) {
|
||||
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
||||
}
|
||||
}
|
||||
|
||||
function getTForX (aX) {
|
||||
var intervalStart = 0.0;
|
||||
var currentSample = 1;
|
||||
var lastSample = kSplineTableSize - 1;
|
||||
|
||||
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
|
||||
intervalStart += kSampleStepSize;
|
||||
}
|
||||
--currentSample;
|
||||
|
||||
// Interpolate to provide an initial guess for t
|
||||
var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
||||
var guessForT = intervalStart + dist * kSampleStepSize;
|
||||
|
||||
var initialSlope = getSlope(guessForT, mX1, mX2);
|
||||
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
||||
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
||||
} else if (initialSlope === 0.0) {
|
||||
return guessForT;
|
||||
} else {
|
||||
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
|
||||
}
|
||||
}
|
||||
|
||||
return function BezierEasing (x) {
|
||||
if (mX1 === mY1 && mX2 === mY2) {
|
||||
return x; // linear
|
||||
}
|
||||
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
||||
if (x === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (x === 1) {
|
||||
return 1;
|
||||
}
|
||||
return calcBezier(getTForX(x), mY1, mY2);
|
||||
};
|
||||
};
|
||||
|
||||
this.colorEasing = BezierEasing(0.26, 0.09, 0.37, 0.18);
|
||||
// less 3 requires a return
|
||||
return '';
|
||||
})()`;
|
||||
}
|
||||
// It is hacky way to make this function will be compiled preferentially by less
|
||||
// resolve error: `ReferenceError: colorPalette is not defined`
|
||||
// https://github.com/ant-design/ant-motion/issues/44
|
||||
.bezierEasingMixin();
|
||||
@@ -0,0 +1,85 @@
|
||||
/* stylelint-disable no-duplicate-selectors */
|
||||
@import "bezierEasing";
|
||||
@import "tinyColor";
|
||||
|
||||
// We create a very complex algorithm which take the place of original tint/shade color system
|
||||
// to make sure no one can understand it 👻
|
||||
// and create an entire color palette magicly by inputing just a single primary color.
|
||||
// We are using bezier-curve easing function and some color manipulations like tint/shade/darken/spin
|
||||
.colorPaletteMixin() {
|
||||
@functions: ~`(function() {
|
||||
var hueStep = 2;
|
||||
var saturationStep = 0.16;
|
||||
var saturationStep2 = 0.05;
|
||||
var brightnessStep1 = 0.05;
|
||||
var brightnessStep2 = 0.15;
|
||||
var lightColorCount = 5;
|
||||
var darkColorCount = 4;
|
||||
|
||||
var getHue = function(hsv, i, isLight) {
|
||||
var hue;
|
||||
if (hsv.h >= 60 && hsv.h <= 240) {
|
||||
hue = isLight ? hsv.h - hueStep * i : hsv.h + hueStep * i;
|
||||
} else {
|
||||
hue = isLight ? hsv.h + hueStep * i : hsv.h - hueStep * i;
|
||||
}
|
||||
if (hue < 0) {
|
||||
hue += 360;
|
||||
} else if (hue >= 360) {
|
||||
hue -= 360;
|
||||
}
|
||||
return Math.round(hue);
|
||||
};
|
||||
var getSaturation = function(hsv, i, isLight) {
|
||||
// grey color don't change saturation
|
||||
if (hsv.h === 0 && hsv.s === 0) {
|
||||
return hsv.s;
|
||||
}
|
||||
var saturation;
|
||||
if (isLight) {
|
||||
saturation = hsv.s - saturationStep * i;
|
||||
} else if (i === darkColorCount) {
|
||||
saturation = hsv.s + saturationStep;
|
||||
} else {
|
||||
saturation = hsv.s + saturationStep2 * i;
|
||||
}
|
||||
if (saturation > 1) {
|
||||
saturation = 1;
|
||||
}
|
||||
if (isLight && i === lightColorCount && saturation > 0.1) {
|
||||
saturation = 0.1;
|
||||
}
|
||||
if (saturation < 0.06) {
|
||||
saturation = 0.06;
|
||||
}
|
||||
return Number(saturation.toFixed(2));
|
||||
};
|
||||
var getValue = function(hsv, i, isLight) {
|
||||
var value;
|
||||
if (isLight) {
|
||||
value = hsv.v + brightnessStep1 * i;
|
||||
}else{
|
||||
value = hsv.v - brightnessStep2 * i
|
||||
}
|
||||
if (value > 1) {
|
||||
value = 1;
|
||||
}
|
||||
return Number(value.toFixed(2))
|
||||
};
|
||||
|
||||
this.colorPalette = function(color, index) {
|
||||
var isLight = index <= 6;
|
||||
var hsv = tinycolor(color).toHsv();
|
||||
var i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1;
|
||||
return tinycolor({
|
||||
h: getHue(hsv, i, isLight),
|
||||
s: getSaturation(hsv, i, isLight),
|
||||
v: getValue(hsv, i, isLight),
|
||||
}).toHexString();
|
||||
};
|
||||
})()`;
|
||||
}
|
||||
// It is hacky way to make this function will be compiled preferentially by less
|
||||
// resolve error: `ReferenceError: colorPalette is not defined`
|
||||
// https://github.com/ant-design/ant-motion/issues/44
|
||||
.colorPaletteMixin();
|
||||
162
webapp/packages/supersonic-fe/src/assets/style/color/colors.less
Normal file
162
webapp/packages/supersonic-fe/src/assets/style/color/colors.less
Normal file
@@ -0,0 +1,162 @@
|
||||
@import 'colorPalette';
|
||||
|
||||
// color palettes
|
||||
@blue-base: #1890ff;
|
||||
@blue-1: color(~`colorPalette('@{blue-6}', 1) `);
|
||||
@blue-2: color(~`colorPalette('@{blue-6}', 2) `);
|
||||
@blue-3: color(~`colorPalette('@{blue-6}', 3) `);
|
||||
@blue-4: color(~`colorPalette('@{blue-6}', 4) `);
|
||||
@blue-5: color(~`colorPalette('@{blue-6}', 5) `);
|
||||
@blue-6: @blue-base;
|
||||
@blue-7: color(~`colorPalette('@{blue-6}', 7) `);
|
||||
@blue-8: color(~`colorPalette('@{blue-6}', 8) `);
|
||||
@blue-9: color(~`colorPalette('@{blue-6}', 9) `);
|
||||
@blue-10: color(~`colorPalette('@{blue-6}', 10) `);
|
||||
|
||||
@purple-base: #722ed1;
|
||||
@purple-1: color(~`colorPalette('@{purple-6}', 1) `);
|
||||
@purple-2: color(~`colorPalette('@{purple-6}', 2) `);
|
||||
@purple-3: color(~`colorPalette('@{purple-6}', 3) `);
|
||||
@purple-4: color(~`colorPalette('@{purple-6}', 4) `);
|
||||
@purple-5: color(~`colorPalette('@{purple-6}', 5) `);
|
||||
@purple-6: @purple-base;
|
||||
@purple-7: color(~`colorPalette('@{purple-6}', 7) `);
|
||||
@purple-8: color(~`colorPalette('@{purple-6}', 8) `);
|
||||
@purple-9: color(~`colorPalette('@{purple-6}', 9) `);
|
||||
@purple-10: color(~`colorPalette('@{purple-6}', 10) `);
|
||||
|
||||
@cyan-base: #13c2c2;
|
||||
@cyan-1: color(~`colorPalette('@{cyan-6}', 1) `);
|
||||
@cyan-2: color(~`colorPalette('@{cyan-6}', 2) `);
|
||||
@cyan-3: color(~`colorPalette('@{cyan-6}', 3) `);
|
||||
@cyan-4: color(~`colorPalette('@{cyan-6}', 4) `);
|
||||
@cyan-5: color(~`colorPalette('@{cyan-6}', 5) `);
|
||||
@cyan-6: @cyan-base;
|
||||
@cyan-7: color(~`colorPalette('@{cyan-6}', 7) `);
|
||||
@cyan-8: color(~`colorPalette('@{cyan-6}', 8) `);
|
||||
@cyan-9: color(~`colorPalette('@{cyan-6}', 9) `);
|
||||
@cyan-10: color(~`colorPalette('@{cyan-6}', 10) `);
|
||||
|
||||
@green-base: #52c41a;
|
||||
@green-1: color(~`colorPalette('@{green-6}', 1) `);
|
||||
@green-2: color(~`colorPalette('@{green-6}', 2) `);
|
||||
@green-3: color(~`colorPalette('@{green-6}', 3) `);
|
||||
@green-4: color(~`colorPalette('@{green-6}', 4) `);
|
||||
@green-5: color(~`colorPalette('@{green-6}', 5) `);
|
||||
@green-6: @green-base;
|
||||
@green-7: color(~`colorPalette('@{green-6}', 7) `);
|
||||
@green-8: color(~`colorPalette('@{green-6}', 8) `);
|
||||
@green-9: color(~`colorPalette('@{green-6}', 9) `);
|
||||
@green-10: color(~`colorPalette('@{green-6}', 10) `);
|
||||
|
||||
@magenta-base: #eb2f96;
|
||||
@magenta-1: color(~`colorPalette('@{magenta-6}', 1) `);
|
||||
@magenta-2: color(~`colorPalette('@{magenta-6}', 2) `);
|
||||
@magenta-3: color(~`colorPalette('@{magenta-6}', 3) `);
|
||||
@magenta-4: color(~`colorPalette('@{magenta-6}', 4) `);
|
||||
@magenta-5: color(~`colorPalette('@{magenta-6}', 5) `);
|
||||
@magenta-6: @magenta-base;
|
||||
@magenta-7: color(~`colorPalette('@{magenta-6}', 7) `);
|
||||
@magenta-8: color(~`colorPalette('@{magenta-6}', 8) `);
|
||||
@magenta-9: color(~`colorPalette('@{magenta-6}', 9) `);
|
||||
@magenta-10: color(~`colorPalette('@{magenta-6}', 10) `);
|
||||
|
||||
// alias of magenta
|
||||
@pink-base: #eb2f96;
|
||||
@pink-1: color(~`colorPalette('@{pink-6}', 1) `);
|
||||
@pink-2: color(~`colorPalette('@{pink-6}', 2) `);
|
||||
@pink-3: color(~`colorPalette('@{pink-6}', 3) `);
|
||||
@pink-4: color(~`colorPalette('@{pink-6}', 4) `);
|
||||
@pink-5: color(~`colorPalette('@{pink-6}', 5) `);
|
||||
@pink-6: @pink-base;
|
||||
@pink-7: color(~`colorPalette('@{pink-6}', 7) `);
|
||||
@pink-8: color(~`colorPalette('@{pink-6}', 8) `);
|
||||
@pink-9: color(~`colorPalette('@{pink-6}', 9) `);
|
||||
@pink-10: color(~`colorPalette('@{pink-6}', 10) `);
|
||||
|
||||
@red-base: #f5222d;
|
||||
@red-1: color(~`colorPalette('@{red-6}', 1) `);
|
||||
@red-2: color(~`colorPalette('@{red-6}', 2) `);
|
||||
@red-3: color(~`colorPalette('@{red-6}', 3) `);
|
||||
@red-4: color(~`colorPalette('@{red-6}', 4) `);
|
||||
@red-5: color(~`colorPalette('@{red-6}', 5) `);
|
||||
@red-6: @red-base;
|
||||
@red-7: color(~`colorPalette('@{red-6}', 7) `);
|
||||
@red-8: color(~`colorPalette('@{red-6}', 8) `);
|
||||
@red-9: color(~`colorPalette('@{red-6}', 9) `);
|
||||
@red-10: color(~`colorPalette('@{red-6}', 10) `);
|
||||
|
||||
@orange-base: #fa8c16;
|
||||
@orange-1: color(~`colorPalette('@{orange-6}', 1) `);
|
||||
@orange-2: color(~`colorPalette('@{orange-6}', 2) `);
|
||||
@orange-3: color(~`colorPalette('@{orange-6}', 3) `);
|
||||
@orange-4: color(~`colorPalette('@{orange-6}', 4) `);
|
||||
@orange-5: color(~`colorPalette('@{orange-6}', 5) `);
|
||||
@orange-6: @orange-base;
|
||||
@orange-7: color(~`colorPalette('@{orange-6}', 7) `);
|
||||
@orange-8: color(~`colorPalette('@{orange-6}', 8) `);
|
||||
@orange-9: color(~`colorPalette('@{orange-6}', 9) `);
|
||||
@orange-10: color(~`colorPalette('@{orange-6}', 10) `);
|
||||
|
||||
@yellow-base: #fadb14;
|
||||
@yellow-1: color(~`colorPalette('@{yellow-6}', 1) `);
|
||||
@yellow-2: color(~`colorPalette('@{yellow-6}', 2) `);
|
||||
@yellow-3: color(~`colorPalette('@{yellow-6}', 3) `);
|
||||
@yellow-4: color(~`colorPalette('@{yellow-6}', 4) `);
|
||||
@yellow-5: color(~`colorPalette('@{yellow-6}', 5) `);
|
||||
@yellow-6: @yellow-base;
|
||||
@yellow-7: color(~`colorPalette('@{yellow-6}', 7) `);
|
||||
@yellow-8: color(~`colorPalette('@{yellow-6}', 8) `);
|
||||
@yellow-9: color(~`colorPalette('@{yellow-6}', 9) `);
|
||||
@yellow-10: color(~`colorPalette('@{yellow-6}', 10) `);
|
||||
|
||||
@volcano-base: #fa541c;
|
||||
@volcano-1: color(~`colorPalette('@{volcano-6}', 1) `);
|
||||
@volcano-2: color(~`colorPalette('@{volcano-6}', 2) `);
|
||||
@volcano-3: color(~`colorPalette('@{volcano-6}', 3) `);
|
||||
@volcano-4: color(~`colorPalette('@{volcano-6}', 4) `);
|
||||
@volcano-5: color(~`colorPalette('@{volcano-6}', 5) `);
|
||||
@volcano-6: @volcano-base;
|
||||
@volcano-7: color(~`colorPalette('@{volcano-6}', 7) `);
|
||||
@volcano-8: color(~`colorPalette('@{volcano-6}', 8) `);
|
||||
@volcano-9: color(~`colorPalette('@{volcano-6}', 9) `);
|
||||
@volcano-10: color(~`colorPalette('@{volcano-6}', 10) `);
|
||||
|
||||
@geekblue-base: #2f54eb;
|
||||
@geekblue-1: color(~`colorPalette('@{geekblue-6}', 1) `);
|
||||
@geekblue-2: color(~`colorPalette('@{geekblue-6}', 2) `);
|
||||
@geekblue-3: color(~`colorPalette('@{geekblue-6}', 3) `);
|
||||
@geekblue-4: color(~`colorPalette('@{geekblue-6}', 4) `);
|
||||
@geekblue-5: color(~`colorPalette('@{geekblue-6}', 5) `);
|
||||
@geekblue-6: @geekblue-base;
|
||||
@geekblue-7: color(~`colorPalette('@{geekblue-6}', 7) `);
|
||||
@geekblue-8: color(~`colorPalette('@{geekblue-6}', 8) `);
|
||||
@geekblue-9: color(~`colorPalette('@{geekblue-6}', 9) `);
|
||||
@geekblue-10: color(~`colorPalette('@{geekblue-6}', 10) `);
|
||||
|
||||
@lime-base: #a0d911;
|
||||
@lime-1: color(~`colorPalette('@{lime-6}', 1) `);
|
||||
@lime-2: color(~`colorPalette('@{lime-6}', 2) `);
|
||||
@lime-3: color(~`colorPalette('@{lime-6}', 3) `);
|
||||
@lime-4: color(~`colorPalette('@{lime-6}', 4) `);
|
||||
@lime-5: color(~`colorPalette('@{lime-6}', 5) `);
|
||||
@lime-6: @lime-base;
|
||||
@lime-7: color(~`colorPalette('@{lime-6}', 7) `);
|
||||
@lime-8: color(~`colorPalette('@{lime-6}', 8) `);
|
||||
@lime-9: color(~`colorPalette('@{lime-6}', 9) `);
|
||||
@lime-10: color(~`colorPalette('@{lime-6}', 10) `);
|
||||
|
||||
@gold-base: #faad14;
|
||||
@gold-1: color(~`colorPalette('@{gold-6}', 1) `);
|
||||
@gold-2: color(~`colorPalette('@{gold-6}', 2) `);
|
||||
@gold-3: color(~`colorPalette('@{gold-6}', 3) `);
|
||||
@gold-4: color(~`colorPalette('@{gold-6}', 4) `);
|
||||
@gold-5: color(~`colorPalette('@{gold-6}', 5) `);
|
||||
@gold-6: @gold-base;
|
||||
@gold-7: color(~`colorPalette('@{gold-6}', 7) `);
|
||||
@gold-8: color(~`colorPalette('@{gold-6}', 8) `);
|
||||
@gold-9: color(~`colorPalette('@{gold-6}', 9) `);
|
||||
@gold-10: color(~`colorPalette('@{gold-6}', 10) `);
|
||||
|
||||
@preset-colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime, green, blue, geekblue,
|
||||
purple;
|
||||
1184
webapp/packages/supersonic-fe/src/assets/style/color/tinyColor.less
Normal file
1184
webapp/packages/supersonic-fe/src/assets/style/color/tinyColor.less
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './themes/compact.less';
|
||||
@import './core/index';
|
||||
@@ -0,0 +1,10 @@
|
||||
// Config global less under antd
|
||||
[class^=~'@{ant-prefix}-'],
|
||||
[class*=~' @{ant-prefix}-'] {
|
||||
// remove the clear button of a text input control in IE10+
|
||||
&::-ms-clear,
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
491
webapp/packages/supersonic-fe/src/assets/style/core/global.less
Normal file
491
webapp/packages/supersonic-fe/src/assets/style/core/global.less
Normal file
@@ -0,0 +1,491 @@
|
||||
/* stylelint-disable property-no-vendor-prefix, at-rule-no-vendor-prefix */
|
||||
|
||||
// Reboot
|
||||
//
|
||||
// Normalization of HTML elements, manually forked from Normalize.css to remove
|
||||
// styles targeting irrelevant browsers while applying new styles.
|
||||
//
|
||||
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
|
||||
|
||||
// HTML & Body reset
|
||||
@{html-selector},
|
||||
body {
|
||||
.square(100%);
|
||||
}
|
||||
|
||||
// remove the clear button of a text input control in IE10+
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Document
|
||||
//
|
||||
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
|
||||
// 2. Change the default font family in all browsers.
|
||||
// 3. Correct the line height in all browsers.
|
||||
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
|
||||
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
|
||||
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
|
||||
// 6. Change the default tap highlight to be completely transparent in iOS.
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box; // 1
|
||||
}
|
||||
|
||||
@{html-selector} {
|
||||
font-family: sans-serif; // 2
|
||||
line-height: 1.15; // 3
|
||||
-webkit-text-size-adjust: 100%; // 4
|
||||
-ms-text-size-adjust: 100%; // 4
|
||||
-ms-overflow-style: scrollbar; // 5
|
||||
-webkit-tap-highlight-color: fade(@black, 0%); // 6
|
||||
}
|
||||
|
||||
// IE10+ doesn't honor `<meta name="viewport">` in some cases.
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
// Body
|
||||
//
|
||||
// 1. remove the margin in all browsers.
|
||||
// 2. As a best practice, apply a default `body-background`.
|
||||
|
||||
body {
|
||||
margin: 0; // 1
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-family: @font-family;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
background-color: @body-background; // 2
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
|
||||
// Suppress the focus outline on elements that cannot be accessed via keyboard.
|
||||
// This prevents an unwanted focus outline from appearing around elements that
|
||||
// might still respond to pointer events.
|
||||
//
|
||||
// Credit: https://github.com/suitcss/base
|
||||
[tabindex='-1']:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
// Content grouping
|
||||
//
|
||||
// 1. Add the correct box sizing in Firefox.
|
||||
// 2. Show the overflow in Edge and IE.
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; // 1
|
||||
height: 0; // 1
|
||||
overflow: visible; // 2
|
||||
}
|
||||
|
||||
//
|
||||
// Typography
|
||||
//
|
||||
|
||||
// remove top margins from headings
|
||||
//
|
||||
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
|
||||
// margin for easier control within type scales as it avoids margin collapsing.
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// Reset margins on paragraphs
|
||||
//
|
||||
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
|
||||
// bottom margin to use `em` units instead of `em`.
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
// Abbreviations
|
||||
//
|
||||
// 1. remove the bottom border in Firefox 39-.
|
||||
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
// 3. Add explicit cursor to indicate changed behavior.
|
||||
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
// 4
|
||||
text-decoration: underline; // 2
|
||||
text-decoration: underline dotted; // 2
|
||||
border-bottom: 0; // 1
|
||||
cursor: help; // 3
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1em;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='number'],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 0; // Undo browser default
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic; // Add the correct font style in Android 4.3-
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%; // Add the correct font size in all browsers
|
||||
}
|
||||
|
||||
//
|
||||
// Prevent `sub` and `sup` elements from affecting the line height in
|
||||
// all browsers.
|
||||
//
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
//
|
||||
// Links
|
||||
//
|
||||
|
||||
a {
|
||||
color: @link-color;
|
||||
text-decoration: @link-decoration;
|
||||
background-color: transparent; // remove the gray background on active links in IE 10.
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
-webkit-text-decoration-skip: objects; // remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:hover {
|
||||
text-decoration: @link-hover-decoration;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22503
|
||||
&:focus {
|
||||
text-decoration: @link-focus-decoration;
|
||||
outline: @link-focus-outline;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code
|
||||
//
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 1em; // Correct the odd `em` font sizing in all browsers.
|
||||
font-family: @code-family;
|
||||
}
|
||||
|
||||
pre {
|
||||
// remove browser default top margin
|
||||
margin-top: 0;
|
||||
// Reset browser default of `1em` to use `em`s
|
||||
margin-bottom: 1em;
|
||||
// Don't allow content to break outside
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
//
|
||||
// Figures
|
||||
//
|
||||
figure {
|
||||
// Apply a consistent margin strategy (matches our type styles).
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
//
|
||||
// Images and content
|
||||
//
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // remove the border on images inside links in IE 10-.
|
||||
}
|
||||
|
||||
// Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
|
||||
//
|
||||
// In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
|
||||
// DON'T remove the click delay when `<meta name="viewport" content="width=device-width">` is present.
|
||||
// However, they DO support emoving the click delay via `touch-action: manipulation`.
|
||||
// See:
|
||||
// * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
|
||||
// * http://caniuse.com/#feat=css-touch-action
|
||||
// * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
|
||||
|
||||
a,
|
||||
area,
|
||||
button,
|
||||
[role='button'],
|
||||
input:not([type='range']),
|
||||
label,
|
||||
select,
|
||||
summary,
|
||||
textarea {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
//
|
||||
// Tables
|
||||
//
|
||||
|
||||
table {
|
||||
border-collapse: collapse; // Prevent double borders
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75em;
|
||||
padding-bottom: 0.3em;
|
||||
color: @text-color-secondary;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
//
|
||||
// Forms
|
||||
//
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0; // remove the margin in Firefox and Safari
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible; // Show the overflow in Edge
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none; // remove the inheritance of text transform in Firefox
|
||||
}
|
||||
|
||||
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
// controls in Android 4.
|
||||
// 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
button,
|
||||
@{html-selector} [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; // 2
|
||||
}
|
||||
|
||||
// remove inner border and padding from Firefox, but don't restore the outline like Normalize.
|
||||
button::-moz-focus-inner,
|
||||
[type='button']::-moz-focus-inner,
|
||||
[type='reset']::-moz-focus-inner,
|
||||
[type='submit']::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
|
||||
padding: 0; // 2. remove the padding in IE 10-
|
||||
}
|
||||
|
||||
input[type='date'],
|
||||
input[type='time'],
|
||||
input[type='datetime-local'],
|
||||
input[type='month'] {
|
||||
// remove the default appearance of temporal inputs to avoid a Mobile Safari
|
||||
// bug where setting a custom line-height prevents text from being vertically
|
||||
// centered within the input.
|
||||
// See https://bugs.webkit.org/show_bug.cgi?id=139848
|
||||
// and https://github.com/twbs/bootstrap/issues/11266
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto; // remove the default vertical scrollbar in IE.
|
||||
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
// Browsers set a default `min-width: min-content;` on fieldsets,
|
||||
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
|
||||
// So we reset that to ensure fieldsets behave more like a standard block element.
|
||||
// See https://github.com/twbs/bootstrap/issues/12359
|
||||
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
// Reset the default outline behavior of fieldsets so they don't affect page layout.
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// 1. Correct the text wrapping in Edge and IE.
|
||||
// 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%; // 1
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0;
|
||||
color: inherit; // 2
|
||||
font-size: 1.5em;
|
||||
line-height: inherit;
|
||||
white-space: normal; // 1
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
}
|
||||
|
||||
// Correct the cursor style of incement and decement buttons in Chrome.
|
||||
[type='number']::-webkit-inner-spin-button,
|
||||
[type='number']::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type='search'] {
|
||||
// This overrides the extra rounded corners on search inputs in iOS so that our
|
||||
// `.form-control` class can properly style them. Note that this cannot simply
|
||||
// be added to `.form-control` as it's not specific enough. For details, see
|
||||
// https://github.com/twbs/bootstrap/issues/11586.
|
||||
outline-offset: -2px; // 2. Correct the outline style in Safari.
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
//
|
||||
|
||||
[type='search']::-webkit-search-cancel-button,
|
||||
[type='search']::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
// 2. Change font properties to `inherit` in Safari.
|
||||
//
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit; // 2
|
||||
-webkit-appearance: button; // 1
|
||||
}
|
||||
|
||||
//
|
||||
// Correct element displays
|
||||
//
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item; // Add the correct display in all browsers
|
||||
}
|
||||
|
||||
template {
|
||||
display: none; // Add the correct display in IE
|
||||
}
|
||||
|
||||
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
|
||||
// Needed for proper display in IE 10-.
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: @yellow-1;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: @text-color-inverse;
|
||||
background: @text-selection-bg;
|
||||
}
|
||||
|
||||
// Utility classes
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
@import '../themes/index';
|
||||
@import '../mixins/iconfont';
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
.iconfont-mixin();
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/33703
|
||||
& > & {
|
||||
line-height: 0;
|
||||
vertical-align: 0;
|
||||
}
|
||||
|
||||
&[tabindex] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-spin,
|
||||
.@{iconfont-css-prefix}-spin::before {
|
||||
display: inline-block;
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@import '../mixins/index';
|
||||
@import 'base';
|
||||
@import 'global';
|
||||
@import 'iconfont';
|
||||
@import 'motion';
|
||||
@@ -0,0 +1,22 @@
|
||||
// @import '../mixins/motion'; This has moved to theme/xxx inside.
|
||||
@import 'motion/fade';
|
||||
@import 'motion/move';
|
||||
@import 'motion/other';
|
||||
@import 'motion/slide';
|
||||
@import 'motion/zoom';
|
||||
|
||||
// For common/openAnimation
|
||||
.ant-motion-collapse-legacy {
|
||||
overflow: hidden;
|
||||
|
||||
&-active {
|
||||
transition: height @animation-duration-base @ease-in-out,
|
||||
opacity @animation-duration-base @ease-in-out !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-motion-collapse {
|
||||
overflow: hidden;
|
||||
transition: height @animation-duration-base @ease-in-out,
|
||||
opacity @animation-duration-base @ease-in-out !important;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
.fade-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
opacity: 0;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-motion(fade, antFade);
|
||||
|
||||
@keyframes antFadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antFadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
.move-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-circ;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-circ;
|
||||
}
|
||||
}
|
||||
|
||||
.move-motion(move-up, antMoveUp);
|
||||
.move-motion(move-down, antMoveDown);
|
||||
.move-motion(move-left, antMoveLeft);
|
||||
.move-motion(move-right, antMoveRight);
|
||||
|
||||
@keyframes antMoveDownIn {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveDownOut {
|
||||
0% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveLeftIn {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveLeftOut {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveRightIn {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveRightOut {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
@keyframes loadingCircle {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@click-animating-true: ~"[@{ant-prefix}-click-animating='true']";
|
||||
@click-animating-with-extra-node-true: ~"[@{ant-prefix}-click-animating-without-extra-node='true']";
|
||||
|
||||
@{click-animating-true},
|
||||
@{click-animating-with-extra-node-true} {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
html {
|
||||
--antd-wave-shadow-color: @primary-color;
|
||||
--scroll-bar: 0;
|
||||
}
|
||||
|
||||
@click-animating-with-extra-node-true-after: ~'@{click-animating-with-extra-node-true}::after';
|
||||
|
||||
@{click-animating-with-extra-node-true-after},
|
||||
.@{ant-prefix}-click-animating-node {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
border-radius: inherit;
|
||||
box-shadow: 0 0 0 0 @primary-color;
|
||||
box-shadow: 0 0 0 0 var(--antd-wave-shadow-color);
|
||||
opacity: 0.2;
|
||||
animation: fadeEffect 2s @ease-out-circ, waveEffect 0.4s @ease-out-circ;
|
||||
animation-fill-mode: forwards;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes waveEffect {
|
||||
100% {
|
||||
box-shadow: 0 0 0 @primary-color;
|
||||
box-shadow: 0 0 0 @wave-animation-width var(--antd-wave-shadow-color);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeEffect {
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
.slide-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
transform: scale(0);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-quint;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-quint;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-motion(slide-up, antSlideUp);
|
||||
.slide-motion(slide-down, antSlideDown);
|
||||
.slide-motion(slide-left, antSlideLeft);
|
||||
.slide-motion(slide-right, antSlideRight);
|
||||
|
||||
@keyframes antSlideUpIn {
|
||||
0% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideUpOut {
|
||||
0% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideDownIn {
|
||||
0% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideDownOut {
|
||||
0% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideLeftIn {
|
||||
0% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideLeftOut {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideRightIn {
|
||||
0% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideRightOut {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
.zoom-motion(@className, @keyframeName, @duration: @animation-duration-base) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName, @duration);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
transform: scale(0); // need this by yiminghe
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-circ;
|
||||
|
||||
&-prepare {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-out-circ;
|
||||
}
|
||||
}
|
||||
|
||||
// For Modal, Select choosen item
|
||||
.zoom-motion(zoom, antZoom);
|
||||
// For Popover, Popconfirm, Dropdown
|
||||
.zoom-motion(zoom-big, antZoomBig);
|
||||
// For Tooltip
|
||||
.zoom-motion(zoom-big-fast, antZoomBig, @animation-duration-fast);
|
||||
|
||||
.zoom-motion(zoom-up, antZoomUp);
|
||||
.zoom-motion(zoom-down, antZoomDown);
|
||||
.zoom-motion(zoom-left, antZoomLeft);
|
||||
.zoom-motion(zoom-right, antZoomRight);
|
||||
|
||||
@keyframes antZoomIn {
|
||||
0% {
|
||||
transform: scale(0.2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBigIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBigOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomUpIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomUpOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomLeftIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 0% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomLeftOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 0% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomRightIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 100% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomRightOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 100% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomDownIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomDownOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
1
webapp/packages/supersonic-fe/src/assets/style/css.js
Normal file
1
webapp/packages/supersonic-fe/src/assets/style/css.js
Normal file
@@ -0,0 +1 @@
|
||||
import './index.css';
|
||||
4
webapp/packages/supersonic-fe/src/assets/style/dark.less
Normal file
4
webapp/packages/supersonic-fe/src/assets/style/dark.less
Normal file
@@ -0,0 +1,4 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './themes/dark.less';
|
||||
@import './core/index';
|
||||
1248
webapp/packages/supersonic-fe/src/assets/style/default.css
Normal file
1248
webapp/packages/supersonic-fe/src/assets/style/default.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
// This is same as `index.less` but given `root-entry-name` for `dist/antd.less` usage
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './index';
|
||||
@@ -0,0 +1,2 @@
|
||||
@import './themes/index';
|
||||
@import './core/index';
|
||||
1248
webapp/packages/supersonic-fe/src/assets/style/index.css
Normal file
1248
webapp/packages/supersonic-fe/src/assets/style/index.css
Normal file
File diff suppressed because it is too large
Load Diff
1
webapp/packages/supersonic-fe/src/assets/style/index.d.ts
vendored
Normal file
1
webapp/packages/supersonic-fe/src/assets/style/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import './index.less';
|
||||
1
webapp/packages/supersonic-fe/src/assets/style/index.js
Normal file
1
webapp/packages/supersonic-fe/src/assets/style/index.js
Normal file
@@ -0,0 +1 @@
|
||||
import './index.less';
|
||||
@@ -0,0 +1,3 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './index-pure.less';
|
||||
@@ -0,0 +1,7 @@
|
||||
.box(@position: absolute) {
|
||||
position: @position;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// mixins for clearfix
|
||||
// ------------------------
|
||||
.clearfix() {
|
||||
// https://github.com/ant-design/ant-design/issues/21301#issuecomment-583955229
|
||||
&::before {
|
||||
display: table;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::after {
|
||||
// https://github.com/ant-design/ant-design/issues/21864
|
||||
display: table;
|
||||
clear: both;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
.compact-item-vertical-border-radius(@prefix-cls) {
|
||||
&-item:not(&-first-item):not(&-last-item) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-first-item:not(&-last-item) {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-last-item:not(&-first-item) {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-vertical-border(@prefix-cls) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item) {
|
||||
margin-bottom: -@border-width-base;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-vertical(@prefix-cls) {
|
||||
&-compact-vertical {
|
||||
.compact-item-vertical-border(@prefix-cls);
|
||||
.compact-item-vertical-border-radius(@prefix-cls);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
.compact-item-border-radius(@prefix-cls, @bordered-item-cls: null) {
|
||||
& when (@bordered-item-cls = null) {
|
||||
// border-radius
|
||||
&-item:not(&-first-item):not(&-last-item).@{prefix-cls} {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item.@{prefix-cls}&-first-item:not(&-last-item):not(&-item-rtl) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
&-item.@{prefix-cls}&-last-item:not(&-first-item):not(&-item-rtl) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for first item----------
|
||||
&-item.@{prefix-cls}&-item-rtl&-first-item:not(&-last-item) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for last item----------
|
||||
&-item.@{prefix-cls}&-item-rtl&-last-item:not(&-first-item) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& when (not (@bordered-item-cls = null)) {
|
||||
// border-radius
|
||||
&-item:not(&-first-item):not(&-last-item).@{prefix-cls} > .@{bordered-item-cls} {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-first-item.@{prefix-cls}:not(&-last-item):not(&-item-rtl) > .@{bordered-item-cls} {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-last-item.@{prefix-cls}:not(&-first-item):not(&-item-rtl) > .@{bordered-item-cls} {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for first item----------
|
||||
&-item.@{prefix-cls}&-first-item&-item-rtl:not(&-last-item) > .@{bordered-item-cls} {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for last item----------
|
||||
&-item.@{prefix-cls}&-last-item&-item-rtl:not(&-first-item) > .@{bordered-item-cls} {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-border(@prefix-cls, @bordered-item-cls: null, @special-open-cls) {
|
||||
& when (@bordered-item-cls = null) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item):not(&-item-rtl) {
|
||||
margin-right: -@border-width-base;
|
||||
}
|
||||
|
||||
// rtl border collapse
|
||||
&-item:not(&-last-item)&-item-rtl {
|
||||
margin-left: -@border-width-base;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
// Select has an extra focus className
|
||||
& when (not (@special-item-cls = null)) {
|
||||
&.@{special-item-cls} {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& when (not (@bordered-item-cls = null)) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item) {
|
||||
margin-right: -@border-width-base;
|
||||
|
||||
&.@{prefix-cls}-compact-item-rtl {
|
||||
margin-right: 0;
|
||||
margin-left: -@border-width-base;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
> * {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Select has an special focus-item
|
||||
& when (not (@special-item-cls = null)) {
|
||||
&.@{special-item-cls} > * {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] > * {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item(@prefix-cls, @bordered-item-cls: null, @special-item-cls: null) {
|
||||
&-compact {
|
||||
.compact-item-border(@prefix-cls, @bordered-item-cls, @special-item-cls);
|
||||
|
||||
.compact-item-border-radius(@prefix-cls, @bordered-item-cls);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Compatibility for browsers.
|
||||
|
||||
// Placeholder text
|
||||
.placeholder(@color: @input-placeholder-color) {
|
||||
&::placeholder {
|
||||
color: @color;
|
||||
user-select: none; // https://github.com/ant-design/ant-design/pull/32639
|
||||
}
|
||||
|
||||
&:placeholder-shown {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
// customize dark components background in popover containers(like Modal, Drawer, Card, Popover, Popconfirm, Notification, ...)
|
||||
// for dark theme
|
||||
.popover-customize-bg(@containerClass, @background: @popover-background, @prefix: @ant-prefix)
|
||||
when
|
||||
(@theme = dark) {
|
||||
@picker-prefix-cls: ~'@{prefix}-picker';
|
||||
@slider-prefix-cls: ~'@{prefix}-slider';
|
||||
@anchor-prefix-cls: ~'@{prefix}-anchor';
|
||||
@collapse-prefix-cls: ~'@{prefix}-collapse';
|
||||
@tab-prefix-cls: ~'@{prefix}-tabs';
|
||||
@timeline-prefix-cls: ~'@{prefix}-timeline';
|
||||
@tree-prefix-cls: ~'@{prefix}-tree';
|
||||
@card-prefix-cls: ~'@{prefix}-card';
|
||||
@badge-prefix-cls: ~'@{prefix}-badge';
|
||||
@transfer-prefix-cls: ~'@{prefix}-transfer';
|
||||
@calendar-prefix-cls: ~'@{prefix}-picker-calendar';
|
||||
@calendar-picker-prefix-cls: ~'@{prefix}-picker';
|
||||
@table-prefix-cls: ~'@{prefix}-table';
|
||||
|
||||
@popover-border: @border-width-base @border-style-base @popover-customize-border-color;
|
||||
|
||||
.@{containerClass} {
|
||||
.@{picker-prefix-cls}-clear,
|
||||
.@{slider-prefix-cls}-handle,
|
||||
.@{anchor-prefix-cls}-wrapper,
|
||||
.@{collapse-prefix-cls}-content,
|
||||
.@{timeline-prefix-cls}-item-head,
|
||||
.@{card-prefix-cls} {
|
||||
background-color: @background;
|
||||
}
|
||||
|
||||
.@{transfer-prefix-cls} {
|
||||
&-list {
|
||||
&-header {
|
||||
background: @background;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
&-content-item:not(.@{transfer-prefix-cls}-list-content-item-disabled):hover {
|
||||
background-color: @item-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.@{table-prefix-cls}-expanded-row {
|
||||
&,
|
||||
&:hover {
|
||||
> td {
|
||||
background: #272727;
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls}.@{table-prefix-cls}-small {
|
||||
thead {
|
||||
> tr {
|
||||
> th {
|
||||
background-color: @background;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls} {
|
||||
background-color: @background;
|
||||
.@{table-prefix-cls}-row-expand-icon {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
tfoot {
|
||||
> tr {
|
||||
> th,
|
||||
> td {
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thead {
|
||||
> tr {
|
||||
> th {
|
||||
background-color: #272727;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
> tr {
|
||||
> td {
|
||||
border-bottom: @popover-border;
|
||||
&.@{table-prefix-cls}-cell-fix-left,
|
||||
&.@{table-prefix-cls}-cell-fix-right {
|
||||
background-color: @background;
|
||||
}
|
||||
}
|
||||
&.@{table-prefix-cls}-row:hover {
|
||||
> td {
|
||||
background: @table-header-sort-active-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.@{table-prefix-cls}-bordered {
|
||||
.@{table-prefix-cls}-title {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
// ============================= Cell =============================
|
||||
thead > tr > th,
|
||||
tbody > tr > td,
|
||||
tfoot > tr > th,
|
||||
tfoot > tr > td {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
|
||||
// Fixed right should provides additional border
|
||||
.@{table-prefix-cls}-cell-fix-right-first::after {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
|
||||
// ============================ Header ============================
|
||||
table > {
|
||||
thead {
|
||||
> tr:not(:last-child) > th {
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================== Content ============================
|
||||
.@{table-prefix-cls}-container {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
// ========================== Expandable ==========================
|
||||
.@{table-prefix-cls}-expanded-row-fixed {
|
||||
&::after {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-footer {
|
||||
border: @popover-border;
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls}-filter-trigger-container-open {
|
||||
background-color: #525252;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-full {
|
||||
background-color: @background;
|
||||
.@{calendar-picker-prefix-cls}-panel {
|
||||
background-color: @background;
|
||||
.@{calendar-prefix-cls}-date {
|
||||
border-top: 2px solid @popover-customize-border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{tab-prefix-cls} {
|
||||
&.@{tab-prefix-cls}-card .@{tab-prefix-cls}-card-bar .@{tab-prefix-cls}-tab-active {
|
||||
background-color: @background;
|
||||
border-bottom: @border-width-base solid @background;
|
||||
}
|
||||
}
|
||||
|
||||
.@{badge-prefix-cls} {
|
||||
&-count {
|
||||
box-shadow: 0 0 0 1px @background;
|
||||
}
|
||||
}
|
||||
|
||||
.@{tree-prefix-cls} {
|
||||
&-show-line {
|
||||
.@{tree-prefix-cls}-switcher {
|
||||
background: @background;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
.iconfont-mixin() {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: @icon-color;
|
||||
font-style: normal;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
vertical-align: -0.125em; // for SVG icon, see https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4
|
||||
text-rendering: optimizelegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
> * {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none; // dont display old icon.
|
||||
}
|
||||
|
||||
& &-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Mixins
|
||||
// --------------------------------------------------
|
||||
@import 'size';
|
||||
@import 'compatibility';
|
||||
@import 'clearfix';
|
||||
@import 'iconfont';
|
||||
@import 'typography';
|
||||
@import 'customize';
|
||||
@import 'box';
|
||||
@import 'modal-mask';
|
||||
@import 'motion';
|
||||
@import 'reset';
|
||||
@import 'operation-unit';
|
||||
@import 'rounded-arrow';
|
||||
@import 'compact-item';
|
||||
@import 'compact-item-vertical';
|
||||
@@ -0,0 +1,30 @@
|
||||
@import 'box';
|
||||
|
||||
.modal-mask() {
|
||||
pointer-events: none;
|
||||
|
||||
&.@{ant-prefix}-zoom-enter,
|
||||
&.@{ant-prefix}-zoom-appear {
|
||||
transform: none; // reset scale avoid mousePosition bug
|
||||
opacity: 0;
|
||||
animation-duration: @animation-duration-slow;
|
||||
user-select: none; // https://github.com/ant-design/ant-design/issues/11777
|
||||
}
|
||||
|
||||
&-mask {
|
||||
.box(fixed);
|
||||
z-index: @zindex-modal-mask;
|
||||
height: 100%;
|
||||
background-color: @modal-mask-bg;
|
||||
|
||||
&-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-wrap {
|
||||
.box(fixed);
|
||||
overflow: auto;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
.motion-common(@duration: @animation-duration-base) {
|
||||
animation-duration: @duration;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.motion-common-leave(@duration: @animation-duration-base) {
|
||||
animation-duration: @duration;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.make-motion(@className, @keyframeName, @duration: @animation-duration-base) {
|
||||
.@{className}-enter,
|
||||
.@{className}-appear {
|
||||
.motion-common(@duration);
|
||||
|
||||
animation-play-state: paused;
|
||||
}
|
||||
.@{className}-leave {
|
||||
.motion-common-leave(@duration);
|
||||
|
||||
animation-play-state: paused;
|
||||
}
|
||||
.@{className}-enter.@{className}-enter-active,
|
||||
.@{className}-appear.@{className}-appear-active {
|
||||
animation-name: ~'@{keyframeName}In';
|
||||
animation-play-state: running;
|
||||
}
|
||||
.@{className}-leave.@{className}-leave-active {
|
||||
animation-name: ~'@{keyframeName}Out';
|
||||
animation-play-state: running;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
.operation-unit() {
|
||||
color: @link-color;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.reset-component() {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
list-style: none;
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
.roundedArrow(@width, @outer-radius, @bg-color: var(--antd-arrow-background-color)) {
|
||||
@corner-height: unit(((@outer-radius) * (1 - 1 / sqrt(2))));
|
||||
|
||||
@width-without-unit: unit(@width);
|
||||
@outer-radius-without-unit: unit(@outer-radius);
|
||||
@inner-radius-without-unit: unit(@arrow-border-radius);
|
||||
|
||||
@a-x: @width-without-unit - @corner-height;
|
||||
@a-y: 2 * @width-without-unit + @corner-height;
|
||||
@b-x: @a-x + @outer-radius-without-unit * (1 / sqrt(2));
|
||||
@b-y: 2 * @width-without-unit;
|
||||
@c-x: 2 * @width-without-unit - @inner-radius-without-unit;
|
||||
@c-y: 2 * @width-without-unit;
|
||||
@d-x: 2 * @width-without-unit;
|
||||
@d-y: 2 * @width-without-unit - @inner-radius-without-unit;
|
||||
@e-x: 2 * @width-without-unit;
|
||||
@e-y: @f-y + @outer-radius-without-unit * (1 / sqrt(2));
|
||||
@f-x: 2 * @width-without-unit + @corner-height;
|
||||
@f-y: @width-without-unit - @corner-height;
|
||||
@g-x: @f-x - 1;
|
||||
@g-y: @f-y;
|
||||
@h-x: @a-x;
|
||||
@h-y: @a-y - 1;
|
||||
|
||||
border-radius: 0 0 @arrow-border-radius;
|
||||
pointer-events: none;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -@width;
|
||||
left: -@width;
|
||||
width: @width * 3;
|
||||
height: @width * 3;
|
||||
background: @bg-color;
|
||||
// Hack firefox: https://github.com/ant-design/ant-design/pull/33710#issuecomment-1015287825
|
||||
background-repeat: no-repeat;
|
||||
background-position: ceil(-@width + 1px) ceil(-@width + 1px);
|
||||
content: '';
|
||||
clip-path: inset(33% 33%); // For browsers that do not support path()
|
||||
clip-path: path(
|
||||
'M @{a-x} @{a-y} A @{outer-radius-without-unit} @{outer-radius-without-unit} 0 0 1 @{b-x} @{b-y} L @{c-x} @{c-y} A @{inner-radius-without-unit} @{inner-radius-without-unit} 0 0 0 @{d-x} @{d-y} L @{e-x} @{e-y} A @{outer-radius-without-unit} @{outer-radius-without-unit} 0 0 1 @{f-x} @{f-y} L @{g-x} @{g-y} L @{h-x} @{h-y} Z'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Sizing shortcuts
|
||||
|
||||
.size(@width; @height) {
|
||||
width: @width;
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.square(@size) {
|
||||
.size(@size; @size);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// =============== Common ===============
|
||||
.typography-paragraph() {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.typography-title(@fontSize; @fontWeight; @lineHeight; @headingColor; @headingMarginBottom;) {
|
||||
margin-bottom: @headingMarginBottom;
|
||||
color: @headingColor;
|
||||
font-weight: @fontWeight;
|
||||
font-size: @fontSize;
|
||||
line-height: @lineHeight;
|
||||
}
|
||||
|
||||
.typography-title-1() {
|
||||
.typography-title(
|
||||
@heading-1-size,
|
||||
@typography-title-font-weight,
|
||||
1.23,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-2() {
|
||||
.typography-title(
|
||||
@heading-2-size,
|
||||
@typography-title-font-weight,
|
||||
1.35,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-3() {
|
||||
.typography-title(
|
||||
@heading-3-size,
|
||||
@typography-title-font-weight,
|
||||
1.35,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-4() {
|
||||
.typography-title(
|
||||
@heading-4-size,
|
||||
@typography-title-font-weight,
|
||||
1.4,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-5() {
|
||||
.typography-title(
|
||||
@heading-5-size,
|
||||
@typography-title-font-weight,
|
||||
1.5,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
@import './default.less';
|
||||
|
||||
@line-height-base: 1.66667;
|
||||
@mode: compact;
|
||||
@font-size-base: 12px;
|
||||
@font-size-lg: @font-size-base + 2px;
|
||||
|
||||
// default paddings
|
||||
@default-padding-lg: 24px; // containers
|
||||
@default-padding-md: 16px; // small containers and buttons
|
||||
@default-padding-sm: 12px; // Form controls and items
|
||||
@default-padding-xs: 8px; // small items
|
||||
@default-padding-xss: 4px; // more small
|
||||
|
||||
// vertical paddings
|
||||
@padding-lg: 16px; // containers
|
||||
@padding-md: 8px; // small containers and buttons
|
||||
@padding-sm: 8px; // Form controls and items
|
||||
@padding-xs: 4px; // small items
|
||||
@padding-xss: 0px; // more small
|
||||
|
||||
// vertical padding for all form controls
|
||||
@control-padding-horizontal: @padding-sm;
|
||||
@control-padding-horizontal-sm: @default-padding-xs;
|
||||
|
||||
// vertical margins
|
||||
@margin-lg: 16px; // containers
|
||||
@margin-md: 8px; // small containers and buttons
|
||||
@margin-sm: 8px; // Form controls and items
|
||||
@margin-xs: 4px; // small items
|
||||
@margin-xss: 0px; // more small
|
||||
|
||||
// height rules
|
||||
@height-base: 28px;
|
||||
@height-lg: 32px;
|
||||
@height-sm: 22px;
|
||||
|
||||
// Button
|
||||
// ---
|
||||
@btn-padding-horizontal-base: @default-padding-sm - 1px;
|
||||
@btn-padding-horizontal-lg: @btn-padding-horizontal-base;
|
||||
@btn-padding-horizontal-sm: @default-padding-xs - 1px;
|
||||
@btn-square-only-icon-size-lg: 16px;
|
||||
@btn-square-only-icon-size: 14px;
|
||||
@btn-square-only-icon-size-sm: 12px;
|
||||
|
||||
// Breadcrumb
|
||||
// ---
|
||||
@breadcrumb-font-size: @font-size-base;
|
||||
@breadcrumb-icon-font-size: @font-size-base;
|
||||
|
||||
//Dropdown
|
||||
@dropdown-line-height: 18px;
|
||||
|
||||
// Menu
|
||||
@menu-item-padding-horizontal: 12px;
|
||||
@menu-horizontal-line-height: 38px;
|
||||
@menu-inline-toplevel-item-height: 32px;
|
||||
@menu-item-height: 32px;
|
||||
@menu-item-vertical-margin: 0px;
|
||||
@menu-item-boundary-margin: 0px;
|
||||
@menu-icon-margin-right: 8px;
|
||||
|
||||
// Checkbox
|
||||
@checkbox-size: 14px;
|
||||
@checkbox-group-item-margin-right: 6px;
|
||||
|
||||
// picker
|
||||
@picker-panel-cell-height: 22px;
|
||||
@picker-panel-cell-width: 32px;
|
||||
@picker-text-height: 32px;
|
||||
@picker-time-panel-cell-height: 24px;
|
||||
@picker-panel-without-time-cell-height: 48px;
|
||||
|
||||
// Form
|
||||
// ---
|
||||
@form-item-margin-bottom: 16px;
|
||||
@form-vertical-label-padding: 0 0 4px;
|
||||
|
||||
// Rate
|
||||
// ---
|
||||
@rate-star-size: 16px;
|
||||
|
||||
// Radio
|
||||
// ---
|
||||
@radio-size: 14px;
|
||||
@radio-wrapper-margin-right: 6px;
|
||||
|
||||
// Switch
|
||||
// ---
|
||||
@switch-height: 20px;
|
||||
@switch-sm-height: 14px;
|
||||
@switch-min-width: 40px;
|
||||
@switch-sm-min-width: 24px;
|
||||
@switch-inner-margin-min: 4px;
|
||||
@switch-inner-margin-max: 22px;
|
||||
|
||||
// Slider
|
||||
// ---
|
||||
@slider-handle-size: 12px;
|
||||
@slider-handle-margin-top: -4px;
|
||||
|
||||
// Input
|
||||
// ---
|
||||
@input-padding-vertical-base: round(
|
||||
max(
|
||||
(round(((@input-height-base - @font-size-base * @line-height-base) / 2) * 10) / 10) -
|
||||
@border-width-base,
|
||||
2px
|
||||
)
|
||||
);
|
||||
@input-padding-horizontal-lg: 11px;
|
||||
|
||||
// PageHeader
|
||||
// ---
|
||||
@page-header-padding: 16px;
|
||||
@page-header-padding-vertical: 8px;
|
||||
@page-header-heading-title: 16px;
|
||||
@page-header-heading-sub-title: 12px;
|
||||
@page-header-tabs-tab-font-size: 14px;
|
||||
|
||||
// Pagination
|
||||
// ---
|
||||
@pagination-mini-options-size-changer-top: 1px;
|
||||
@pagination-item-size-sm: 22px;
|
||||
|
||||
// Cascader
|
||||
// ----
|
||||
@cascader-dropdown-line-height: @dropdown-line-height;
|
||||
|
||||
// Select
|
||||
// ---
|
||||
@select-dropdown-height: @height-base;
|
||||
@select-single-item-height-lg: 32px;
|
||||
@select-multiple-item-height: @input-height-base - max(@input-padding-vertical-base, 4) * 2; // Normal 24px
|
||||
@select-multiple-item-height-lg: 24px;
|
||||
@select-multiple-item-spacing-half: 3px;
|
||||
|
||||
// Tree
|
||||
// ---
|
||||
@tree-title-height: 20px;
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-item-padding-vertical: 3px;
|
||||
@transfer-list-search-icon-top: 8px;
|
||||
@transfer-header-height: 36px;
|
||||
|
||||
// Comment
|
||||
// ---
|
||||
@comment-actions-margin-bottom: 0px;
|
||||
@comment-actions-margin-top: @margin-xs;
|
||||
@comment-content-detail-p-margin-bottom: 0px;
|
||||
|
||||
// Steps
|
||||
// ---
|
||||
@steps-icon-size: 24px;
|
||||
@steps-icon-custom-size: 20px;
|
||||
@steps-icon-custom-font-size: 20px;
|
||||
@steps-icon-custom-top: 2px;
|
||||
@steps-icon-margin: 2px 8px 2px 0;
|
||||
@steps-icon-font-size: @font-size-base;
|
||||
@steps-dot-top: 4px;
|
||||
@steps-icon-top: 0px;
|
||||
@steps-small-icon-size: 20px;
|
||||
@steps-vertical-icon-width: 12px;
|
||||
@steps-vertical-tail-width: 12px;
|
||||
@steps-vertical-tail-width-sm: 10px;
|
||||
// Collapse
|
||||
// ---
|
||||
//@collapse-header-padding-extra: 32px;
|
||||
@collapse-content-padding: @padding-md @padding-lg;
|
||||
|
||||
// List
|
||||
// ---
|
||||
@list-item-meta-description-font-size: @font-size-sm;
|
||||
@list-item-padding-sm: 4px 12px;
|
||||
@list-item-padding-lg: 12px 16px;
|
||||
|
||||
// Drawer
|
||||
// ---
|
||||
@drawer-header-padding: 11px @padding-lg;
|
||||
@drawer-footer-padding-vertical: @padding-sm;
|
||||
@drawer-footer-padding-horizontal: @padding-sm;
|
||||
@drawer-header-close-size: 44px;
|
||||
|
||||
// Modal
|
||||
// --
|
||||
@modal-header-padding-vertical: 11px;
|
||||
@modal-header-padding: @modal-header-padding-vertical @modal-header-padding-horizontal;
|
||||
@modal-footer-padding-vertical: @padding-sm;
|
||||
@modal-header-close-size: @modal-header-title-line-height + 2 * @modal-header-padding-vertical;
|
||||
@modal-confirm-body-padding: 24px 24px 16px;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-padding: 8px 16px;
|
||||
|
||||
// popover
|
||||
// --
|
||||
@popover-min-height: 28px;
|
||||
@popover-padding-horizontal: @default-padding-sm;
|
||||
|
||||
// Card
|
||||
// ---
|
||||
@card-head-height: 36px;
|
||||
@card-head-font-size: @card-head-font-size-sm;
|
||||
@card-head-padding: 8.5px;
|
||||
@card-padding-base: 12px;
|
||||
@card-padding-base-sm: @card-padding-base;
|
||||
@card-head-height-sm: 30px;
|
||||
@card-head-padding-sm: 6px;
|
||||
@card-actions-li-margin: 4px 0;
|
||||
@card-head-tabs-margin-bottom: -9px;
|
||||
|
||||
// Table
|
||||
// ---
|
||||
@table-padding-vertical: 12px;
|
||||
@table-padding-horizontal: 8px;
|
||||
@table-padding-vertical-md: 8px;
|
||||
@table-padding-horizontal-md: 8px;
|
||||
@table-padding-vertical-sm: 4px;
|
||||
@table-padding-horizontal-sm: 4px;
|
||||
@table-selection-column-width: 32px;
|
||||
|
||||
// Statistic
|
||||
// ---
|
||||
@statistic-content-font-size: 20px;
|
||||
|
||||
// Alert
|
||||
// ---
|
||||
@alert-with-description-no-icon-padding-vertical: 7px;
|
||||
@alert-with-description-padding-vertical: 11px;
|
||||
@alert-icon-top: 7px + @font-size-base * (@line-height-base / 2) - (@font-size-base / 2);
|
||||
@alert-with-description-icon-size: 20px;
|
||||
|
||||
// Skeleton
|
||||
// ---
|
||||
@skeleton-paragraph-margin-top: 20px;
|
||||
@skeleton-paragraph-li-margin-top: 12px;
|
||||
@skeleton-paragraph-li-height: 14px;
|
||||
@skeleton-title-height: 14px;
|
||||
@skeleton-title-paragraph-margin-top: 20px;
|
||||
|
||||
// Descriptions
|
||||
@descriptions-title-margin-bottom: 8px;
|
||||
@descriptions-default-padding: 12px @padding-lg;
|
||||
@descriptions-item-padding-bottom: @padding-xs;
|
||||
|
||||
// Avatar
|
||||
// ---
|
||||
@avatar-size-base: 28px;
|
||||
@avatar-size-lg: 32px;
|
||||
@avatar-size-sm: 22px;
|
||||
@avatar-font-size-base: 16px;
|
||||
@avatar-font-size-lg: 20px;
|
||||
@avatar-font-size-sm: 12px;
|
||||
|
||||
// Badge
|
||||
// ---
|
||||
@badge-height: 18px;
|
||||
|
||||
// Tag
|
||||
// ---
|
||||
@tag-line-height: 18px;
|
||||
|
||||
// Notification
|
||||
// ---
|
||||
@notification-padding-vertical: 12px;
|
||||
@notification-padding-horizontal: 16px;
|
||||
|
||||
// Result
|
||||
// ---
|
||||
@result-title-font-size: 20px;
|
||||
@result-icon-font-size: 64px;
|
||||
@result-extra-margin: 24px 0 0 0;
|
||||
|
||||
// Anchor
|
||||
// ---
|
||||
@anchor-link-top: 4px;
|
||||
@anchor-link-left: 16px;
|
||||
@anchor-link-padding: @anchor-link-top 0 @anchor-link-top @anchor-link-left;
|
||||
|
||||
// Tabs
|
||||
// ---
|
||||
@tabs-card-horizontal-padding: 4px @padding-md;
|
||||
|
||||
// Progress
|
||||
// ---
|
||||
@progress-circle-text-font-size: 0.833333em;
|
||||
|
||||
// Image
|
||||
// ---
|
||||
@image-size-base: 48px;
|
||||
@image-font-size-base: 24px;
|
||||
457
webapp/packages/supersonic-fe/src/assets/style/themes/dark.less
Normal file
457
webapp/packages/supersonic-fe/src/assets/style/themes/dark.less
Normal file
@@ -0,0 +1,457 @@
|
||||
@import './default.less';
|
||||
|
||||
@theme: dark;
|
||||
// color palettes
|
||||
@blue-1: mix(color(~`colorPalette('@{blue-base}', 8) `), @component-background, 15%);
|
||||
@blue-2: mix(color(~`colorPalette('@{blue-base}', 7) `), @component-background, 25%);
|
||||
@blue-3: mix(@blue-base, @component-background, 30%);
|
||||
@blue-4: mix(@blue-base, @component-background, 45%);
|
||||
@blue-5: mix(@blue-base, @component-background, 65%);
|
||||
@blue-6: mix(@blue-base, @component-background, 85%);
|
||||
@blue-7: mix(color(~`colorPalette('@{blue-base}', 5) `), @component-background, 90%);
|
||||
@blue-8: mix(color(~`colorPalette('@{blue-base}', 4) `), @component-background, 95%);
|
||||
@blue-9: mix(color(~`colorPalette('@{blue-base}', 3) `), @component-background, 97%);
|
||||
@blue-10: mix(color(~`colorPalette('@{blue-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@purple-1: mix(color(~`colorPalette('@{purple-base}', 8) `), @component-background, 15%);
|
||||
@purple-2: mix(color(~`colorPalette('@{purple-base}', 7) `), @component-background, 25%);
|
||||
@purple-3: mix(@purple-base, @component-background, 30%);
|
||||
@purple-4: mix(@purple-base, @component-background, 45%);
|
||||
@purple-5: mix(@purple-base, @component-background, 65%);
|
||||
@purple-6: mix(@purple-base, @component-background, 85%);
|
||||
@purple-7: mix(color(~`colorPalette('@{purple-base}', 5) `), @component-background, 90%);
|
||||
@purple-8: mix(color(~`colorPalette('@{purple-base}', 4) `), @component-background, 95%);
|
||||
@purple-9: mix(color(~`colorPalette('@{purple-base}', 3) `), @component-background, 97%);
|
||||
@purple-10: mix(color(~`colorPalette('@{purple-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@cyan-1: mix(color(~`colorPalette('@{cyan-base}', 8) `), @component-background, 15%);
|
||||
@cyan-2: mix(color(~`colorPalette('@{cyan-base}', 7) `), @component-background, 25%);
|
||||
@cyan-3: mix(@cyan-base, @component-background, 30%);
|
||||
@cyan-4: mix(@cyan-base, @component-background, 45%);
|
||||
@cyan-5: mix(@cyan-base, @component-background, 65%);
|
||||
@cyan-6: mix(@cyan-base, @component-background, 85%);
|
||||
@cyan-7: mix(color(~`colorPalette('@{cyan-base}', 5) `), @component-background, 90%);
|
||||
@cyan-8: mix(color(~`colorPalette('@{cyan-base}', 4) `), @component-background, 95%);
|
||||
@cyan-9: mix(color(~`colorPalette('@{cyan-base}', 3) `), @component-background, 97%);
|
||||
@cyan-10: mix(color(~`colorPalette('@{cyan-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@green-1: mix(color(~`colorPalette('@{green-base}', 8) `), @component-background, 15%);
|
||||
@green-2: mix(color(~`colorPalette('@{green-base}', 7) `), @component-background, 25%);
|
||||
@green-3: mix(@green-base, @component-background, 30%);
|
||||
@green-4: mix(@green-base, @component-background, 45%);
|
||||
@green-5: mix(@green-base, @component-background, 65%);
|
||||
@green-6: mix(@green-base, @component-background, 85%);
|
||||
@green-7: mix(color(~`colorPalette('@{green-base}', 5) `), @component-background, 90%);
|
||||
@green-8: mix(color(~`colorPalette('@{green-base}', 4) `), @component-background, 95%);
|
||||
@green-9: mix(color(~`colorPalette('@{green-base}', 3) `), @component-background, 97%);
|
||||
@green-10: mix(color(~`colorPalette('@{green-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@magenta-1: mix(color(~`colorPalette('@{magenta-base}', 8) `), @component-background, 15%);
|
||||
@magenta-2: mix(color(~`colorPalette('@{magenta-base}', 7) `), @component-background, 25%);
|
||||
@magenta-3: mix(@magenta-base, @component-background, 30%);
|
||||
@magenta-4: mix(@magenta-base, @component-background, 45%);
|
||||
@magenta-5: mix(@magenta-base, @component-background, 65%);
|
||||
@magenta-6: mix(@magenta-base, @component-background, 85%);
|
||||
@magenta-7: mix(color(~`colorPalette('@{magenta-base}', 5) `), @component-background, 90%);
|
||||
@magenta-8: mix(color(~`colorPalette('@{magenta-base}', 4) `), @component-background, 95%);
|
||||
@magenta-9: mix(color(~`colorPalette('@{magenta-base}', 3) `), @component-background, 97%);
|
||||
@magenta-10: mix(color(~`colorPalette('@{magenta-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@pink-1: mix(color(~`colorPalette('@{pink-base}', 8) `), @component-background, 15%);
|
||||
@pink-2: mix(color(~`colorPalette('@{pink-base}', 7) `), @component-background, 25%);
|
||||
@pink-3: mix(@pink-base, @component-background, 30%);
|
||||
@pink-4: mix(@pink-base, @component-background, 45%);
|
||||
@pink-5: mix(@pink-base, @component-background, 65%);
|
||||
@pink-6: mix(@pink-base, @component-background, 85%);
|
||||
@pink-7: mix(color(~`colorPalette('@{pink-base}', 5) `), @component-background, 90%);
|
||||
@pink-8: mix(color(~`colorPalette('@{pink-base}', 4) `), @component-background, 95%);
|
||||
@pink-9: mix(color(~`colorPalette('@{pink-base}', 3) `), @component-background, 97%);
|
||||
@pink-10: mix(color(~`colorPalette('@{pink-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@red-1: mix(color(~`colorPalette('@{red-base}', 8) `), @component-background, 15%);
|
||||
@red-2: mix(color(~`colorPalette('@{red-base}', 7) `), @component-background, 25%);
|
||||
@red-3: mix(@red-base, @component-background, 30%);
|
||||
@red-4: mix(@red-base, @component-background, 45%);
|
||||
@red-5: mix(@red-base, @component-background, 65%);
|
||||
@red-6: mix(@red-base, @component-background, 85%);
|
||||
@red-7: mix(color(~`colorPalette('@{red-base}', 5) `), @component-background, 90%);
|
||||
@red-8: mix(color(~`colorPalette('@{red-base}', 4) `), @component-background, 95%);
|
||||
@red-9: mix(color(~`colorPalette('@{red-base}', 3) `), @component-background, 97%);
|
||||
@red-10: mix(color(~`colorPalette('@{red-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@orange-1: mix(color(~`colorPalette('@{orange-base}', 8) `), @component-background, 15%);
|
||||
@orange-2: mix(color(~`colorPalette('@{orange-base}', 7) `), @component-background, 25%);
|
||||
@orange-3: mix(@orange-base, @component-background, 30%);
|
||||
@orange-4: mix(@orange-base, @component-background, 45%);
|
||||
@orange-5: mix(@orange-base, @component-background, 65%);
|
||||
@orange-6: mix(@orange-base, @component-background, 85%);
|
||||
@orange-7: mix(color(~`colorPalette('@{orange-base}', 5) `), @component-background, 90%);
|
||||
@orange-8: mix(color(~`colorPalette('@{orange-base}', 4) `), @component-background, 95%);
|
||||
@orange-9: mix(color(~`colorPalette('@{orange-base}', 3) `), @component-background, 97%);
|
||||
@orange-10: mix(color(~`colorPalette('@{orange-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@yellow-1: mix(color(~`colorPalette('@{yellow-base}', 8) `), @component-background, 15%);
|
||||
@yellow-2: mix(color(~`colorPalette('@{yellow-base}', 7) `), @component-background, 25%);
|
||||
@yellow-3: mix(@yellow-base, @component-background, 30%);
|
||||
@yellow-4: mix(@yellow-base, @component-background, 45%);
|
||||
@yellow-5: mix(@yellow-base, @component-background, 65%);
|
||||
@yellow-6: mix(@yellow-base, @component-background, 85%);
|
||||
@yellow-7: mix(color(~`colorPalette('@{yellow-base}', 5) `), @component-background, 90%);
|
||||
@yellow-8: mix(color(~`colorPalette('@{yellow-base}', 4) `), @component-background, 95%);
|
||||
@yellow-9: mix(color(~`colorPalette('@{yellow-base}', 3) `), @component-background, 97%);
|
||||
@yellow-10: mix(color(~`colorPalette('@{yellow-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@volcano-1: mix(color(~`colorPalette('@{volcano-base}', 8) `), @component-background, 15%);
|
||||
@volcano-2: mix(color(~`colorPalette('@{volcano-base}', 7) `), @component-background, 25%);
|
||||
@volcano-3: mix(@volcano-base, @component-background, 30%);
|
||||
@volcano-4: mix(@volcano-base, @component-background, 45%);
|
||||
@volcano-5: mix(@volcano-base, @component-background, 65%);
|
||||
@volcano-6: mix(@volcano-base, @component-background, 85%);
|
||||
@volcano-7: mix(color(~`colorPalette('@{volcano-base}', 5) `), @component-background, 90%);
|
||||
@volcano-8: mix(color(~`colorPalette('@{volcano-base}', 4) `), @component-background, 95%);
|
||||
@volcano-9: mix(color(~`colorPalette('@{volcano-base}', 3) `), @component-background, 97%);
|
||||
@volcano-10: mix(color(~`colorPalette('@{volcano-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@geekblue-1: mix(color(~`colorPalette('@{geekblue-base}', 8) `), @component-background, 15%);
|
||||
@geekblue-2: mix(color(~`colorPalette('@{geekblue-base}', 7) `), @component-background, 25%);
|
||||
@geekblue-3: mix(@geekblue-base, @component-background, 30%);
|
||||
@geekblue-4: mix(@geekblue-base, @component-background, 45%);
|
||||
@geekblue-5: mix(@geekblue-base, @component-background, 65%);
|
||||
@geekblue-6: mix(@geekblue-base, @component-background, 85%);
|
||||
@geekblue-7: mix(color(~`colorPalette('@{geekblue-base}', 5) `), @component-background, 90%);
|
||||
@geekblue-8: mix(color(~`colorPalette('@{geekblue-base}', 4) `), @component-background, 95%);
|
||||
@geekblue-9: mix(color(~`colorPalette('@{geekblue-base}', 3) `), @component-background, 97%);
|
||||
@geekblue-10: mix(color(~`colorPalette('@{geekblue-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@lime-1: mix(color(~`colorPalette('@{lime-base}', 8) `), @component-background, 15%);
|
||||
@lime-2: mix(color(~`colorPalette('@{lime-base}', 7) `), @component-background, 25%);
|
||||
@lime-3: mix(@lime-base, @component-background, 30%);
|
||||
@lime-4: mix(@lime-base, @component-background, 45%);
|
||||
@lime-5: mix(@lime-base, @component-background, 65%);
|
||||
@lime-6: mix(@lime-base, @component-background, 85%);
|
||||
@lime-7: mix(color(~`colorPalette('@{lime-base}', 5) `), @component-background, 90%);
|
||||
@lime-8: mix(color(~`colorPalette('@{lime-base}', 4) `), @component-background, 95%);
|
||||
@lime-9: mix(color(~`colorPalette('@{lime-base}', 3) `), @component-background, 97%);
|
||||
@lime-10: mix(color(~`colorPalette('@{lime-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@gold-1: mix(color(~`colorPalette('@{gold-base}', 8) `), @component-background, 15%);
|
||||
@gold-2: mix(color(~`colorPalette('@{gold-base}', 7) `), @component-background, 25%);
|
||||
@gold-3: mix(@gold-base, @component-background, 30%);
|
||||
@gold-4: mix(@gold-base, @component-background, 45%);
|
||||
@gold-5: mix(@gold-base, @component-background, 65%);
|
||||
@gold-6: mix(@gold-base, @component-background, 85%);
|
||||
@gold-7: mix(color(~`colorPalette('@{gold-base}', 5) `), @component-background, 90%);
|
||||
@gold-8: mix(color(~`colorPalette('@{gold-base}', 4) `), @component-background, 95%);
|
||||
@gold-9: mix(color(~`colorPalette('@{gold-base}', 3) `), @component-background, 97%);
|
||||
@gold-10: mix(color(~`colorPalette('@{gold-base}', 2) `), @component-background, 98%);
|
||||
|
||||
// Color used by default to control hover and active backgrounds and for
|
||||
// alert info backgrounds.
|
||||
@primary-1: mix(color(~`colorPalette('@{primary-color}', 8) `), @component-background, 15%);
|
||||
@primary-2: mix(color(~`colorPalette('@{primary-color}', 7) `), @component-background, 25%);
|
||||
@primary-3: mix(@primary-color, @component-background, 30%);
|
||||
@primary-4: mix(@primary-color, @component-background, 45%);
|
||||
@primary-5: mix(@primary-color, @component-background, 65%);
|
||||
@primary-6: @primary-color;
|
||||
@primary-7: mix(color(~`colorPalette('@{primary-color}', 5) `), @component-background, 90%);
|
||||
@primary-8: mix(color(~`colorPalette('@{primary-color}', 4) `), @component-background, 95%);
|
||||
@primary-9: mix(color(~`colorPalette('@{primary-color}', 3) `), @component-background, 97%);
|
||||
@primary-10: mix(color(~`colorPalette('@{primary-color}', 2) `), @component-background, 98%);
|
||||
|
||||
// Layer background
|
||||
@popover-background: #1f1f1f;
|
||||
@popover-customize-border-color: #3a3a3a;
|
||||
@body-background: @black;
|
||||
@component-background: #141414;
|
||||
|
||||
@text-color: fade(@white, 85%);
|
||||
@text-color-secondary: fade(@white, 45%);
|
||||
@text-color-inverse: @white;
|
||||
@icon-color-hover: fade(@white, 75%);
|
||||
@heading-color: fade(@white, 85%);
|
||||
|
||||
// The background colors for active and hover states for things like
|
||||
// list items or table cells.
|
||||
@item-active-bg: @primary-1;
|
||||
@item-hover-bg: fade(@white, 8%);
|
||||
|
||||
// Border color
|
||||
@border-color-base: #434343; // base border outline a component
|
||||
@border-color-split: #303030; // split border inside a component
|
||||
|
||||
@background-color-light: fade(@white, 4%); // background of header and selected item
|
||||
@background-color-base: fade(@white, 8%); // Default grey background color
|
||||
|
||||
// Disabled states
|
||||
@disabled-color: fade(@white, 30%);
|
||||
@disabled-bg: @background-color-base;
|
||||
@disabled-color-dark: fade(@white, 30%);
|
||||
|
||||
// Tree
|
||||
// ---
|
||||
@tree-bg: transparent;
|
||||
|
||||
// List
|
||||
// ---
|
||||
@list-customize-card-bg: transparent;
|
||||
|
||||
// Shadow
|
||||
// ---
|
||||
@shadow-color: rgba(0, 0, 0, 0.45);
|
||||
@shadow-color-inverse: @component-background;
|
||||
@box-shadow-base: @shadow-2;
|
||||
@shadow-1-up: 0 -6px 16px -8px rgba(0, 0, 0, 0.32), 0 -9px 28px 0 rgba(0, 0, 0, 0.2),
|
||||
0 -12px 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-1-down: 0 6px 16px -8px rgba(0, 0, 0, 0.32), 0 9px 28px 0 rgba(0, 0, 0, 0.2),
|
||||
0 12px 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-1-right: 6px 0 16px -8px rgba(0, 0, 0, 0.32), 9px 0 28px 0 rgba(0, 0, 0, 0.2),
|
||||
12px 0 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-2: 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 6px 16px 0 rgba(0, 0, 0, 0.32),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.2);
|
||||
|
||||
// Buttons
|
||||
// ---
|
||||
@btn-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
||||
@btn-primary-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
|
||||
@btn-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
@btn-default-bg: transparent;
|
||||
|
||||
@btn-default-ghost-color: @text-color;
|
||||
@btn-default-ghost-border: fade(@white, 25%);
|
||||
|
||||
@btn-text-hover-bg: rgba(255, 255, 255, 0.03);
|
||||
|
||||
// Checkbox
|
||||
// ---
|
||||
@checkbox-check-bg: transparent;
|
||||
|
||||
// Descriptions
|
||||
// ---
|
||||
@descriptions-bg: @background-color-light;
|
||||
|
||||
// Divider
|
||||
// ---
|
||||
@divider-color: rgba(255, 255, 255, 12%);
|
||||
|
||||
// Modal
|
||||
// ---
|
||||
@modal-header-bg: @popover-background;
|
||||
@modal-header-border-color-split: @border-color-split;
|
||||
@modal-content-bg: @popover-background;
|
||||
@modal-footer-border-color-split: @border-color-split;
|
||||
|
||||
// Radio
|
||||
// ---
|
||||
@radio-solid-checked-color: @white;
|
||||
@radio-dot-disabled-color: fade(@white, 20%);
|
||||
|
||||
// Radio buttons
|
||||
// ---
|
||||
@radio-disabled-button-checked-bg: fade(@white, 20%);
|
||||
@radio-disabled-button-checked-color: @disabled-color;
|
||||
|
||||
// Layout
|
||||
// ---
|
||||
@layout-body-background: @body-background;
|
||||
@layout-header-background: @popover-background;
|
||||
@layout-trigger-background: #262626;
|
||||
|
||||
// Input
|
||||
// ---
|
||||
@input-bg: transparent;
|
||||
@input-placeholder-color: fade(@white, 30%);
|
||||
@input-icon-color: fade(@white, 30%);
|
||||
@input-number-handler-active-bg: @item-hover-bg;
|
||||
@input-icon-hover-color: fade(@white, 85%);
|
||||
|
||||
// Select
|
||||
// ---
|
||||
@select-background: transparent;
|
||||
@select-dropdown-bg: @popover-background;
|
||||
@select-clear-background: @component-background;
|
||||
@select-selection-item-bg: fade(@white, 8);
|
||||
@select-selection-item-border-color: @border-color-split;
|
||||
@select-multiple-disabled-background: @component-background;
|
||||
@select-multiple-item-disabled-color: #595959;
|
||||
@select-multiple-item-disabled-border-color: @popover-background;
|
||||
|
||||
// Cascader
|
||||
// ---
|
||||
@cascader-bg: transparent;
|
||||
@cascader-menu-bg: @popover-background;
|
||||
@cascader-menu-border-color-split: @border-color-split;
|
||||
|
||||
// Tooltip
|
||||
// ---
|
||||
// Tooltip background color
|
||||
@tooltip-bg: #434343;
|
||||
|
||||
// Menu
|
||||
// ---
|
||||
// dark theme
|
||||
@menu-dark-inline-submenu-bg: @component-background;
|
||||
@menu-dark-bg: @popover-background;
|
||||
@menu-popup-bg: @popover-background;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-bg: @popover-background;
|
||||
|
||||
// Notification
|
||||
@notification-bg: @popover-background;
|
||||
|
||||
// LINK
|
||||
@link-hover-color: @primary-5;
|
||||
@link-active-color: @primary-7;
|
||||
|
||||
// Table
|
||||
// --
|
||||
@table-header-bg: #1d1d1d;
|
||||
@table-body-sort-bg: fade(@white, 1%);
|
||||
@table-row-hover-bg: #262626;
|
||||
@table-header-cell-split-color: fade(@white, 8%);
|
||||
@table-header-sort-bg: #262626;
|
||||
@table-header-filter-active-bg: #434343;
|
||||
@table-header-sort-active-bg: #303030;
|
||||
@table-fixed-header-sort-active-bg: #222;
|
||||
@table-filter-btns-bg: @popover-background;
|
||||
@table-expanded-row-bg: @table-header-bg;
|
||||
@table-filter-dropdown-bg: @popover-background;
|
||||
@table-expand-icon-bg: transparent;
|
||||
|
||||
// Tag
|
||||
// ---
|
||||
@info-color-deprecated-bg: @primary-1;
|
||||
@info-color-deprecated-border: @primary-3;
|
||||
@success-color-deprecated-bg: @green-1;
|
||||
@success-color-deprecated-border: @green-3;
|
||||
@warning-color-deprecated-bg: @orange-1;
|
||||
@warning-color-deprecated-border: @orange-3;
|
||||
@error-color-deprecated-bg: @red-1;
|
||||
@error-color-deprecated-border: @red-3;
|
||||
|
||||
// TimePicker
|
||||
// ---
|
||||
@picker-basic-cell-hover-with-range-color: darken(@primary-color, 35%);
|
||||
@picker-basic-cell-disabled-bg: #303030;
|
||||
@picker-border-color: @border-color-split;
|
||||
@picker-bg: transparent;
|
||||
@picker-date-hover-range-border-color: darken(@primary-color, 20%);
|
||||
|
||||
// Dropdown
|
||||
// ---
|
||||
@dropdown-menu-bg: @popover-background;
|
||||
@dropdown-menu-submenu-disabled-bg: transparent;
|
||||
|
||||
// Steps
|
||||
// ---
|
||||
@steps-nav-arrow-color: fade(@white, 20%);
|
||||
@steps-background: transparent;
|
||||
|
||||
// Avatar
|
||||
// ---
|
||||
@avatar-bg: fade(@white, 30%);
|
||||
|
||||
// Progress
|
||||
// ---
|
||||
@progress-steps-item-bg: fade(@white, 8%);
|
||||
|
||||
// Calendar
|
||||
// ---
|
||||
@calendar-bg: @popover-background;
|
||||
@calendar-input-bg: @calendar-bg;
|
||||
@calendar-border-color: transparent;
|
||||
@calendar-full-bg: @component-background;
|
||||
|
||||
// Badge
|
||||
// ---
|
||||
@badge-text-color: @white;
|
||||
|
||||
// Popover
|
||||
@popover-bg: @popover-background;
|
||||
|
||||
// Drawer
|
||||
@drawer-bg: @popover-background;
|
||||
|
||||
// Card
|
||||
// ---
|
||||
@card-actions-background: @component-background;
|
||||
@card-skeleton-bg: #303030;
|
||||
@card-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.64), 0 3px 6px 0 rgba(0, 0, 0, 0.48),
|
||||
0 5px 12px 4px rgba(0, 0, 0, 0.36);
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-item-hover-bg: #262626;
|
||||
|
||||
// Comment
|
||||
// ---
|
||||
@comment-bg: transparent;
|
||||
@comment-author-time-color: fade(@white, 30%);
|
||||
@comment-action-hover-color: fade(@white, 65%);
|
||||
|
||||
// Rate
|
||||
// ---
|
||||
@rate-star-bg: fade(@white, 12%);
|
||||
|
||||
// Switch
|
||||
// ---
|
||||
@switch-bg: @white;
|
||||
|
||||
// Pagination
|
||||
// ---
|
||||
@pagination-item-bg: transparent;
|
||||
@pagination-item-bg-active: transparent;
|
||||
@pagination-item-link-bg: transparent;
|
||||
@pagination-item-disabled-bg-active: fade(@white, 25%);
|
||||
@pagination-item-disabled-color-active: @black;
|
||||
@pagination-item-input-bg: @pagination-item-bg;
|
||||
|
||||
// PageHeader
|
||||
// ---
|
||||
@page-header-back-color: @icon-color;
|
||||
@page-header-ghost-bg: transparent;
|
||||
|
||||
// Slider
|
||||
// ---
|
||||
@slider-rail-background-color: #262626;
|
||||
@slider-rail-background-color-hover: @border-color-base;
|
||||
@slider-dot-border-color: @border-color-split;
|
||||
@slider-dot-border-color-active: @primary-4;
|
||||
|
||||
// Skeleton
|
||||
// ---
|
||||
@skeleton-to-color: fade(@white, 16%);
|
||||
|
||||
// Alert
|
||||
// ---
|
||||
@alert-success-border-color: @green-3;
|
||||
@alert-success-bg-color: @green-1;
|
||||
@alert-success-icon-color: @success-color;
|
||||
@alert-info-border-color: @primary-3;
|
||||
@alert-info-bg-color: @primary-1;
|
||||
@alert-info-icon-color: @info-color;
|
||||
@alert-warning-border-color: @gold-3;
|
||||
@alert-warning-bg-color: @gold-1;
|
||||
@alert-warning-icon-color: @warning-color;
|
||||
@alert-error-border-color: @red-3;
|
||||
@alert-error-bg-color: @red-1;
|
||||
@alert-error-icon-color: @error-color;
|
||||
|
||||
// Timeline
|
||||
// ---
|
||||
@timeline-color: @border-color-split;
|
||||
@timeline-dot-color: @primary-color;
|
||||
|
||||
// Mentions
|
||||
// ---
|
||||
@mentions-dropdown-bg: @popover-background;
|
||||
|
||||
// Segmented
|
||||
// ---
|
||||
@segmented-bg: fade(@black, 25%);
|
||||
@segmented-hover-bg: fade(@black, 45%);
|
||||
@segmented-selected-bg: #333333;
|
||||
@segmented-label-color: fade(@white, 65%);
|
||||
@segmented-label-hover-color: fade(@white, 85%);
|
||||
1084
webapp/packages/supersonic-fe/src/assets/style/themes/default.less
Normal file
1084
webapp/packages/supersonic-fe/src/assets/style/themes/default.less
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
// Default using variable as entry to support site variable version
|
||||
// This will be replaced in webpack bundle
|
||||
// @root-entry-name: variable;
|
||||
|
||||
// @import './default.less';
|
||||
// @import './variable.less';
|
||||
@import './@{root-entry-name}.less';
|
||||
1139
webapp/packages/supersonic-fe/src/assets/style/themes/variable.less
Normal file
1139
webapp/packages/supersonic-fe/src/assets/style/themes/variable.less
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
@root-entry-name: variable;
|
||||
|
||||
@import './themes/variable.less';
|
||||
@import './core/index';
|
||||
@@ -0,0 +1,165 @@
|
||||
import { Space, Popconfirm, Dropdown, DatePicker, Popover, Button, Radio } from 'antd';
|
||||
import { FC, useState, useRef } from 'react';
|
||||
import {
|
||||
PlaySquareOutlined,
|
||||
StopOutlined,
|
||||
CloudDownloadOutlined,
|
||||
DeleteOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
export type BatchCtrlDropDownButtonProps = {
|
||||
onMenuClick?: (key: string) => void;
|
||||
onDownloadDateRangeChange?: (dateRange: string[], pickerType: string) => void;
|
||||
onDeleteConfirm?: () => void;
|
||||
downloadLoading?: boolean;
|
||||
disabledList?: string[];
|
||||
hiddenList?: string[];
|
||||
};
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
|
||||
onMenuClick,
|
||||
onDownloadDateRangeChange,
|
||||
onDeleteConfirm,
|
||||
downloadLoading,
|
||||
disabledList = [],
|
||||
hiddenList = [],
|
||||
}) => {
|
||||
const [popoverOpenState, setPopoverOpenState] = useState<boolean>(false);
|
||||
const [pickerType, setPickerType] = useState<string>('day');
|
||||
const dateRangeRef = useRef<any>([]);
|
||||
const dropdownButtonItems: any[] = [
|
||||
{
|
||||
key: 'batchStart',
|
||||
label: '批量启用',
|
||||
icon: <PlaySquareOutlined />,
|
||||
disabled: disabledList?.includes('batchStart'),
|
||||
},
|
||||
{
|
||||
key: 'batchStop',
|
||||
label: '批量停用',
|
||||
icon: <StopOutlined />,
|
||||
disabled: disabledList?.includes('batchStop'),
|
||||
},
|
||||
{
|
||||
key: 'batchDownload',
|
||||
label: (
|
||||
<a
|
||||
onClick={() => {
|
||||
setPopoverOpenState(true);
|
||||
}}
|
||||
>
|
||||
批量下载
|
||||
</a>
|
||||
),
|
||||
icon: <CloudDownloadOutlined />,
|
||||
disabled: disabledList?.includes('batchDownload'),
|
||||
},
|
||||
{
|
||||
key: 'batchDeleteDivider',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
key: 'batchDelete',
|
||||
label: (
|
||||
<Popconfirm
|
||||
title="确定批量删除吗?"
|
||||
onConfirm={() => {
|
||||
onDeleteConfirm?.();
|
||||
}}
|
||||
>
|
||||
<a>批量删除</a>
|
||||
</Popconfirm>
|
||||
),
|
||||
icon: <DeleteOutlined />,
|
||||
disabled: disabledList?.includes('batchDelete'),
|
||||
},
|
||||
].filter((item) => {
|
||||
return !hiddenList.includes(item.key);
|
||||
});
|
||||
|
||||
const popoverConfig = {
|
||||
title: '选择下载区间',
|
||||
content: (
|
||||
<Space direction="vertical">
|
||||
<Radio.Group
|
||||
size="small"
|
||||
value={pickerType}
|
||||
onChange={(e) => {
|
||||
setPickerType(e.target.value);
|
||||
}}
|
||||
>
|
||||
<Radio.Button value="day">按日</Radio.Button>
|
||||
<Radio.Button value="week">按周</Radio.Button>
|
||||
<Radio.Button value="month">按月</Radio.Button>
|
||||
</Radio.Group>
|
||||
<RangePicker
|
||||
style={{ paddingBottom: 5 }}
|
||||
onChange={(date) => {
|
||||
dateRangeRef.current = date;
|
||||
return;
|
||||
}}
|
||||
picker={pickerType as any}
|
||||
allowClear={true}
|
||||
/>
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={downloadLoading}
|
||||
onClick={() => {
|
||||
const [startMoment, endMoment] = dateRangeRef.current;
|
||||
let searchDateRange = [
|
||||
startMoment?.format('YYYY-MM-DD'),
|
||||
endMoment?.format('YYYY-MM-DD'),
|
||||
];
|
||||
if (pickerType === 'week') {
|
||||
searchDateRange = [
|
||||
startMoment?.startOf('isoWeek').format('YYYY-MM-DD'),
|
||||
endMoment?.startOf('isoWeek').format('YYYY-MM-DD'),
|
||||
];
|
||||
}
|
||||
if (pickerType === 'month') {
|
||||
searchDateRange = [
|
||||
startMoment?.startOf('month').format('YYYY-MM-DD'),
|
||||
endMoment?.startOf('month').format('YYYY-MM-DD'),
|
||||
];
|
||||
}
|
||||
onDownloadDateRangeChange?.(searchDateRange, pickerType);
|
||||
}}
|
||||
>
|
||||
下载
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</Space>
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={popoverConfig?.content}
|
||||
title={popoverConfig?.title}
|
||||
trigger="click"
|
||||
key="ctrlBtnList"
|
||||
open={popoverOpenState}
|
||||
placement="bottomLeft"
|
||||
onOpenChange={(open: boolean) => {
|
||||
setPopoverOpenState(open);
|
||||
}}
|
||||
>
|
||||
<Dropdown.Button
|
||||
menu={{
|
||||
items: dropdownButtonItems,
|
||||
onClick: ({ key }: { key: string }) => {
|
||||
onMenuClick?.(key);
|
||||
},
|
||||
}}
|
||||
>
|
||||
批量操作
|
||||
</Dropdown.Button>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default BatchCtrlDropDownButton;
|
||||
@@ -1,12 +1,13 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
|
||||
.container > * {
|
||||
background-color: @popover-bg;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: @shadow-1-down;
|
||||
box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.08), 0 9px 28px 0 rgba(0, 0, 0, 0.05),
|
||||
0 12px 48px 16px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs) {
|
||||
@media screen and (max-width: 480px) {
|
||||
.container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
30
webapp/packages/supersonic-fe/src/components/MStar/index.tsx
Normal file
30
webapp/packages/supersonic-fe/src/components/MStar/index.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { StarOutlined, StarFilled } from '@ant-design/icons';
|
||||
import styles from './style.less';
|
||||
|
||||
type Props = {
|
||||
star?: boolean;
|
||||
onToggleCollect: (star: boolean) => void;
|
||||
};
|
||||
|
||||
const MStar: React.FC<Props> = ({ star = false, onToggleCollect }) => {
|
||||
const [starState, setStarState] = useState(star);
|
||||
useEffect(() => {
|
||||
setStarState(star);
|
||||
}, [star]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.collectDashboard} ${starState === true ? 'dashboardCollected' : ''}`}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setStarState(!starState);
|
||||
onToggleCollect(!starState);
|
||||
}}
|
||||
>
|
||||
{starState === false ? <StarOutlined /> : <StarFilled style={{ color: '#eac54f' }} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MStar;
|
||||
@@ -0,0 +1,6 @@
|
||||
.collectDashboard {
|
||||
color: #546174;
|
||||
&.dashboardCollected {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = () => {
|
||||
<HeaderDropdown menu={{ items }} disabled={APP_TARGET === 'inner'}>
|
||||
<span className={`${styles.action} ${styles.account}`}>
|
||||
<TMEAvatar className={styles.avatar} size="small" staffName={currentUser.staffName} />
|
||||
<span className={cx(styles.name, 'anticon')}>{currentUser.staffName}</span>
|
||||
<span style={{ color: '#fff' }}>{currentUser.staffName}</span>
|
||||
</span>
|
||||
</HeaderDropdown>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
|
||||
@pro-header-hover-bg: rgba(0, 0, 0, 0.025);
|
||||
|
||||
@@ -26,15 +26,17 @@
|
||||
padding: 0 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
color: #fff;
|
||||
>span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
background: @pro-header-hover-bg;
|
||||
background: #296df3;
|
||||
}
|
||||
|
||||
|
||||
&:global(.opened) {
|
||||
background: @pro-header-hover-bg;
|
||||
}
|
||||
@@ -57,49 +59,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.action {
|
||||
.download {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.menuName {
|
||||
margin-left: 5px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #296df3;
|
||||
}
|
||||
|
||||
&:global(.opened) {
|
||||
background: #252a3d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actionIcon {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.tooltip {
|
||||
padding-top: 0 !important;
|
||||
font-size: 12px !important;
|
||||
|
||||
:global {
|
||||
.ant-tooltip-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-tooltip-inner {
|
||||
min-height: 0 !important;
|
||||
padding: 3px 6px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import Avatar from './AvatarDropdown';
|
||||
import { SettingOutlined } from '@ant-design/icons';
|
||||
import { getSystemConfig } from '@/services/user';
|
||||
import styles from './index.less';
|
||||
import cx from 'classnames';
|
||||
|
||||
export type SiderTheme = 'light' | 'dark';
|
||||
|
||||
@@ -21,27 +20,20 @@ const GlobalHeaderRight: React.FC = () => {
|
||||
}
|
||||
const { currentUser = {} } = initialState as any;
|
||||
|
||||
const { layout } = initialState.settings;
|
||||
let className = styles.right;
|
||||
|
||||
const querySystemConfig = async () => {
|
||||
const { code, data } = await getSystemConfig();
|
||||
if (code === 200) {
|
||||
const { admins } = data;
|
||||
if (admins.includes(currentUser?.staffName)) {
|
||||
if (Array.isArray(admins) && admins.includes(currentUser?.staffName)) {
|
||||
setHasSettingPermisson(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (layout === 'top' || layout === 'mix') {
|
||||
className = cx(styles.right, styles.dark);
|
||||
}
|
||||
|
||||
function handleLogin() {}
|
||||
|
||||
return (
|
||||
<Space className={className} style={{ marginRight: -8 }}>
|
||||
<Space className={styles.right}>
|
||||
<Avatar onClickLogin={handleLogin} />
|
||||
{hasSettingPermisson && (
|
||||
<span
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
.standardFormRow {
|
||||
display: flex;
|
||||
@@ -15,7 +14,7 @@
|
||||
.ant-legacy-form-item-label {
|
||||
label {
|
||||
margin-right: 0;
|
||||
color: @text-color;
|
||||
color: fade(#000, 85%);
|
||||
}
|
||||
}
|
||||
.ant-form-item-label,
|
||||
@@ -29,8 +28,8 @@
|
||||
.label {
|
||||
flex: 0 0 auto;
|
||||
margin-right: 12px;
|
||||
color: @heading-color;
|
||||
font-size: @font-size-base;
|
||||
color: fade(#000, 85%);
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
& > span {
|
||||
display: inline-block;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
.tagSelect {
|
||||
position: relative;
|
||||
@@ -12,7 +11,7 @@
|
||||
.ant-tag {
|
||||
margin-right: 24px;
|
||||
padding: 0 8px;
|
||||
font-size: @font-size-base;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
&.expanded {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
|
||||
:root:root {
|
||||
--primary-color: #f87653;
|
||||
@@ -30,6 +30,7 @@ body,
|
||||
height: 100%;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Microsoft YaHei,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
||||
-webkit-font-smoothing:antialiased;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.colorWeak {
|
||||
@@ -55,7 +56,7 @@ ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs) {
|
||||
@media (max-width: 480px) {
|
||||
.ant-table {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
@@ -111,26 +112,46 @@ ol {
|
||||
.ant-spin-spinning {
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.loadingPlaceholder {
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pro-layout .ant-pro-layout-content {
|
||||
padding: 0;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
|
||||
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,
|
||||
.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
|
||||
.ant-pro-top-nav-header-menu {
|
||||
padding: 0!important;
|
||||
line-height: unset!important;
|
||||
}
|
||||
|
||||
.ant-menu-root>.ant-menu-item,
|
||||
.ant-menu-root>.ant-menu-submenu {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
|
||||
&>span>a,
|
||||
&>a {
|
||||
color: white;
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: #296DF3!important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu-root>.ant-menu-item.ant-menu-item-selected {
|
||||
background-color: #296DF3!important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ant-pro-top-nav-header-logo h1 {
|
||||
@@ -143,63 +164,19 @@ ol {
|
||||
backdrop-filter: blur(10px) !important;
|
||||
}
|
||||
|
||||
.ant-menu.ant-menu-dark {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ant-menu-submenu-selected {
|
||||
background-color: #296DF3 !important;
|
||||
}
|
||||
|
||||
.ant-menu.ant-menu-dark .ant-menu-sub {
|
||||
background-color: #fff;
|
||||
.ant-menu-item-selected {
|
||||
background-color: #296DF3;
|
||||
.ant-pro-menu-item-title {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.ant-menu-item {
|
||||
&:hover {
|
||||
background-color: #e3e3e3;
|
||||
|
||||
.ant-menu-item-selected {
|
||||
background-color: #e3e3e3;
|
||||
.ant-pro-menu-item-title {
|
||||
color: #181a1a !important;
|
||||
}
|
||||
}
|
||||
.ant-pro-menu-item-title {
|
||||
color: #181a1a !important;
|
||||
}
|
||||
}
|
||||
& > span > a {
|
||||
color: #181a1a;
|
||||
&:hover {
|
||||
color: #181a1a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-menu-item:active {
|
||||
background: inherit
|
||||
}
|
||||
// .ant-menu-dark .ant-menu-item > span > a {
|
||||
// color: #181a1a;
|
||||
// &:hover {
|
||||
// color: #fff;
|
||||
// }
|
||||
// }
|
||||
// .ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||||
// // color: #fff;
|
||||
// background-color: #1b4aef;
|
||||
|
||||
// .ant-menu-submenu-selected {
|
||||
// background-color: #296DF3 !important;
|
||||
// }
|
||||
|
||||
.customizeHeader {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
|
||||
// .ant-menu-item:active {
|
||||
// background: inherit
|
||||
// }
|
||||
|
||||
|
||||
|
||||
.ant-pro-top-nav-header-main-left {
|
||||
min-width: 100px !important;
|
||||
@@ -210,64 +187,31 @@ ol {
|
||||
}
|
||||
|
||||
|
||||
.link {
|
||||
color: #296df3;
|
||||
cursor: pointer;
|
||||
}
|
||||
// .link {
|
||||
// color: #296df3;
|
||||
// cursor: pointer;
|
||||
// }
|
||||
|
||||
.closeTab {
|
||||
position: relative;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
// opacity: 0;
|
||||
}
|
||||
|
||||
.closeTab::before,
|
||||
.closeTab::after {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
background-color: rgb(50, 50, 50);
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
.closeTab::before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.closeTab::after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.dot {
|
||||
float: right;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #bfbfbf;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.bdWrapper {
|
||||
margin: -24px;
|
||||
.ant-layout-sider {
|
||||
top: 48px !important;
|
||||
}
|
||||
}
|
||||
// .dot {
|
||||
// float: right;
|
||||
// width: 8px;
|
||||
// height: 8px;
|
||||
// background: #bfbfbf;
|
||||
// border-radius: 100%;
|
||||
// }
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
padding-bottom: 5px;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.ant-notification-topRight {
|
||||
right: 240px !important;
|
||||
}
|
||||
// .ant-notification-topRight {
|
||||
// right: 240px !important;
|
||||
// }
|
||||
|
||||
|
||||
.g6ContextMenuContainer {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Form, Input, Spin, Select, message } from 'antd';
|
||||
import type { FormInstance } from 'antd/lib/form';
|
||||
import { getDbNames, getTables } from '../../service';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import { ISemantic } from '../../data';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
@@ -123,6 +124,13 @@ const DataSourceBasicForm: React.FC<Props> = ({ isEdit, databaseConfigList, mode
|
||||
<FormItem name="description" label="数据源描述">
|
||||
<TextArea placeholder="请输入数据源描述" />
|
||||
</FormItem>
|
||||
{/* <FormItem
|
||||
name="filterSql"
|
||||
label="过滤SQL"
|
||||
tooltip="主要用于词典导入场景, 对维度值进行过滤 格式: field1 = 'xxx' and field2 = 'yyy'"
|
||||
>
|
||||
<SqlEditor height={'150px'} />
|
||||
</FormItem> */}
|
||||
</Spin>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ export type CreateFormProps = {
|
||||
basicInfoFormMode?: 'normal' | 'fast';
|
||||
onDataBaseTableChange?: (tableName: string) => void;
|
||||
onDataSourceBtnClick?: () => void;
|
||||
// modalSolt: ReactNode;
|
||||
onOpenDataSourceEdit?: () => void;
|
||||
};
|
||||
const { Step } = Steps;
|
||||
|
||||
@@ -45,6 +45,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
databaseId,
|
||||
basicInfoFormMode,
|
||||
onDataSourceBtnClick,
|
||||
onOpenDataSourceEdit,
|
||||
children,
|
||||
}) => {
|
||||
const isEdit = !!dataSourceItem?.id;
|
||||
@@ -59,7 +60,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
const updateFormVal = (val: any) => {
|
||||
formValRef.current = val;
|
||||
};
|
||||
|
||||
const [sqlFilter, setSqlFilter] = useState<string>('');
|
||||
useEffect(() => {
|
||||
const hasEmpty = fields.some((item) => {
|
||||
const { name, isCreateDimension, isCreateMetric } = item;
|
||||
@@ -170,6 +171,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
|
||||
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
|
||||
modelId: isEdit ? dataSourceItem.modelId : modelId,
|
||||
filterSql: sqlFilter,
|
||||
};
|
||||
const queryDatasource = isEdit ? updateDatasource : createDatasource;
|
||||
const { code, msg, data } = await queryDatasource(queryParams);
|
||||
@@ -221,7 +223,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
const initData = async () => {
|
||||
const { queryType, tableQuery } = dataSourceItem.datasourceDetail;
|
||||
let tableQueryInitValue = {};
|
||||
let columns = fieldColumns;
|
||||
let columns = fieldColumns || [];
|
||||
if (queryType === 'table_query') {
|
||||
const tableQueryString = tableQuery || '';
|
||||
const [dbName, tableName] = tableQueryString.split('.');
|
||||
@@ -235,7 +237,8 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
};
|
||||
|
||||
const formatterInitData = (columns: any[], extendParams: Record<string, any> = {}) => {
|
||||
const { id, name, bizName, description, datasourceDetail, databaseId } = dataSourceItem as any;
|
||||
const { id, name, bizName, description, datasourceDetail, databaseId, filterSql } =
|
||||
dataSourceItem as any;
|
||||
const { dimensions, identifiers, measures } = datasourceDetail;
|
||||
const initValue = {
|
||||
id,
|
||||
@@ -243,6 +246,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
bizName,
|
||||
description,
|
||||
databaseId,
|
||||
filterSql,
|
||||
...extendParams,
|
||||
// ...tableQueryInitValue,
|
||||
};
|
||||
@@ -250,6 +254,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
...formValRef.current,
|
||||
...initValue,
|
||||
};
|
||||
setSqlFilter(filterSql);
|
||||
updateFormVal(editInitFormVal);
|
||||
form.setFieldsValue(initValue);
|
||||
const formatFields = [
|
||||
@@ -261,10 +266,24 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isEdit) {
|
||||
initData();
|
||||
} else {
|
||||
initFields([], fieldColumns);
|
||||
const { queryType } = dataSourceItem?.datasourceDetail || {};
|
||||
if (queryType === 'table_query') {
|
||||
if (isEdit) {
|
||||
initData();
|
||||
} else {
|
||||
initFields([], fieldColumns);
|
||||
}
|
||||
}
|
||||
}, [dataSourceItem]);
|
||||
|
||||
useEffect(() => {
|
||||
const { queryType } = dataSourceItem?.datasourceDetail || {};
|
||||
if (queryType !== 'table_query') {
|
||||
if (isEdit) {
|
||||
initData();
|
||||
} else {
|
||||
initFields([], fieldColumns);
|
||||
}
|
||||
}
|
||||
}, [dataSourceItem, fieldColumns]);
|
||||
|
||||
@@ -306,7 +325,14 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: currentStep === 1 ? 'block' : 'none' }}>
|
||||
<FieldForm fields={fields} onFieldChange={handleFieldChange} />
|
||||
<FieldForm
|
||||
fields={fields}
|
||||
onFieldChange={handleFieldChange}
|
||||
onSqlChange={(sql) => {
|
||||
setSqlFilter(sql);
|
||||
}}
|
||||
sql={sqlFilter}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: currentStep !== 1 ? 'block' : 'none' }}>
|
||||
<DataSourceBasicForm
|
||||
@@ -357,6 +383,9 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
handleNext();
|
||||
if (!isEdit && Array.isArray(fields) && fields.length === 0) {
|
||||
onOpenDataSourceEdit?.();
|
||||
}
|
||||
}}
|
||||
>
|
||||
下一步
|
||||
@@ -381,7 +410,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
<Modal
|
||||
forceRender
|
||||
width={1300}
|
||||
bodyStyle={{ padding: '32px 40px 48px' }}
|
||||
styles={{ padding: '32px 40px 48px' }}
|
||||
destroyOnClose
|
||||
title={`${isEdit ? '编辑' : '新建'}数据源`}
|
||||
maskClosable={false}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Table, Select, Checkbox, Input, Alert, Space, Tooltip } from 'antd';
|
||||
import { Table, Select, Checkbox, Input, Alert, Space, Tooltip, Form } from 'antd';
|
||||
import TableTitleTooltips from '../../components/TableTitleTooltips';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import Marquee from 'react-fast-marquee';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import {
|
||||
TYPE_OPTIONS,
|
||||
DATE_FORMATTER,
|
||||
@@ -24,7 +24,11 @@ type FieldItem = {
|
||||
timeGranularity?: string;
|
||||
};
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
type Props = {
|
||||
onSqlChange: (sql: string) => void;
|
||||
sql: string;
|
||||
fields: FieldItem[];
|
||||
onFieldChange: (fieldName: string, data: Partial<FieldItem>) => void;
|
||||
};
|
||||
@@ -41,7 +45,7 @@ const getCreateFieldName = (type: EnumDataSourceType) => {
|
||||
// const editState = !isUndefined(record[isCreateName]) ? !!record[isCreateName] : true;
|
||||
};
|
||||
|
||||
const FieldForm: React.FC<Props> = ({ fields, onFieldChange }) => {
|
||||
const FieldForm: React.FC<Props> = ({ fields, sql, onFieldChange, onSqlChange }) => {
|
||||
const handleFieldChange = (record: FieldItem, fieldName: string, value: any) => {
|
||||
onFieldChange(record.bizName, {
|
||||
...record,
|
||||
@@ -271,6 +275,14 @@ const FieldForm: React.FC<Props> = ({ fields, onFieldChange }) => {
|
||||
pagination={false}
|
||||
scroll={{ y: 500 }}
|
||||
/>
|
||||
<FormItem
|
||||
style={{ marginTop: 40, marginBottom: 60 }}
|
||||
name="filterSql"
|
||||
label={<span style={{ fontSize: 14 }}>过滤SQL</span>}
|
||||
tooltip="主要用于词典导入场景, 对维度值进行过滤 格式: field1 = 'xxx' and field2 = 'yyy'"
|
||||
>
|
||||
<SqlEditor height={'150px'} value={sql} onChange={onSqlChange} />
|
||||
</FormItem>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import MetricTrendSection from '@/pages/SemanticModel/Metric/components/MetricTr
|
||||
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_COLOR } from '../constant';
|
||||
import type { TabsProps } from 'antd';
|
||||
import { ISemantic } from '../data';
|
||||
import MetricStar from './components/MetricStar';
|
||||
|
||||
const { Content } = Layout;
|
||||
type Props = {
|
||||
@@ -31,20 +32,6 @@ interface DescriptionItemProps {
|
||||
icon: ReactNode;
|
||||
}
|
||||
|
||||
// type InfoListItemChildrenItem = {
|
||||
// label: string;
|
||||
// value: string;
|
||||
// content?: ReactNode;
|
||||
// hideItem?: boolean;
|
||||
// };
|
||||
|
||||
// type InfoListItem = {
|
||||
// title: string;
|
||||
// hideItem?: boolean;
|
||||
// render?: () => ReactNode;
|
||||
// children?: InfoListItemChildrenItem[];
|
||||
// };
|
||||
|
||||
const DescriptionItem = ({ title, content, icon }: DescriptionItemProps) => (
|
||||
<Tooltip title={title}>
|
||||
<div style={{ width: 'max-content', fontSize: 14, color: '#546174' }}>
|
||||
@@ -59,10 +46,7 @@ const DescriptionItem = ({ title, content, icon }: DescriptionItemProps) => (
|
||||
const MetricDetail: React.FC<Props> = ({ domainManger }) => {
|
||||
const params: any = useParams();
|
||||
const metricId = params.metricId;
|
||||
// const bizName = params.bizName;
|
||||
|
||||
// const [infoList, setInfoList] = useState<InfoListItem[]>([]);
|
||||
// const { selectModelName } = domainManger;
|
||||
const [metircData, setMetircData] = useState<ISemantic.IMetricItem>();
|
||||
useEffect(() => {
|
||||
queryMetricData(metricId);
|
||||
@@ -77,112 +61,20 @@ const MetricDetail: React.FC<Props> = ({ domainManger }) => {
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!metircData) {
|
||||
// return;
|
||||
// }
|
||||
// const {
|
||||
// alias,
|
||||
// bizName,
|
||||
// createdBy,
|
||||
// createdAt,
|
||||
// updatedAt,
|
||||
// description,
|
||||
// sensitiveLevel,
|
||||
// modelName,
|
||||
// } = metircData;
|
||||
|
||||
// const list = [
|
||||
// {
|
||||
// title: '基本信息',
|
||||
// children: [
|
||||
// {
|
||||
// label: '字段名称',
|
||||
// value: bizName,
|
||||
// },
|
||||
// {
|
||||
// label: '别名',
|
||||
// hideItem: !alias,
|
||||
// value: alias || '-',
|
||||
// },
|
||||
// {
|
||||
// label: '所属模型',
|
||||
// value: modelName,
|
||||
// content: <Tag>{modelName || selectModelName}</Tag>,
|
||||
// },
|
||||
|
||||
// {
|
||||
// label: '描述',
|
||||
// value: description,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// title: '应用信息',
|
||||
// children: [
|
||||
// {
|
||||
// label: '敏感度',
|
||||
// value: SENSITIVE_LEVEL_ENUM[sensitiveLevel],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// // {
|
||||
// // title: '指标趋势',
|
||||
// // render: () => (
|
||||
// // <Row key={`metricTrendSection`} style={{ marginBottom: 10, display: 'flex' }}>
|
||||
// // <Col span={24}>
|
||||
// // <MetricTrendSection nodeData={metircData} />
|
||||
// // </Col>
|
||||
// // </Row>
|
||||
// // ),
|
||||
// // },
|
||||
// {
|
||||
// title: '创建信息',
|
||||
// children: [
|
||||
// {
|
||||
// label: '创建人',
|
||||
// value: createdBy,
|
||||
// },
|
||||
// {
|
||||
// label: '创建时间',
|
||||
// value: createdAt ? moment(createdAt).format('YYYY-MM-DD HH:mm:ss') : '',
|
||||
// },
|
||||
// {
|
||||
// label: '更新时间',
|
||||
// value: updatedAt ? moment(updatedAt).format('YYYY-MM-DD HH:mm:ss') : '',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ];
|
||||
|
||||
// setInfoList(list);
|
||||
// }, [metircData]);
|
||||
|
||||
const tabItems: TabsProps['items'] = [
|
||||
{
|
||||
key: 'metricTrend',
|
||||
label: '图表',
|
||||
children: <MetricTrendSection metircData={metircData} />,
|
||||
},
|
||||
// {
|
||||
// key: '2',
|
||||
// label: 'Tab 2',
|
||||
// children: 'Content of Tab Pane 2',
|
||||
// },
|
||||
];
|
||||
|
||||
const contentStyle: React.CSSProperties = {
|
||||
minHeight: 120,
|
||||
color: '#fff',
|
||||
// marginRight: 15,
|
||||
backgroundColor: '#fff',
|
||||
};
|
||||
|
||||
// const siderStyle: React.CSSProperties = {
|
||||
// width: '300px',
|
||||
// backgroundColor: '#fff',
|
||||
// };
|
||||
|
||||
return (
|
||||
<Layout className={styles.metricDetail}>
|
||||
<Layout>
|
||||
@@ -200,20 +92,21 @@ const MetricDetail: React.FC<Props> = ({ domainManger }) => {
|
||||
|
||||
<div className={styles.navContainer}>
|
||||
<Space>
|
||||
<MetricStar metricId={metricId} initState={metircData?.isCollect} />
|
||||
<span style={{ color: '#296DF3' }}>
|
||||
{metircData?.name}
|
||||
{metircData?.alias && `[${metircData.alias}]`}
|
||||
</span>
|
||||
{metircData?.name && (
|
||||
<>
|
||||
<span style={{ position: 'relative', top: '-2px' }}> | </span>
|
||||
<span style={{ position: 'relative', top: '-2px', color: '#c3c3c3' }}>|</span>
|
||||
<span style={{ fontSize: 16, color: '#296DF3' }}>{metircData?.bizName}</span>
|
||||
</>
|
||||
)}
|
||||
{metircData?.sensitiveLevel !== undefined && (
|
||||
<span style={{ position: 'relative', top: '-2px' }}>
|
||||
<Tag color={SENSITIVE_LEVEL_COLOR[metircData.sensitiveLevel]}>
|
||||
{SENSITIVE_LEVEL_ENUM[metircData.sensitiveLevel]}敏感度
|
||||
{SENSITIVE_LEVEL_ENUM[metircData.sensitiveLevel]}
|
||||
</Tag>
|
||||
</span>
|
||||
)}
|
||||
@@ -235,19 +128,6 @@ const MetricDetail: React.FC<Props> = ({ domainManger }) => {
|
||||
<div className={styles.titleRight}>
|
||||
{metircData?.createdBy ? (
|
||||
<>
|
||||
{/* <div className={styles.info}>
|
||||
<DescriptionItem
|
||||
title="所属模型"
|
||||
icon={<UserOutlined />}
|
||||
content={metircData?.modelName}
|
||||
/>
|
||||
|
||||
<DescriptionItem
|
||||
title="更新时间"
|
||||
icon={<CalendarOutlined />}
|
||||
content={metircData?.description}
|
||||
/>
|
||||
</div> */}
|
||||
<div className={styles.info}>
|
||||
<DescriptionItem
|
||||
title="创建人"
|
||||
@@ -272,41 +152,6 @@ const MetricDetail: React.FC<Props> = ({ domainManger }) => {
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
{/* <Sider style={siderStyle} width={400}>
|
||||
<>
|
||||
<div key={metircData?.id} className={styles.metricInfoContent}>
|
||||
{infoList.map((item) => {
|
||||
const { children, title, render } = item;
|
||||
return (
|
||||
<div key={title} style={{ display: item.hideItem ? 'none' : 'block' }}>
|
||||
<p className={styles.title}>{title}</p>
|
||||
{render?.() ||
|
||||
(Array.isArray(children) &&
|
||||
children.map((childrenItem) => {
|
||||
return (
|
||||
<Row
|
||||
key={`${childrenItem.label}-${childrenItem.value}`}
|
||||
style={{
|
||||
marginBottom: 10,
|
||||
display: childrenItem.hideItem ? 'none' : 'flex',
|
||||
}}
|
||||
>
|
||||
<Col span={24}>
|
||||
<DescriptionItem
|
||||
title={childrenItem.label}
|
||||
content={childrenItem.content || childrenItem.value}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}))}
|
||||
<Divider />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
</Sider> */}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-table';
|
||||
import ProTable from '@ant-design/pro-table';
|
||||
import {
|
||||
message,
|
||||
Space,
|
||||
Popconfirm,
|
||||
Tag,
|
||||
Spin,
|
||||
Dropdown,
|
||||
DatePicker,
|
||||
Popover,
|
||||
Button,
|
||||
Radio,
|
||||
} from 'antd';
|
||||
import { message, Space, Popconfirm, Tag, Spin, Tooltip } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect, history, useModel } from 'umi';
|
||||
@@ -28,23 +17,17 @@ import MetricInfoCreateForm from '../components/MetricInfoCreateForm';
|
||||
import MetricCardList from './components/MetricCardList';
|
||||
import NodeInfoDrawer from '../SemanticGraph/components/NodeInfoDrawer';
|
||||
import { SemanticNodeType, StatusEnum } from '../enum';
|
||||
import moment, { Moment } from 'moment';
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
import { ISemantic } from '../data';
|
||||
import {
|
||||
PlaySquareOutlined,
|
||||
StopOutlined,
|
||||
CloudDownloadOutlined,
|
||||
DeleteOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import MetricStar from './components/MetricStar';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
type QueryMetricListParams = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
@@ -58,7 +41,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { initialState = {} } = useModel('@@initialState');
|
||||
|
||||
const { currentUser = {} } = initialState as any;
|
||||
|
||||
const { selectDomainId, selectModelId: modelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const defaultPagination = {
|
||||
@@ -75,10 +57,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
showType: localStorage.getItem('metricMarketShowType') === '1' ? true : false,
|
||||
});
|
||||
const [infoDrawerVisible, setInfoDrawerVisible] = useState<boolean>(false);
|
||||
const [popoverOpenState, setPopoverOpenState] = useState<boolean>(false);
|
||||
const [pickerType, setPickerType] = useState<string>('day');
|
||||
|
||||
const dateRangeRef = useRef<any>([]);
|
||||
const [downloadLoading, setDownloadLoading] = useState<boolean>(false);
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
@@ -152,7 +131,11 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const downloadMetricQuery = async (ids: React.Key[], dateStringList: string[]) => {
|
||||
const downloadMetricQuery = async (
|
||||
ids: React.Key[],
|
||||
dateStringList: string[],
|
||||
pickerType: string,
|
||||
) => {
|
||||
if (Array.isArray(ids) && ids.length > 0) {
|
||||
setDownloadLoading(true);
|
||||
const [startDate, endDate] = dateStringList;
|
||||
@@ -166,7 +149,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
},
|
||||
});
|
||||
setDownloadLoading(false);
|
||||
setPopoverOpenState(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,14 +166,18 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
dataIndex: 'name',
|
||||
title: '指标名称',
|
||||
render: (_, record: any) => {
|
||||
const { id, isCollect } = record;
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
history.push(`/metric/detail/${record.id}`);
|
||||
}}
|
||||
>
|
||||
{record.name}
|
||||
</a>
|
||||
<Space>
|
||||
<MetricStar metricId={id} initState={isCollect} />
|
||||
<a
|
||||
onClick={() => {
|
||||
history.push(`/metric/detail/${record.id}`);
|
||||
}}
|
||||
>
|
||||
{record.name}
|
||||
</a>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -343,43 +329,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
}),
|
||||
};
|
||||
|
||||
const dropdownButtonItems: any[] = [
|
||||
{
|
||||
key: 'batchStart',
|
||||
label: '批量启用',
|
||||
icon: <PlaySquareOutlined />,
|
||||
},
|
||||
{
|
||||
key: 'batchStop',
|
||||
label: '批量停用',
|
||||
icon: <StopOutlined />,
|
||||
},
|
||||
{
|
||||
key: 'batchDownload',
|
||||
// label: '批量下载',
|
||||
label: <a>批量下载</a>,
|
||||
icon: <CloudDownloadOutlined />,
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
key: 'batchDelete',
|
||||
label: (
|
||||
<Popconfirm
|
||||
title="确定批量删除吗?"
|
||||
onConfirm={() => {
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.DELETED);
|
||||
}}
|
||||
>
|
||||
<a>批量删除</a>
|
||||
</Popconfirm>
|
||||
),
|
||||
icon: <DeleteOutlined />,
|
||||
},
|
||||
];
|
||||
|
||||
const onMenuClick = ({ key }: { key: string }) => {
|
||||
const onMenuClick = (key: string) => {
|
||||
switch (key) {
|
||||
case 'batchStart':
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.ONLINE);
|
||||
@@ -387,69 +337,11 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
case 'batchStop':
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.OFFLINE);
|
||||
break;
|
||||
case 'batchDownload':
|
||||
setPopoverOpenState(true);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
const popoverConfig = {
|
||||
title: '选择下载区间',
|
||||
content: (
|
||||
<Space direction="vertical">
|
||||
<Radio.Group
|
||||
size="small"
|
||||
value={pickerType}
|
||||
onChange={(e) => {
|
||||
setPickerType(e.target.value);
|
||||
}}
|
||||
>
|
||||
<Radio.Button value="day">按日</Radio.Button>
|
||||
<Radio.Button value="week">按周</Radio.Button>
|
||||
<Radio.Button value="month">按月</Radio.Button>
|
||||
</Radio.Group>
|
||||
<RangePicker
|
||||
style={{ paddingBottom: 5 }}
|
||||
onChange={(date) => {
|
||||
dateRangeRef.current = date;
|
||||
return;
|
||||
}}
|
||||
picker={pickerType as any}
|
||||
allowClear={true}
|
||||
/>
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={downloadLoading}
|
||||
onClick={() => {
|
||||
const [startMoment, endMoment] = dateRangeRef.current;
|
||||
let searchDateRange = [
|
||||
startMoment?.format('YYYY-MM-DD'),
|
||||
endMoment?.format('YYYY-MM-DD'),
|
||||
];
|
||||
if (pickerType === 'week') {
|
||||
searchDateRange = [
|
||||
startMoment?.startOf('isoWeek').format('YYYY-MM-DD'),
|
||||
endMoment?.startOf('isoWeek').format('YYYY-MM-DD'),
|
||||
];
|
||||
}
|
||||
if (pickerType === 'month') {
|
||||
searchDateRange = [
|
||||
startMoment?.startOf('month').format('YYYY-MM-DD'),
|
||||
endMoment?.startOf('month').format('YYYY-MM-DD'),
|
||||
];
|
||||
}
|
||||
downloadMetricQuery(selectedRowKeys, searchDateRange);
|
||||
}}
|
||||
>
|
||||
下载
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</Space>
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.metricFilterWrapper}>
|
||||
@@ -499,21 +391,17 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
...rowSelection,
|
||||
}}
|
||||
toolBarRender={() => [
|
||||
<Popover
|
||||
content={popoverConfig?.content}
|
||||
title={popoverConfig?.title}
|
||||
trigger="click"
|
||||
<BatchCtrlDropDownButton
|
||||
key="ctrlBtnList"
|
||||
open={popoverOpenState}
|
||||
placement="bottomLeft"
|
||||
onOpenChange={(open: boolean) => {
|
||||
setPopoverOpenState(open);
|
||||
downloadLoading={downloadLoading}
|
||||
onDeleteConfirm={() => {
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.DELETED);
|
||||
}}
|
||||
>
|
||||
<Dropdown.Button menu={{ items: dropdownButtonItems, onClick: onMenuClick }}>
|
||||
批量操作
|
||||
</Dropdown.Button>
|
||||
</Popover>,
|
||||
onMenuClick={onMenuClick}
|
||||
onDownloadDateRangeChange={(searchDateRange, pickerType) => {
|
||||
downloadMetricQuery(selectedRowKeys, searchDateRange, pickerType);
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
loading={loading}
|
||||
onChange={(data: any) => {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Tooltip, message } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { metricStarState } from '../../service';
|
||||
import MStar from '@/components/MStar';
|
||||
|
||||
type Props = {
|
||||
metricId: number;
|
||||
initState?: boolean;
|
||||
onChange?: (state: boolean) => void;
|
||||
};
|
||||
|
||||
const MetricStar: React.FC<Props> = ({ metricId, initState = false }) => {
|
||||
const [star, setStar] = useState<boolean>(initState);
|
||||
|
||||
const starStateChange = async (id: number, state: boolean) => {
|
||||
const { code, msg } = await metricStarState({ id, state });
|
||||
if (code === 200) {
|
||||
setStar(state);
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip title={`${star ? '取消' : '加入'}收藏`}>
|
||||
<div>
|
||||
<MStar
|
||||
star={star}
|
||||
onToggleCollect={(star: boolean) => {
|
||||
starStateChange(metricId, star);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricStar;
|
||||
@@ -120,7 +120,8 @@
|
||||
height: calc(100vh - 50px);
|
||||
.title {
|
||||
margin-bottom: 0;
|
||||
// padding: 20px;
|
||||
margin-top:0;
|
||||
background-color: #fff;
|
||||
font-size: 20px;
|
||||
line-height: 34px;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
|
||||
@@ -203,7 +203,7 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
<Helmet title={'语义模型-超音数'} />
|
||||
<div className={styles.projectManger}>
|
||||
<div className={styles.sider}>
|
||||
<div className={styles.domainTitle}>
|
||||
{/* <div className={styles.domainTitle}>
|
||||
<Space>
|
||||
{selectDomainName ? `${selectDomainName}` : '主题域信息'}
|
||||
{selectModelName && (
|
||||
@@ -213,7 +213,7 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
</>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
</div> */}
|
||||
<DomainListTree
|
||||
createDomainBtnVisible={mode === 'domain' ? true : false}
|
||||
onTreeSelected={(domainData) => {
|
||||
|
||||
@@ -118,7 +118,7 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
cover={
|
||||
<CoffeeOutlined
|
||||
width={240}
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
style={{ paddingTop: '45px', height: 75, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -137,7 +137,7 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
style={{ height: 220 }}
|
||||
cover={
|
||||
<ConsoleSqlOutlined
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
style={{ paddingTop: '45px', height: 75, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -185,6 +185,9 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
onDataSourceBtnClick={() => {
|
||||
setDataSourceEditOpen(true);
|
||||
}}
|
||||
onOpenDataSourceEdit={() => {
|
||||
setDataSourceEditOpen(true);
|
||||
}}
|
||||
>
|
||||
<Drawer
|
||||
width={'100%'}
|
||||
|
||||
@@ -18,6 +18,7 @@ import DimensionValueSettingModal from './DimensionValueSettingModal';
|
||||
import { updateDimension } from '../service';
|
||||
import { ISemantic, IDataSource } from '../data';
|
||||
import moment from 'moment';
|
||||
import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import styles from './style.less';
|
||||
|
||||
type Props = {
|
||||
@@ -328,7 +329,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
},
|
||||
];
|
||||
|
||||
const onMenuClick = ({ key }: { key: string }) => {
|
||||
const onMenuClick = (key: string) => {
|
||||
switch (key) {
|
||||
case 'batchStart':
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.ONLINE);
|
||||
@@ -386,12 +387,14 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
>
|
||||
创建维度
|
||||
</Button>,
|
||||
<Dropdown.Button
|
||||
<BatchCtrlDropDownButton
|
||||
key="ctrlBtnList"
|
||||
menu={{ items: dropdownButtonItems, onClick: onMenuClick }}
|
||||
>
|
||||
批量操作
|
||||
</Dropdown.Button>,
|
||||
onDeleteConfirm={() => {
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.DELETED);
|
||||
}}
|
||||
hiddenList={['batchDownload']}
|
||||
onMenuClick={onMenuClick}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-table';
|
||||
import ProTable from '@ant-design/pro-table';
|
||||
import { message, Button, Space, Popconfirm, Input, Tag, Dropdown } from 'antd';
|
||||
import { message, Button, Space, Popconfirm, Input, Tag } from 'antd';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { StatusEnum } from '../enum';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { SENSITIVE_LEVEL_ENUM } from '../constant';
|
||||
import { queryMetric, deleteMetric, updateExprMetric, batchUpdateMetricStatus } from '../service';
|
||||
import {
|
||||
queryMetric,
|
||||
deleteMetric,
|
||||
batchUpdateMetricStatus,
|
||||
batchDownloadMetric,
|
||||
} from '../service';
|
||||
|
||||
import MetricInfoCreateForm from './MetricInfoCreateForm';
|
||||
|
||||
import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
import { ISemantic } from '../data';
|
||||
@@ -32,20 +37,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
});
|
||||
const actionRef = useRef<ActionType>();
|
||||
|
||||
const updateStatus = async (data: ISemantic.IMetricItem) => {
|
||||
const { code, msg } = await updateExprMetric(data);
|
||||
if (code === 200) {
|
||||
actionRef?.current?.reload();
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
const [downloadLoading, setDownloadLoading] = useState<boolean>(false);
|
||||
|
||||
const queryBatchUpdateStatus = async (ids: React.Key[], status: StatusEnum) => {
|
||||
if (Array.isArray(ids) && ids.length === 0) {
|
||||
@@ -268,31 +260,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
},
|
||||
};
|
||||
|
||||
const dropdownButtonItems = [
|
||||
{
|
||||
key: 'batchStart',
|
||||
label: '批量启用',
|
||||
},
|
||||
{
|
||||
key: 'batchStop',
|
||||
label: '批量停用',
|
||||
},
|
||||
{
|
||||
key: 'batchDelete',
|
||||
label: (
|
||||
<Popconfirm
|
||||
title="确定批量删除吗?"
|
||||
onConfirm={() => {
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.DELETED);
|
||||
}}
|
||||
>
|
||||
<a>批量删除</a>
|
||||
</Popconfirm>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const onMenuClick = ({ key }: { key: string }) => {
|
||||
const onMenuClick = (key: string) => {
|
||||
switch (key) {
|
||||
case 'batchStart':
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.ONLINE);
|
||||
@@ -305,6 +273,27 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const downloadMetricQuery = async (
|
||||
ids: React.Key[],
|
||||
dateStringList: string[],
|
||||
pickerType: string,
|
||||
) => {
|
||||
if (Array.isArray(ids) && ids.length > 0) {
|
||||
setDownloadLoading(true);
|
||||
const [startDate, endDate] = dateStringList;
|
||||
await batchDownloadMetric({
|
||||
metricIds: ids,
|
||||
dateInfo: {
|
||||
dateMode: 'BETWEEN',
|
||||
startDate,
|
||||
endDate,
|
||||
period: pickerType.toUpperCase(),
|
||||
},
|
||||
});
|
||||
setDownloadLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProTable
|
||||
@@ -350,12 +339,17 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
>
|
||||
创建指标
|
||||
</Button>,
|
||||
<Dropdown.Button
|
||||
<BatchCtrlDropDownButton
|
||||
key="ctrlBtnList"
|
||||
menu={{ items: dropdownButtonItems, onClick: onMenuClick }}
|
||||
>
|
||||
批量操作
|
||||
</Dropdown.Button>,
|
||||
downloadLoading={downloadLoading}
|
||||
onDeleteConfirm={() => {
|
||||
queryBatchUpdateStatus(selectedRowKeys, StatusEnum.DELETED);
|
||||
}}
|
||||
onMenuClick={onMenuClick}
|
||||
onDownloadDateRangeChange={(searchDateRange, pickerType) => {
|
||||
downloadMetricQuery(selectedRowKeys, searchDateRange, pickerType);
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
{createModalVisible && (
|
||||
|
||||
@@ -179,32 +179,33 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
|
||||
return (
|
||||
<div className={styles.domainList}>
|
||||
<Row>
|
||||
<Col flex="1 1 auto">
|
||||
{/* <Space> */}
|
||||
<Search
|
||||
allowClear
|
||||
className={styles.search}
|
||||
placeholder="请输入主题域名称进行查询"
|
||||
onSearch={onSearch}
|
||||
/>
|
||||
{/* </Space> */}
|
||||
</Col>
|
||||
{createDomainBtnVisible && (
|
||||
<Col flex="0 0 40px" style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Tooltip title="新增顶级域">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setProjectInfoParams({ type: 'top', modelType: 'add' });
|
||||
setProjectInfoModalVisible(true);
|
||||
onCreateDomainBtnClick?.();
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
{/* <Tooltip title="新增顶级域">
|
||||
<div className={styles.searchContainer}>
|
||||
<Row>
|
||||
<Col flex="1 1 auto">
|
||||
{/* <Space> */}
|
||||
<Search
|
||||
allowClear
|
||||
className={styles.search}
|
||||
placeholder="请输入主题域名称进行查询"
|
||||
onSearch={onSearch}
|
||||
/>
|
||||
{/* </Space> */}
|
||||
</Col>
|
||||
{createDomainBtnVisible && (
|
||||
<Col flex="0 0 40px" style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Tooltip title="新增顶级域">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setProjectInfoParams({ type: 'top', modelType: 'add' });
|
||||
setProjectInfoModalVisible(true);
|
||||
onCreateDomainBtnClick?.();
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
{/* <Tooltip title="新增顶级域">
|
||||
<PlusCircleOutlined
|
||||
onClick={() => {
|
||||
setProjectInfoParams({ type: 'top', modelType: 'add' });
|
||||
@@ -214,10 +215,10 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
className={styles.addBtn}
|
||||
/>
|
||||
</Tooltip> */}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
<Tree
|
||||
expandedKeys={expandedKeys}
|
||||
onExpand={handleExpand}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tabs, Button } from 'antd';
|
||||
import { Tabs, Breadcrumb, Space } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
import { connect, history } from 'umi';
|
||||
|
||||
import ClassDataSourceTable from './ClassDataSourceTable';
|
||||
import ClassDimensionTable from './ClassDimensionTable';
|
||||
@@ -11,7 +11,7 @@ import ChatSettingSection from '../ChatSetting/ChatSettingSection';
|
||||
import OverView from './OverView';
|
||||
import styles from './style.less';
|
||||
import type { StateType } from '../model';
|
||||
import { LeftOutlined } from '@ant-design/icons';
|
||||
import { HomeOutlined, FundViewOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from '../data';
|
||||
import SemanticGraphCanvas from '../SemanticGraphCanvas';
|
||||
import RecommendedQuestionsSection from '../components/Entity/RecommendedQuestionsSection';
|
||||
@@ -39,7 +39,9 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
onMenuChange,
|
||||
}) => {
|
||||
const defaultTabKey = 'xflow';
|
||||
const { selectDomainId, domainList, selectModelId } = domainManger;
|
||||
const { selectDomainId, domainList, selectModelId, selectModelName, selectDomainName } =
|
||||
domainManger;
|
||||
|
||||
const tabItem = [
|
||||
{
|
||||
label: '模型管理',
|
||||
@@ -126,40 +128,49 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Breadcrumb
|
||||
className={styles.breadcrumb}
|
||||
separator=""
|
||||
items={[
|
||||
{
|
||||
path: `/webapp/model/${selectDomainId}/0/overview`,
|
||||
title: (
|
||||
<Space
|
||||
onClick={() => {
|
||||
onBackDomainBtnClick?.();
|
||||
}}
|
||||
style={selectModelName ? {} : { color: '#296df3', fontWeight: 'bold' }}
|
||||
>
|
||||
<HomeOutlined />
|
||||
<span>{selectDomainName}</span>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
separator: selectModelName ? '/' : '',
|
||||
},
|
||||
{
|
||||
title: selectModelName ? (
|
||||
<Space
|
||||
onClick={() => {
|
||||
history.push(`/model/${selectDomainId}/${selectModelId}/`);
|
||||
}}
|
||||
style={{ color: '#296df3' }}
|
||||
>
|
||||
<FundViewOutlined style={{ position: 'relative', top: '2px' }} />
|
||||
<span>{selectModelName}</span>
|
||||
</Space>
|
||||
) : undefined,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Tabs
|
||||
className={styles.tab}
|
||||
items={!isModel ? tabItem : isModelItem}
|
||||
activeKey={activeKey || defaultTabKey}
|
||||
destroyInactiveTabPane
|
||||
size="large"
|
||||
tabBarExtraContent={{
|
||||
left: (
|
||||
<>
|
||||
{!!selectModelId && (
|
||||
<div
|
||||
className={styles.backBtn}
|
||||
onClick={() => {
|
||||
onBackDomainBtnClick?.();
|
||||
}}
|
||||
>
|
||||
<LeftOutlined />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
// right: isModel ? (
|
||||
// <Button
|
||||
// type="primary"
|
||||
// icon={<LeftOutlined />}
|
||||
// onClick={() => {
|
||||
// onBackDomainBtnClick?.();
|
||||
// }}
|
||||
// style={{ marginRight: 10, marginBottom: 5 }}
|
||||
// >
|
||||
// 返回主题域
|
||||
// </Button>
|
||||
// ) : undefined,
|
||||
}}
|
||||
onChange={(menuKey: string) => {
|
||||
onMenuChange?.(menuKey);
|
||||
}}
|
||||
|
||||
@@ -455,7 +455,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
forceRender
|
||||
width={1300}
|
||||
style={{ top: 48 }}
|
||||
bodyStyle={{ padding: '32px 40px 48px' }}
|
||||
styles={{ padding: '32px 40px 48px' }}
|
||||
destroyOnClose
|
||||
title={`${isEdit ? '编辑' : '新建'}指标`}
|
||||
maskClosable={false}
|
||||
|
||||
@@ -96,7 +96,7 @@ const ModelCreateFormModal: React.FC<ModelCreateFormModalProps> = (props) => {
|
||||
return (
|
||||
<Modal
|
||||
width={640}
|
||||
bodyStyle={{ padding: '32px 40px 48px' }}
|
||||
styles={{ padding: '32px 40px 48px' }}
|
||||
destroyOnClose
|
||||
title={'模型信息'}
|
||||
open={true}
|
||||
|
||||
@@ -192,24 +192,6 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
{/* <a
|
||||
key="dimensionEditBtn"
|
||||
onClick={() => {
|
||||
setPermissonData(record);
|
||||
setDimensionModalVisible(true);
|
||||
}}
|
||||
>
|
||||
维度授权
|
||||
</a>
|
||||
<a
|
||||
key="metricEditBtn"
|
||||
onClick={() => {
|
||||
setPermissonData(record);
|
||||
setMetricModalVisible(true);
|
||||
}}
|
||||
>
|
||||
指标授权
|
||||
</a> */}
|
||||
<Popconfirm
|
||||
title="确认删除?"
|
||||
okText="是"
|
||||
|
||||
@@ -62,7 +62,7 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
|
||||
return (
|
||||
<Modal
|
||||
width={640}
|
||||
bodyStyle={{ padding: '32px 40px 48px' }}
|
||||
styles={{ padding: '32px 40px 48px' }}
|
||||
destroyOnClose
|
||||
title={titleRender()}
|
||||
open={true}
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: #fff;
|
||||
height: calc(100vh - 48px);
|
||||
height: calc(100vh - 56px);
|
||||
|
||||
|
||||
.projectManger {
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 48px);
|
||||
// background: #f8f9fb;
|
||||
min-height: calc(100vh - 56px);
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
position: relative;
|
||||
@@ -126,6 +125,8 @@
|
||||
// }
|
||||
// }
|
||||
.tab {
|
||||
border-top: 1px solid #eee;
|
||||
margin-top: 10px;
|
||||
:global {
|
||||
.ant-tabs-tab-btn {
|
||||
font-size: 16px;
|
||||
@@ -186,31 +187,18 @@
|
||||
.domainList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// width: 400px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.searchContainer {
|
||||
padding:3px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
// .user {
|
||||
// display: grid;
|
||||
// }
|
||||
|
||||
// .search{
|
||||
// width: 50%;
|
||||
// margin-bottom: 20px;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// .authBtn{
|
||||
// cursor: pointer;
|
||||
// }
|
||||
|
||||
.classTable {
|
||||
:global {
|
||||
.ant-pro-table-search-query-filter {
|
||||
// padding-left: 0 !important;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ant-pro-table-list-toolbar-container {
|
||||
@@ -335,4 +323,17 @@
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb{
|
||||
font-size: 18px;
|
||||
margin: 20px 0 0 20px;
|
||||
:global {
|
||||
.ant-breadcrumb-link {
|
||||
height: 28px;
|
||||
}
|
||||
.anticon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,15 @@ export enum SENSITIVE_LEVEL {
|
||||
|
||||
export const SENSITIVE_LEVEL_OPTIONS = [
|
||||
{
|
||||
label: '低',
|
||||
label: '普通',
|
||||
value: SENSITIVE_LEVEL.LOW,
|
||||
},
|
||||
{
|
||||
label: '中',
|
||||
label: '重要',
|
||||
value: SENSITIVE_LEVEL.MID,
|
||||
},
|
||||
{
|
||||
label: '高',
|
||||
label: '核心',
|
||||
value: SENSITIVE_LEVEL.HIGH,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -202,6 +202,7 @@ export declare namespace ISemantic {
|
||||
dataFormat: string;
|
||||
alias: string;
|
||||
useCnt: number;
|
||||
isCollect: boolean;
|
||||
relateDimension?: IRelateDimension;
|
||||
}
|
||||
|
||||
|
||||
@@ -476,3 +476,17 @@ export async function queryStruct({
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export function metricStarState(data: { id: number; state: boolean }): Promise<any> {
|
||||
const { id, state } = data;
|
||||
if (state) {
|
||||
return request(`${process.env.API_BASE_URL}collect/createCollectionIndicators`, {
|
||||
method: 'POST',
|
||||
data: { id },
|
||||
});
|
||||
} else {
|
||||
return request(`${process.env.API_BASE_URL}collect/deleteCollectionIndicators/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
import styles from './style.less';
|
||||
import { Button, Form, Input, InputNumber, message, Space, Switch, Divider } from 'antd';
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
message,
|
||||
Space,
|
||||
Switch,
|
||||
Select,
|
||||
Divider,
|
||||
Anchor,
|
||||
Row,
|
||||
Col,
|
||||
} from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getSystemConfig, saveSystemConfig } from '@/services/user';
|
||||
import ProCard from '@ant-design/pro-card';
|
||||
import SelectTMEPerson from '@/components/SelectTMEPerson';
|
||||
import { SystemConfigParametersItem, SystemConfig } from './types';
|
||||
import { groupBy } from 'lodash';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { TextArea } = Input;
|
||||
const System: React.FC = () => {
|
||||
const [systemConfig, setSystemConfig] = useState<SystemConfigParametersItem[]>([]);
|
||||
|
||||
const [systemConfig, setSystemConfig] = useState<Record<string, SystemConfigParametersItem[]>>(
|
||||
{},
|
||||
);
|
||||
const [anchorItems, setAnchorItems] = useState<{ key: string; href: string; title: string }[]>(
|
||||
[],
|
||||
);
|
||||
const [configSource, setConfigSource] = useState<SystemConfig>();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -21,7 +39,16 @@ const System: React.FC = () => {
|
||||
const { code, data, msg } = await getSystemConfig();
|
||||
if (code === 200) {
|
||||
const { parameters, admins } = data;
|
||||
setSystemConfig(parameters);
|
||||
const groupByConfig = groupBy(parameters, 'module');
|
||||
const anchor = Object.keys(groupByConfig).map((key: string) => {
|
||||
return {
|
||||
key,
|
||||
href: `#${key}`,
|
||||
title: key,
|
||||
};
|
||||
});
|
||||
setAnchorItems(anchor);
|
||||
setSystemConfig(groupByConfig);
|
||||
setInitData(admins, parameters);
|
||||
setConfigSource(data);
|
||||
} else {
|
||||
@@ -29,8 +56,8 @@ const System: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const setInitData = (admins: string[], systemConfig: SystemConfigParametersItem[]) => {
|
||||
const fieldsValue = systemConfig.reduce(
|
||||
const setInitData = (admins: string[], systemConfigParameters: SystemConfigParametersItem[]) => {
|
||||
const fieldsValue = systemConfigParameters.reduce(
|
||||
(fields, item) => {
|
||||
const { name, value } = item;
|
||||
return {
|
||||
@@ -48,7 +75,7 @@ const System: React.FC = () => {
|
||||
const { code, msg } = await saveSystemConfig({
|
||||
...configSource,
|
||||
admins: submitData.admins,
|
||||
parameters: systemConfig.map((item) => {
|
||||
parameters: configSource!.parameters.map((item) => {
|
||||
const { name } = item;
|
||||
if (submitData[name] !== undefined) {
|
||||
return {
|
||||
@@ -68,68 +95,99 @@ const System: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ margin: '40px auto', width: 800 }}>
|
||||
<ProCard
|
||||
title="系统设置"
|
||||
extra={
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
querySaveSystemConfig();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Form form={form} layout="vertical" className={styles.form}>
|
||||
<FormItem name="admins" label="管理员">
|
||||
<SelectTMEPerson placeholder="请邀请团队成员" />
|
||||
</FormItem>
|
||||
<Divider />
|
||||
{systemConfig.map((item: SystemConfigParametersItem) => {
|
||||
const { dataType, name, comment } = item;
|
||||
let defaultItem = <Input />;
|
||||
switch (dataType) {
|
||||
case 'string':
|
||||
defaultItem = <TextArea placeholder="" style={{ height: 100 }} />;
|
||||
break;
|
||||
case 'number':
|
||||
defaultItem = <InputNumber style={{ width: '100%' }} />;
|
||||
break;
|
||||
case 'bool':
|
||||
return (
|
||||
<FormItem
|
||||
name={name}
|
||||
label={comment}
|
||||
key={name}
|
||||
valuePropName="checked"
|
||||
getValueFromEvent={(value) => {
|
||||
return value === true ? 'true' : 'false';
|
||||
}}
|
||||
getValueProps={(value) => {
|
||||
return {
|
||||
checked: value === 'true',
|
||||
};
|
||||
}}
|
||||
>
|
||||
<Switch />
|
||||
</FormItem>
|
||||
);
|
||||
default:
|
||||
defaultItem = <Input />;
|
||||
break;
|
||||
<div style={{ margin: '40px auto', width: 1200 }}>
|
||||
<Row>
|
||||
<Col span={18}>
|
||||
<ProCard
|
||||
title="系统设置"
|
||||
extra={
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
querySaveSystemConfig();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
return (
|
||||
<FormItem name={name} label={comment} key={name}>
|
||||
{defaultItem}
|
||||
>
|
||||
<Form form={form} layout="vertical" className={styles.form}>
|
||||
<FormItem name="admins" label="管理员">
|
||||
<SelectTMEPerson placeholder="请邀请团队成员" />
|
||||
</FormItem>
|
||||
);
|
||||
})}
|
||||
</Form>
|
||||
</ProCard>
|
||||
<Divider />
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={35}>
|
||||
{Object.keys(systemConfig).map((key: string) => {
|
||||
const itemList = systemConfig[key];
|
||||
return (
|
||||
<ProCard
|
||||
title={<span style={{ color: '#296df3' }}>{key}</span>}
|
||||
key={key}
|
||||
bordered
|
||||
id={key}
|
||||
>
|
||||
{itemList.map((item) => {
|
||||
const { dataType, name, comment } = item;
|
||||
let defaultItem = <Input />;
|
||||
switch (dataType) {
|
||||
case 'string':
|
||||
defaultItem = <TextArea placeholder="" style={{ height: 100 }} />;
|
||||
break;
|
||||
case 'number':
|
||||
defaultItem = <InputNumber style={{ width: '100%' }} />;
|
||||
break;
|
||||
case 'bool':
|
||||
return (
|
||||
<FormItem
|
||||
name={name}
|
||||
label={comment}
|
||||
key={name}
|
||||
valuePropName="checked"
|
||||
getValueFromEvent={(value) => {
|
||||
return value === true ? 'true' : 'false';
|
||||
}}
|
||||
getValueProps={(value) => {
|
||||
return {
|
||||
checked: value === 'true',
|
||||
};
|
||||
}}
|
||||
>
|
||||
<Switch />
|
||||
</FormItem>
|
||||
);
|
||||
case 'list': {
|
||||
const { candidateValues } = item;
|
||||
const options = candidateValues.map((value) => {
|
||||
return { label: value, value };
|
||||
});
|
||||
defaultItem = <Select style={{ width: '100%' }} options={options} />;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
defaultItem = <Input />;
|
||||
break;
|
||||
}
|
||||
return (
|
||||
<FormItem name={name} label={comment} key={name}>
|
||||
{defaultItem}
|
||||
</FormItem>
|
||||
);
|
||||
})}
|
||||
</ProCard>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</Form>
|
||||
</ProCard>
|
||||
</Col>
|
||||
<Col span={6} style={{ background: '#fff' }}>
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<Anchor items={anchorItems} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ export type SystemConfigParametersItem = {
|
||||
name: string;
|
||||
comment: string;
|
||||
value: string;
|
||||
candidateValues: string[];
|
||||
};
|
||||
|
||||
export type SystemConfig = {
|
||||
|
||||
Reference in New Issue
Block a user