From ce0e88b679e607db9f6cc00908c35ea611305676 Mon Sep 17 00:00:00 2001 From: liuhan Date: Mon, 12 May 2025 15:40:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E7=8E=AF=E5=A2=83=E5=8D=AB=E7=94=9F?= =?UTF-8?q?=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/images/V-2504/female.png | Bin 0 -> 340 bytes src/assets/images/V-2504/femaleActive.png | Bin 0 -> 294 bytes src/assets/images/V-2504/male.png | Bin 0 -> 243 bytes src/assets/images/V-2504/maleActive.png | Bin 0 -> 248 bytes .../Environment/components/LeftContent.less | 42 ------ .../components/WorkersAge/index.less | 0 .../components/WorkersAge/index.tsx | 13 ++ .../components/WorkersArea/index.less | 0 .../components/WorkersArea/index.tsx | 13 ++ .../components/GenderPieChart/index.less | 0 .../components/GenderPieChart/index.tsx | 126 ++++++++++++++++++ .../components/GenderProportion/index.less | 15 +++ .../components/GenderProportion/index.tsx | 85 ++++++++++++ .../components/WorkersGender/index.less | 34 +++++ .../components/WorkersGender/index.tsx | 46 +++++++ .../components/WorkersType/index.less | 0 .../components/WorkersType/index.tsx | 13 ++ .../components/LeftContent/index.less | 25 ++++ .../index.tsx} | 20 +-- .../components/SubPages/Environment/index.tsx | 2 +- .../SubPages/RestaurantOil/index.tsx | 3 +- .../components/common/Card/index.less | 11 ++ .../components/common/Card/index.tsx | 34 +++++ 23 files changed, 430 insertions(+), 52 deletions(-) create mode 100644 src/assets/images/V-2504/female.png create mode 100644 src/assets/images/V-2504/femaleActive.png create mode 100644 src/assets/images/V-2504/male.png create mode 100644 src/assets/images/V-2504/maleActive.png delete mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.less create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.tsx create mode 100644 src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.less rename src/pages/Home_v_2504/components/SubPages/Environment/components/{LeftContent.tsx => LeftContent/index.tsx} (66%) create mode 100644 src/pages/Home_v_2504/components/common/Card/index.less create mode 100644 src/pages/Home_v_2504/components/common/Card/index.tsx diff --git a/src/assets/images/V-2504/female.png b/src/assets/images/V-2504/female.png new file mode 100644 index 0000000000000000000000000000000000000000..934b6365e4719e81aec99f845e9e5a291a4eb13a GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0y~yVBle3V36csV_;xl%{zadfq{Xg*vT`5gM)*kh9jke zfq{|R)5S5wqIYhvW8NVHfjOm*wuF9Up2Ys4@t<Zv< zCm`p*uY1ssUo|mT-NHcqw)JM~xVJ(wCa159D4k+pm}qgKX7l61O($M&*W3~q#i>=H;TI>Kj;Tyx5D2_BW#=cBz#L+p+pYl7WsH<7sXWTO9Ki7HxOpgYYc{ipxO_&t=LYh-NozFCN-G?6r zvY|&`c=dcbUvT?_=gK1*|9K4S>dN1~;psZ>?0K{-|NNz_Z*bvEOyc~psKjF4zMo(D&+dv!NS%`Poq>UY!PC{xWt~$(69C$!j1d3; literal 0 HcmV?d00001 diff --git a/src/assets/images/V-2504/femaleActive.png b/src/assets/images/V-2504/femaleActive.png new file mode 100644 index 0000000000000000000000000000000000000000..11f2a3ca7ca8e8defd9949a18b32a54498d0d24b GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0y~yVBle3V36csV_;xl%{zadfq{Xg*vT`5gM)*kh9jke zfq~(!r;B5VMep3;i=s^i0^X~t1IrprzgRM+GR<43Xx-3VSf{Wjdp*-E`yDFNzb$oP z+8NG!fPq25EpFb@dB#fiuNax;N3g{GzQ(a+wT(=Bi84dNq)FTBSQw_O<|K&f@U^qf zPdFH)l3_fnFuc-2M4`6I*-apJ<-G}em+IW?x+1x6;^Udo#qSdyo{{#;`NmS9G0DSP z;VRqZ`7z689zM$#8CuZ(N&8Qj-KE{mKSj^YSQ4}AbF9tuNz?cF?h5fXJNb3zr+@Vh zn?>ES<^OlHDur#>sn~u*Md(HQrldpO_4^oSvikK-`*c*1fq{X+)78&qol`;+0Dr-8 ABme*a literal 0 HcmV?d00001 diff --git a/src/assets/images/V-2504/male.png b/src/assets/images/V-2504/male.png new file mode 100644 index 0000000000000000000000000000000000000000..d5282269ee0af17770a22db363cc36c013139b86 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0y~yU;wctIoKE&7&r>{cQ7z8uoOFahH!9jaMW<5fcUFC zT^vI!dY?|T7CL0W<5F(B#m>Qk;pdh+|2eiCDQI}YuqaKl!*<@0C&8PSesNnpwZrFa z?9>iphQ$fB#|^(lG)&Uq5iHxNaVUA&o@bkWF`b#}z;#&f!`ly95&DN29Auv?e;Jzb z^GtR2O5YgTe~DWM4f&MIO3 literal 0 HcmV?d00001 diff --git a/src/assets/images/V-2504/maleActive.png b/src/assets/images/V-2504/maleActive.png new file mode 100644 index 0000000000000000000000000000000000000000..ed8c487b7b2539c3d1b02e37cf71015427924760 GIT binary patch literal 248 zcmeAS@N?(olHy`uVBq!ia0y~yU;wctIoKE&7&r>{cQ7z8uoOFahH!9jaMW<5fcWb@ zT^vI!dhbqhjl8kE9PeA7VYZn(|T}$D4kRxB9%i)unQ| z*83%oeSPn(^s@C#)8ZGRt9eQ z#LygQ>sRKv_v{rRL*a*Y+bkNTSIy<Wh_`5Bn(2#+Ffx*+&&t;ucLK6U`P+R=~ literal 0 HcmV?d00001 diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.less deleted file mode 100644 index 7770540f..00000000 --- a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.less +++ /dev/null @@ -1,42 +0,0 @@ -.container { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; -} - -.header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 24px; -} - -.content { - flex: 1; - background: rgba(7, 28, 67, 0.5); - border-radius: 12px; - border: 1px solid rgba(24, 144, 255, 0.3); - padding: 20px; - display: flex; - flex-direction: column; - gap: 20px; -} - -.placeholder { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - color: #fff; - font-size: 24px; - text-align: center; - - p { - margin-top: 20px; - font-size: 16px; - color: rgba(255, 255, 255, 0.7); - } -} \ No newline at end of file diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.less new file mode 100644 index 00000000..e69de29b diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.tsx new file mode 100644 index 00000000..7fc264b2 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersAge/index.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import './index.less' +import HncyCard from '@/pages/Home_v_2504/components/common/Card' + +export default function WorkersAge() { + return ( + + <> + + ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.less new file mode 100644 index 00000000..e69de29b diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.tsx new file mode 100644 index 00000000..8b1e2868 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersArea/index.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import './index.less' +import HncyCard from '@/pages/Home_v_2504/components/common/Card' + +export default function WorkersArea() { + return ( + + <> + + ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.less new file mode 100644 index 00000000..e69de29b diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.tsx new file mode 100644 index 00000000..1ffd8692 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderPieChart/index.tsx @@ -0,0 +1,126 @@ +import React, { useEffect, useRef } from 'react' +import * as echarts from 'echarts'; +import './index.less' + +export default function GenderPieChart() { + + const chartRef = useRef(null); + + useEffect(() => { + if (chartRef.current) { + const myChart = echarts.init(chartRef.current); + + const option = { + // title: { + // // text: `{a|总共}\n{b|${5.8}}{c|万人}`, + // formatter: [ + // '{a|总共}', + // `{b|${5.8}}这段用默认样式{x|万人}` + // ].join('\n'), + // left: 'center', + // top: 'center', + // // textStyle.rich() + // textStyle: { + // a: { + // fontSize: 16, + // fontWeight: 400, + // color: '#BCCEE9', + // }, + // b: { + // fontSize: 24, + // fontWeight: 700, + // color: '#FFFFFF' + // }, + // c: { + // fontSize: 14, + // fontWeight: 400, + // color: '#BCCEE9', + // } + // } + // }, + label: { + formatter: [ + '{a|总共}', + `{b|${5.8}}{x|万人}` + ].join('\n'), + rich: { + a: { + fontFamily: '微软雅黑', + fontSize: 16, + fontWeight: 400, + color: '#BCCEE9', + }, + b: { + fontFamily: 'D-DIN', + fontSize: 24, + fontWeight: 700, + color: '#FFFFFF', + padding: [8, 8, 0, 0] + }, + x: { + fontFamily: '微软雅黑', + fontSize: 14, + fontWeight: 400, + color: '#BCCEE9', + padding: [10, 0, 0, 0] + }, + } + }, + series: [ + + { + type: 'pie', + radius: ['65%', '70%'], + padAngle: 1, + silent: true, // 禁用交互 + itemStyle: { + borderRadius: 0 + }, + label: { + show: true, + position: 'center' + }, + labelLine: { + show: false + }, + data: [ + { value: 1048, name: 'Search Engine', itemStyle: { color: '#26D5FF' } }, + { value: 735, name: 'Direct', itemStyle: { color: '#FF9155' } } + ] + }, + { + type: 'pie', + radius: ['45%', '70%'], + padAngle: 1, + silent: true, // 禁用交互 + label: { + show: false, + position: 'center' + }, + labelLine: { + show: false + }, + data: [ + { + value: 1048, + name: 'Search Engine', + itemStyle: { color: 'rgb(38, 213, 255, .2)' } + }, + { + value: 735, + name: 'Direct', + itemStyle: { color: 'rgb(255, 145, 85, .2)' } + } + ] + } + ] + }; + myChart.setOption(option); + } + }, []); + + + return ( +
+ ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.less new file mode 100644 index 00000000..fd9d52ed --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.less @@ -0,0 +1,15 @@ +.percentage { + display: flex; + align-items: center; + gap: 6px; + margin-top: 15px; + margin-bottom: 11px; + + .male, + .female { + img { + width: 10px; + height: 25px; + } + } +} \ No newline at end of file diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.tsx new file mode 100644 index 00000000..77268a07 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/components/GenderProportion/index.tsx @@ -0,0 +1,85 @@ +import React, { useMemo } from 'react' +import DescriptionItem from '@/components/DescriptionItem' +import male from '@/assets/images/V-2504/male.png' +import female from '@/assets/images/V-2504/female.png' +import maleActive from '@/assets/images/V-2504/maleActive.png' +import femaleActive from '@/assets/images/V-2504/femaleActive.png' +import './index.less' + +type GenderProportionProps = { + value: number, + percentage: number, + type: 'male' | 'female' +} + +export default function GenderProportion({ + value, + percentage, + type +}: GenderProportionProps) { + + const activeNums = useMemo(() => { + return Math.ceil(percentage / 100 * 7) + }, [percentage]) + + + return ( +
+ +
+ {/* 根据activeNums 和 type 类型,渲染高亮的 maleActive 或者 femaleActive 的图片数量 */} + { + Array.from({ length: 7 }).map((_, index) => { + return ( +
+ { + index < activeNums ? ( + + ) : ( + + ) + } +
+ ) + }) + } +
+ +
+ ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.less new file mode 100644 index 00000000..8530073b --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.less @@ -0,0 +1,34 @@ + + +.gender-wrapper { + display: flex; + align-items: center; + gap: 13px; + padding-right: 26px; + + div { + display: flex; + align-items: center; + gap: 8px; + + .dot { + width: 12px; + height: 12px; + border-radius: 50%; + } + + .blue { + background-image: linear-gradient(to bottom, #33FFDC, #0095FF); + } + + .yellow { + background-image: linear-gradient(to bottom, #FF9494, #FFCC7A); + } + } +} + +.children { + display: flex; + align-items: center; + gap: 34px; +} \ No newline at end of file diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.tsx new file mode 100644 index 00000000..f606f137 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersGender/index.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import './index.less' +import ModuleTitleWithTabs from '@/pages/Home_v_2504/components/common/ModuleTitleWithTabs' +import HncyCard from '@/pages/Home_v_2504/components/common/Card' +import GenderProportion from './components/GenderProportion' +import GenderPieChart from './components/GenderPieChart' + +export default function WorkersGender() { + return ( + +
+
+ 男 +
+
+
+ 女 +
+
+ } + > +
+
+ +
+
+ +
+
+ +
+
+ + ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.less new file mode 100644 index 00000000..e69de29b diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.tsx new file mode 100644 index 00000000..3ca3950b --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/components/WorkersType/index.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import './index.less' +import HncyCard from '@/pages/Home_v_2504/components/common/Card' + +export default function WorkersType() { + return ( + + <> + + ) +} diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.less b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.less new file mode 100644 index 00000000..b06b11c1 --- /dev/null +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.less @@ -0,0 +1,25 @@ +.container { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background: rgba(7, 28, 67, 0.5); +} + +.header { + display: flex; + justify-content: space-between; + align-items: center; + // margin-bottom: 24px; +} + +.content { + // flex: 1; + border-radius: 12px; + // border: 1px solid rgba(24, 144, 255, 0.3); + padding: 15px; + display: flex; + flex-wrap: wrap; + // flex-direction: column; + gap: 15px; +} \ No newline at end of file diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.tsx similarity index 66% rename from src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.tsx rename to src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.tsx index 61e33089..31399f66 100644 --- a/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent.tsx +++ b/src/pages/Home_v_2504/components/SubPages/Environment/components/LeftContent/index.tsx @@ -1,7 +1,11 @@ import React from 'react'; import PanelTitle from '@/pages/Home_v_2504/components/common/PanelTitle'; import DateSelector from '@/components/V2504/DateSelector'; -import styles from './LeftContent.less'; +import styles from './index.less'; +import WorkersGender from './components/WorkersGender'; +import WorkersType from './components/WorkersType'; +import WorkersArea from './components/WorkersArea'; +import WorkersAge from './components/WorkersAge'; /** * 环卫行业子页面 - 左侧内容组件 @@ -17,19 +21,19 @@ const LeftContent: React.FC = () => {
{/* 标题 */}
- - + {/* + /> */}
-
- 环卫行业左侧内容 -

这是一个示例组件,实际使用时需要根据业务需求实现

-
+ + + +
); diff --git a/src/pages/Home_v_2504/components/SubPages/Environment/index.tsx b/src/pages/Home_v_2504/components/SubPages/Environment/index.tsx index 741c6318..bfc7f56e 100644 --- a/src/pages/Home_v_2504/components/SubPages/Environment/index.tsx +++ b/src/pages/Home_v_2504/components/SubPages/Environment/index.tsx @@ -3,7 +3,7 @@ import SubPageTemplate from '../SubPageTemplate'; import { INDUSTRY_PAGE_IDS } from '@/constants/dataTypes'; // 引入业务组件 -import LeftContent from './components/LeftContent'; +import LeftContent from './components/LeftContent/LeftContent'; import RightContent from './components/RightContent'; interface EnvironmentProps { diff --git a/src/pages/Home_v_2504/components/SubPages/RestaurantOil/index.tsx b/src/pages/Home_v_2504/components/SubPages/RestaurantOil/index.tsx index 761c61e7..b5029162 100644 --- a/src/pages/Home_v_2504/components/SubPages/RestaurantOil/index.tsx +++ b/src/pages/Home_v_2504/components/SubPages/RestaurantOil/index.tsx @@ -1,7 +1,8 @@ import React from 'react'; import SubPageTemplate from '../SubPageTemplate'; import RightContent from './components/RightContent'; -import LeftContent from './components/LeftContent'; +// import LeftContent from './components/LeftContent'; +import LeftContent from '../Environment/components/LeftContent'; import { INDUSTRY_PAGE_IDS } from '@/constants/dataTypes'; interface RestaurantOilProps { diff --git a/src/pages/Home_v_2504/components/common/Card/index.less b/src/pages/Home_v_2504/components/common/Card/index.less new file mode 100644 index 00000000..c325758e --- /dev/null +++ b/src/pages/Home_v_2504/components/common/Card/index.less @@ -0,0 +1,11 @@ +.workers-wrapper { + width: 530px; + min-height: 192px; + background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%); + border-radius: 15px; +} + +.content { + height: calc(100% - 52px); + padding: 0px 36px 20px 36px; +} \ No newline at end of file diff --git a/src/pages/Home_v_2504/components/common/Card/index.tsx b/src/pages/Home_v_2504/components/common/Card/index.tsx new file mode 100644 index 00000000..8d61a047 --- /dev/null +++ b/src/pages/Home_v_2504/components/common/Card/index.tsx @@ -0,0 +1,34 @@ +import React, { Children, CSSProperties, ReactNode } from 'react' +import './index.less' +import ModuleTitleWithTabs from '../ModuleTitleWithTabs' + +type CardProps ={ + title: string, + extra?: ReactNode, + children: ReactNode, + style?: CSSProperties +} +export default function HncyCard({ + title, + extra, + children, + style +}: CardProps) { + return ( +
+
+ + {extra} +
+
+ {children} +
+
+ ) +} -- GitLab