feat:工作台初始化项目。

This commit is contained in:
tianyongbao
2025-12-11 09:15:47 +08:00
parent 824a387119
commit 613d14fac0
123 changed files with 33586 additions and 0 deletions

23
src/Util.js Normal file
View File

@@ -0,0 +1,23 @@
/**
* 常用函数工具类
*/
'use strict'
const userAgent = navigator.userAgent
export default class Util {
static os = {
trident: userAgent.indexOf('Trident') > -1, // IE内核
presto: userAgent.indexOf('Presto') > -1, // opera内核
webKit: userAgent.indexOf('AppleWebKit') > -1, // 苹果、谷歌内核
gecko: userAgent.indexOf('Gecko') > -1 && userAgent.indexOf('KHTML') === -1, // 火狐内核
ios: !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // ios终端
android: userAgent.indexOf('Android') > -1 || userAgent.indexOf('Linux') > -1, // android终端或者uc浏览器
iPhone: userAgent.indexOf('iPhone') > -1, // 是否为iPhone
mobile: !!userAgent.match(/AppleWebKit.*Mobile.*/), // 是否为移动终端
iPad: userAgent.indexOf('iPad') > -1, // 是否iPad
webApp: userAgent.indexOf('Safari') === -1, // 是否web应该程序没有头部与底部
wechat: userAgent.indexOf('MicroMessenger') > -1, // 是否微信浏览器
isapp: window.innerWidth < 768, // 是否微信浏览器
harmonyOS: userAgent.indexOf('HarmonyOS') > -1,
}
}

19
src/assets/css/common.css Normal file
View File

@@ -0,0 +1,19 @@
/* 全局样式 */
.m-0-auto {
margin: 0 auto;
}
.m-0 {
margin: 0;
}
.m-r-5 {
margin-right: 5px;
}
.m-t-5 {
margin-top: 5px;
}
.p-0 {
padding: 0;
}
.w-100pct {
width: 100%;
}

1
src/assets/css/vivify.min.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
src/assets/img/feature1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4CAF50;stop-opacity:1" />
<stop offset="100%" style="stop-color:#45a049;stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="48" cy="48" r="44" fill="url(#grad1)" opacity="0.1"/>
<circle cx="48" cy="48" r="40" fill="none" stroke="url(#grad1)" stroke-width="3"/>
<!-- 钱包图标 -->
<path d="M 28 35 L 68 35 C 70.2 35 72 36.8 72 39 L 72 61 C 72 63.2 70.2 65 68 65 L 28 65 C 25.8 65 24 63.2 24 61 L 24 39 C 24 36.8 25.8 35 28 35 Z" fill="url(#grad1)" opacity="0.8"/>
<!-- 钱币符号 ¥ -->
<text x="48" y="56" font-family="Arial, sans-serif" font-size="24" font-weight="bold" fill="#ffffff" text-anchor="middle">¥</text>
<!-- 账本线条 -->
<line x1="32" y1="42" x2="44" y2="42" stroke="#ffffff" stroke-width="2" opacity="0.6"/>
<line x1="32" y1="48" x2="40" y2="48" stroke="#ffffff" stroke-width="2" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/assets/img/feature2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
<defs>
<linearGradient id="grad2" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#E91E63;stop-opacity:1" />
<stop offset="100%" style="stop-color:#C2185B;stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="48" cy="48" r="44" fill="url(#grad2)" opacity="0.1"/>
<circle cx="48" cy="48" r="40" fill="none" stroke="url(#grad2)" stroke-width="3"/>
<!-- 心电图/健康图标 -->
<path d="M 28 50 L 35 50 L 38 42 L 42 58 L 46 38 L 50 50 L 68 50" fill="none" stroke="url(#grad2)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<!-- 心形 -->
<path d="M 48 62 C 48 62 38 54 38 46 C 38 42 40 40 43 40 C 45 40 47 41 48 43 C 49 41 51 40 53 40 C 56 40 58 42 58 46 C 58 54 48 62 48 62 Z" fill="url(#grad2)" opacity="0.8"/>
<!-- 十字符号 -->
<rect x="45" y="26" width="6" height="10" rx="1" fill="url(#grad2)"/>
<rect x="42" y="29" width="12" height="4" rx="1" fill="url(#grad2)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/assets/img/feature3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,27 @@
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
<defs>
<linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#FF9800;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F57C00;stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="48" cy="48" r="44" fill="url(#grad3)" opacity="0.1"/>
<circle cx="48" cy="48" r="40" fill="none" stroke="url(#grad3)" stroke-width="3"/>
<!-- 酒瓶轮廓 -->
<path d="M 42 28 L 54 28 L 54 32 L 52 32 L 52 36 C 56 38 58 42 58 48 L 58 64 C 58 66 56 68 54 68 L 42 68 C 40 68 38 66 38 64 L 38 48 C 38 42 40 38 44 36 L 44 32 L 42 32 Z" fill="url(#grad3)" opacity="0.8"/>
<!-- 瓶盖 -->
<rect x="44" y="24" width="8" height="4" rx="1" fill="url(#grad3)"/>
<!-- 酒标签 -->
<ellipse cx="48" cy="52" rx="8" ry="10" fill="#ffffff" opacity="0.3"/>
<!-- 日历/预约符号 -->
<rect x="60" y="26" width="10" height="12" rx="1" fill="url(#grad3)" opacity="0.9"/>
<line x1="62" y1="28" x2="68" y2="28" stroke="#ffffff" stroke-width="1.5"/>
<circle cx="63" cy="32" r="1" fill="#ffffff"/>
<circle cx="67" cy="32" r="1" fill="#ffffff"/>
<circle cx="63" cy="35" r="1" fill="#ffffff"/>
<circle cx="67" cy="35" r="1" fill="#ffffff"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/assets/img/feature4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
<defs>
<linearGradient id="grad4" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#2196F3;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1976D2;stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="48" cy="48" r="44" fill="url(#grad4)" opacity="0.1"/>
<circle cx="48" cy="48" r="40" fill="none" stroke="url(#grad4)" stroke-width="3"/>
<!-- 客服耳机图标 -->
<path d="M 48 32 C 38 32 30 40 30 50 L 30 58 C 30 60 32 62 34 62 L 38 62 C 40 62 42 60 42 58 L 42 52 C 42 50 40 48 38 48 L 34 48 L 34 50 C 34 42 40 36 48 36 C 56 36 62 42 62 50 L 62 48 L 58 48 C 56 48 54 50 54 52 L 54 58 C 54 60 56 62 58 62 L 62 62 C 64 60 66 58 66 58 L 66 50 C 66 40 58 32 48 32 Z" fill="url(#grad4)" opacity="0.8"/>
<!-- 麦克风 -->
<rect x="45" y="62" width="6" height="8" rx="3" fill="url(#grad4)"/>
<line x1="42" y1="70" x2="54" y2="70" stroke="url(#grad4)" stroke-width="2" stroke-linecap="round"/>
<!-- 服务星标 -->
<path d="M 48 24 L 50 29 L 55 29 L 51 32 L 53 37 L 48 34 L 43 37 L 45 32 L 41 29 L 46 29 Z" fill="url(#grad4)" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/img/health.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/assets/img/imaotai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/assets/img/invest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/assets/img/qrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
src/assets/img/qrcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

475
src/assets/less/normalize.less vendored Normal file
View File

@@ -0,0 +1,475 @@
// =============================================================================
// Normalize.less based on Nicolas Gallagher and Jonathan Neal's
// normalize.css v3.0.1 | MIT License | github.com/necolas/normalize.css
// =============================================================================
//
// Variables
// ====================================================================
// Base font-family
@base-font-family: sans-serif;
// The base font size
@base-font-size: 16px;
// The base line height determines the basic unit of vertical rhythm.
@base-line-height: 24px;
// Heading sizes
@h1-size: 36px;
//
// Mixins
// ====================================================================
//
// Passing in a single value will create font-sizing in
// pixels, rems as well as a proper line-height.
//
// `.font-size(24px, false);`
//
.font-size(@font-size, @line-height: true) {
@px-value: (@font-size);
@rem-value: (@font-size / @base-font-size) * 1rem;
@line-height-value: ceil(@font-size / @base-line-height) * (@base-line-height / @font-size);
font-size: ~"@{px-value}";
font-size: @rem-value;
.line-height(@boolean) when (@boolean = true) {
line-height: unit(@line-height-value);
}
.line-height(@line-height);
}
//
// 1. Set default font family to sans-serif.
// 2. Prevent iOS and IE text size adjust after device orientation change,
// without disabling user zoom.
//
html {
font-size: 100%; // 1 //
-ms-text-size-adjust: 100%; // 2 //
-webkit-text-size-adjust: 100%; // 2 //
}
//
// Remove default margin.
//
body { margin: 0; }
//
// HTML5 display definitions
// ====================================================================
//
// Correct `block` display not defined for any HTML5 element in IE 8/9.
// Correct `block` display not defined for `details` or `summary` in IE 10/11
// and Firefox.
// Correct `block` display not defined for `main` in IE 11.
//
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
main,
nav,
section,
summary { display: block; }
//
// 1. Correct `inline-block` display not defined in IE 8/9.
// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
//
audio,
canvas,
progress,
video {
display: inline-block; // 1 //
vertical-align: baseline; // 2 //
}
//
// Prevent modern browsers from displaying `audio` without controls.
// Remove excess height in iOS 5 devices.
//
audio:not([controls]) {
display: none;
height: 0;
}
//
// Address `[hidden]` styling not present in IE 8/9/10.
// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
//
[hidden],
template { display: none; }
//
// Links
// ====================================================================
//
// Remove the gray background color from active links in IE 10.
//
a {
background-color: transparent;
//
// Improve readability of focused elements when they are also in an
// active/hover state.
//
&:focus { outline: thin dotted; }
&:active,
&:hover { outline: 0; }
}
//
// Text-level semantics
// ====================================================================
//
// Address styling not present in IE 8/9/10/11, Safari, and Chrome.
//
abbr[title] { border-bottom: 1px dotted; }
//
// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
//
b,
strong { font-weight: bold; }
//
// Address styling not present in Safari and Chrome.
//
dfn { font-style: italic; }
//
// Address variable `h1` font-size and margin within `section` and `article`
// contexts in Firefox 4+, Safari, and Chrome.
//
h1 {
.font-size(@h1-size);
margin: 0.67em 0;
}
//
// Address styling not present in IE 8/9.
//
mark {
background: #ff0;
color: #000;
}
//
// Address inconsistent and variable font size in all browsers.
//
small { font-size: 80%; }
//
// Prevent `sub` and `sup` affecting `line-height` in all browsers.
//
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup { top: -0.5em; }
sub { bottom: -0.25em; }
//
// Embedded content
// ====================================================================
//
// Remove border when inside `a` element in IE 8/9/10.
//
img { border: 0; }
//
// Correct overflow not hidden in IE 9/10/11.
//
svg:not(:root) { overflow: hidden; }
//
// Grouping content
// ====================================================================
//
// Address margin not present in IE 8/9 and Safari.
//
figure { margin: 1em 40px; }
//
// Address differences between Firefox and other browsers.
//
hr {
box-sizing: content-box;
height: 0;
}
//
// Contain overflow in all browsers.
//
pre { overflow: auto; }
//
// Address odd `em`-unit font size rendering in all browsers.
//
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
.font-size(@base-font-size);
}
//
// Forms
// ====================================================================
//
// Known limitation: by default, Chrome and Safari on OS X allow very limited
// styling of `select`, unless a `border` property is set.
//
//
// 1. Correct color not being inherited.
// Known issue: affects color of disabled elements.
// 2. Correct font properties not being inherited.
// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
//
button,
input,
optgroup,
select,
textarea {
color: inherit; // 1 //
font: inherit; // 1 //
margin: 0; // 1 //
}
//
// Address `overflow` set to `hidden` in IE 8/9/10/11.
//
button { overflow: visible; }
//
// Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
// Correct `select` style inheritance in Firefox.
//
button,
select { text-transform: none; }
//
// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
// and `video` controls.
// 2. Correct inability to style clickable `input` types in iOS.
// 3. Improve usability and consistency of cursor style between image-type
// `input` and others.
//
button,
html input[type="button"], // 1 //
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; // 2 //
cursor: pointer; // 3 //
}
//
// Re-set default cursor for disabled elements.
//
button[disabled],
html input[disabled] { cursor: default; }
//
// Remove inner padding and border in Firefox 4+.
//
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
//
// Address Firefox 4+ setting `line-height` on `input` using `!important` in
// the UA stylesheet.
//
input {
line-height: normal;
//
// It's recommended that you don't attempt to style these elements.
// Firefox's implementation doesn't respect box-sizing, padding, or width.
//
// 1. Address box sizing set to `content-box` in IE 8/9/10.
// 2. Remove excess padding in IE 8/9/10.
//
&[type="checkbox"],
&[type="radio"] {
box-sizing: border-box; // 1 //
padding: 0; // 2 //
}
//
// Fix the cursor style for Chrome's increment/decrement buttons. For certain
// `font-size` values of the `input`, it causes the cursor style of the
// decrement button to change from `default` to `text`.
//
&[type="number"] {
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button { height: auto; }
}
//
// 1. Address `appearance` set to `searchfield` in Safari and Chrome.
// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
//
&[type="search"] {
-webkit-appearance: textfield; // 1 //
box-sizing: content-box; // 2 //
//
// Remove inner padding and search cancel button in Safari and Chrome on OS X.
// Safari (but not Chrome) clips the cancel button when the search input has
// padding (and `textfield` appearance).
//
&::-webkit-search-cancel-button,
&::-webkit-search-decoration { -webkit-appearance: none; }
}
}
//
// Define consistent border, margin, and padding.
//
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
//
// 1. Correct `color` not being inherited in IE 8/9/10/11.
// 2. Remove padding so people aren't caught out if they zero out fieldsets.
//
legend {
border: 0; // 1 //
padding: 0; // 2 //
}
//
// Remove default vertical scrollbar in IE 8/9/10/11.
//
textarea { overflow: auto; }
//
// Don't inherit the `font-weight` (applied by a rule above).
// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
//
optgroup { font-weight: bold; }
//
// Tables
// ====================================================================
//
// Remove most spacing between table cells.
//
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th { padding: 0; }

525
src/assets/scss/normalize.scss vendored Normal file
View File

@@ -0,0 +1,525 @@
// =============================================================================
// Normalize.scss based on Nicolas Gallagher and Jonathan Neal's
// normalize.css v2.1.3 | MIT License | git.io/normalize
// =============================================================================
// =============================================================================
// Normalize.scss settings
// =============================================================================
// Set to true if you want to add support for IE6 and IE7
// Notice: setting to true might render some elements
// slightly differently than when set to false
$legacy_support_for_ie: false !default; // Used also in Compass
// Set the default font family here so you don't have to override it later
$normalized_font_family: sans-serif !default;
$normalize_headings: true !default;
$h1_font_size: 2em !default;
$h2_font_size: 1.5em !default;
$h3_font_size: 1.17em !default;
$h4_font_size: 1em !default;
$h5_font_size: 0.83em !default;
$h6_font_size: 0.75em !default;
$h1_margin: 0.67em 0 !default;
$h2_margin: 0.83em 0 !default;
$h3_margin: 1em 0 !default;
$h4_margin: 1.33em 0 !default;
$h5_margin: 1.67em 0 !default;
$h6_margin: 2.33em 0 !default;
$background: #fff !default;
$color: #000 !default;
// =============================================================================
// HTML5 display definitions
// =============================================================================
// Corrects block display not defined in IE6/7/8/9 & FF3
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
// Corrects inline-block display not defined in IE6/7/8/9 & FF3
audio,
canvas,
video {
display: inline-block;
@if $legacy_support_for_ie {
*display: inline;
*zoom: 1;
}
}
// 1. Prevents modern browsers from displaying 'audio' without controls
// 2. Remove excess height in iOS5 devices
audio:not([controls]) {
display: none; // 1
height: 0; // 2
}
//
// Address `[hidden]` styling not present in IE 8/9.
// Hide the `template` element in IE, Safari, and Firefox < 22.
//
[hidden], template {
display: none;
}
// =============================================================================
// Base
// =============================================================================
// 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
// http://clagnut.com/blog/348/#c790
// 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
// www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
html {
@if $legacy_support_for_ie {
font-size: 100%; // 1
}
background: $background;
color: $color;
-webkit-text-size-adjust: 100%; // 2
-ms-text-size-adjust: 100%; // 2
}
// Addresses font-family inconsistency between 'textarea' and other form elements.
html,
button,
input,
select,
textarea {
font-family: $normalized_font_family;
}
// Addresses margins handled incorrectly in IE6/7
body {
margin: 0;
}
// =============================================================================
// Links
// =============================================================================
// 1. Remove the gray background color from active links in IE 10.
// 2. Addresses outline displayed oddly in Chrome
// 3. Improves readability when focused and also mouse hovered in all browsers
// people.opera.com/patrickl/experiments/keyboard/test
a {
// 1
background: transparent;
// 2
&:focus {
outline: thin dotted;
}
// 3
&:hover,
&:active {
outline: 0;
}
}
// =============================================================================
// Typography
// =============================================================================
// Addresses font sizes and margins set differently in IE6/7
// Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5
@if $normalize_headings == true {
h1 {
font-size: $h1_font_size;
margin: $h1_margin;
}
h2 {
font-size: $h2_font_size;
margin: $h2_margin;
}
h3 {
font-size: $h3_font_size;
margin: $h3_margin;
}
h4 {
font-size: $h4_font_size;
margin: $h4_margin;
}
h5 {
font-size: $h5_font_size;
margin: $h5_margin;
}
h6 {
font-size: $h6_font_size;
margin: $h6_margin;
}
}
// Addresses styling not present in IE 8/9, S5, Chrome
abbr[title] {
border-bottom: 1px dotted;
}
// Addresses style set to 'bolder' in FF3+, S4/5, Chrome
b,
strong {
font-weight: bold;
}
@if $legacy_support_for_ie {
blockquote {
margin: 1em 40px;
}
}
// Addresses styling not present in S5, Chrome
dfn {
font-style: italic;
}
// Addresses styling not present in IE6/7/8/9
mark {
background: #ff0;
color: #000;
}
// Addresses margins set differently in IE6/7
@if $legacy_support_for_ie {
p,
pre {
margin: 1em 0;
}
}
// Corrects font family set oddly in IE6, S4/5, Chrome
// en.wikipedia.org/wiki/User:Davidgothberg/Test59
code,
kbd,
pre,
samp {
font-family: monospace, serif;
@if $legacy_support_for_ie {
_font-family: 'courier new', monospace;
}
font-size: 1em;
}
// Improves readability of pre-formatted text in all browsers
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
// Set consistent quote types.
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
// 1. Addresses CSS quotes not supported in IE6/7
// 2. Addresses quote property not supported in S4
// 1
@if $legacy_support_for_ie {
q {
quotes: none;
}
}
// 2
q {
&:before,
&:after {
content: '';
content: none;
}
}
// Address inconsistent and variable font size in all browsers.
small {
font-size: 80%;
}
// Prevents sub and sup affecting line-height in all browsers
// gist.github.com/413930
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
// =============================================================================
// Lists
// =============================================================================
// Addresses margins set differently in IE6/7
@if $legacy_support_for_ie {
dl,
menu,
ol,
ul {
margin: 1em 0;
}
}
@if $legacy_support_for_ie {
dd {
margin: 0 0 0 40px;
}
}
// Addresses paddings set differently in IE6/7
@if $legacy_support_for_ie {
menu,
ol,
ul {
padding: 0 0 0 40px;
}
}
// Corrects list images handled incorrectly in IE7
nav {
ul,
ol {
@if $legacy_support_for_ie {
list-style-image: none;
}
}
}
// =============================================================================
// Embedded content
// =============================================================================
// 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
// 2. Improves image quality when scaled in IE7
// code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
img {
border: 0; // 1
@if $legacy_support_for_ie {
-ms-interpolation-mode: bicubic; // 2
}
}
// Corrects overflow displayed oddly in IE9
svg:not(:root) {
overflow: hidden;
}
// =============================================================================
// Figures
// =============================================================================
// Addresses margin not present in IE6/7/8/9, S5, O11
figure {
margin: 0;
}
// =============================================================================
// Forms
// =============================================================================
// Corrects margin displayed oddly in IE6/7
@if $legacy_support_for_ie {
form {
margin: 0;
}
}
// Define consistent border, margin, and padding
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
// 1. Corrects color not being inherited in IE6/7/8/9
// 2. Remove padding so people aren't caught out if they zero out fieldsets.
// 3. Corrects text not wrapping in FF3
// 4. Corrects alignment displayed oddly in IE6/7
legend {
border: 0; // 1
padding: 0; // 2
white-space: normal; // 3
@if $legacy_support_for_ie {
*margin-left: -7px; // 4
}
}
// 1. Correct font family not being inherited in all browsers.
// 2. Corrects font size not being inherited in all browsers
// 3. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
// 4. Improves appearance and consistency in all browsers
button,
input,
select,
textarea {
font-family: inherit; // 1
font-size: 100%; // 2
margin: 0; // 3
vertical-align: baseline; // 4
@if $legacy_support_for_ie {
*vertical-align: middle; // 4
}
}
// Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
button, input {
line-height: normal;
}
// Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
// Correct `select` style inheritance in Firefox 4+ and Opera.
button,
select {
text-transform: none;
}
// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
// and `video` controls
// 2. Corrects inability to style clickable 'input' types in iOS
// 3. Improves usability and consistency of cursor style between image-type
// 'input' and others
// 4. Removes inner spacing in IE7 without affecting normal text inputs
// Known issue: inner spacing remains in IE6
button,
html input[type="button"], // 1
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; // 2
cursor: pointer; // 3
@if $legacy_support_for_ie {
*overflow: visible; // 4
}
}
// Re-set default cursor for disabled elements
button[disabled],
input[disabled] {
cursor: default;
}
// Removes inner padding and border in FF3+
// www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
button, input {
&::-moz-focus-inner {
border: 0;
padding: 0;
}
}
// 1. Removes default vertical scrollbar in IE6/7/8/9
// 2. Improves readability and alignment in all browsers
textarea {
overflow: auto; // 1
vertical-align: top; // 2
}
// =============================================================================
// Tables
// =============================================================================
// Remove most spacing between table cells
table {
border-collapse: collapse;
border-spacing: 0;
}
input {
// 1. Addresses appearance set to searchfield in S5, Chrome
// 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
&[type="search"] {
-webkit-appearance: textfield; // 1
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; // 2
box-sizing: content-box;
// Remove inner padding and search cancel button in Safari 5 and Chrome
// on OS X.
&::-webkit-search-cancel-button,
&::-webkit-search-decoration {
-webkit-appearance: none;
}
}
// 1. Address box sizing set to `content-box` in IE 8/9/10.
// 2. Remove excess padding in IE 8/9/10.
// 3. Removes excess padding in IE7
// Known issue: excess padding remains in IE6
&[type="checkbox"],
&[type="radio"] {
box-sizing: border-box; // 1
padding: 0; // 2
@if $legacy_support_for_ie {
*height: 13px; // 3
*width: 13px; // 3
}
}
}

6
src/components/App.vue Normal file
View File

@@ -0,0 +1,6 @@
<template>
<router-view></router-view>
</template>
<script>
export default {}
</script>

15
src/components/Button.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<button class="zui-button" @click="onClick">
<slot></slot>
</button>
</template>
<script>
import './less/button.less'
export default {
methods: {
onClick (e) {
this.$emit('click', e)
}
}
}
</script>

151
src/components/CaseLogo.vue Normal file
View File

@@ -0,0 +1,151 @@
<template>
<!-- <img alt="zhichou" class="zui-logo" :src="src" @click="onClick"/> -->
<img alt="zhichou" class="zui-logo" :src="src" />
</template>
<script>
import './less/logo.less'
import case1 from './img/case1.png'
import case2 from './img/case2.png'
import case3 from './img/case3.png'
import case4 from './img/case4.png'
import case5 from './img/case5.png'
import case6 from './img/case6.png'
import case7 from './img/case7.png'
import case8 from './img/case8.png'
import case9 from './img/case9.png'
import case10 from './img/case10.png'
import case11 from './img/case11.png'
import case12 from './img/case12.png'
import case13 from './img/case13.png'
import case14 from './img/case14.png'
import case15 from './img/case15.png'
import mcase1 from './img/mcase1.png'
import mcase2 from './img/mcase2.png'
import mcase3 from './img/mcase3.png'
import mcase4 from './img/mcase4.png'
import mcase5 from './img/mcase5.png'
import mcase6 from './img/mcase6.png'
import mcase7 from './img/mcase7.png'
import mcase8 from './img/mcase8.png'
import mcase9 from './img/mcase9.png'
import mcase10 from './img/mcase10.png'
import mcase11 from './img/mcase11.png'
import mcase12 from './img/mcase12.png'
import mcase13 from './img/mcase13.png'
import mcase14 from './img/mcase14.png'
import mcase15 from './img/mcase15.png'
export default {
name: 'CaseLogo',
props: {
type: {
default: 'case1'
},
href: {
default: '/'
}
},
computed: {
src: function () {
if (this.type === 'case1') {
return case1
}
if (this.type === 'case2') {
return case2
}
if (this.type === 'case3') {
return case3
}
if (this.type === 'case4') {
return case4
}
if (this.type === 'case5') {
return case5
}
if (this.type === 'case6') {
return case6
}
if (this.type === 'case7') {
return case7
}
if (this.type === 'case8') {
return case8
}
if (this.type === 'case9') {
return case9
}
if (this.type === 'case10') {
return case10
}
if (this.type === 'case11') {
return case11
}
if (this.type === 'case12') {
return case12
}
if (this.type === 'case13') {
return case13
}
if (this.type === 'case14') {
return case14
}
if (this.type === 'case15') {
return case15
}
if (this.type === 'mcase1') {
return mcase1
}
if (this.type === 'mcase2') {
return mcase2
}
if (this.type === 'mcase3') {
return mcase3
}
if (this.type === 'mcase4') {
return mcase4
}
if (this.type === 'mcase5') {
return mcase5
}
if (this.type === 'mcase6') {
return mcase6
}
if (this.type === 'mcase7') {
return mcase7
}
if (this.type === 'mcase8') {
return mcase8
}
if (this.type === 'mcase9') {
return mcase9
}
if (this.type === 'mcase10') {
return mcase10
}
if (this.type === 'mcase11') {
return mcase11
}
if (this.type === 'mcase12') {
return mcase12
}
if (this.type === 'mcase13') {
return mcase13
}
if (this.type === 'mcase14') {
return mcase14
}
if (this.type === 'mcase15') {
return mcase15
}
}
},
methods: {
onClick: function (e) {
location.assign(this.href)
}
}
}
</script>

View File

@@ -0,0 +1,10 @@
<template>
<div class="customer-case">
<slot></slot>
</div>
</template>
<script>
import './less/customer-case.less'
export default {
}
</script>

23
src/components/Footer.vue Normal file
View File

@@ -0,0 +1,23 @@
<template>
<footer class="zui-footer">
<div class="footer-content">
<div class="footer-qrcode">
<img src="../assets/img/qrcode.png" width="270" height="155" alt="客服二维码">
</div>
<div class="links">
<a href="https://beian.miit.gov.cn/" target="_blank">鲁ICP备2024118666号-1</a>
<img src="./img/gongan.png" width="18" height="20" alt="公安图标">&nbsp;<a href="https://beian.mps.gov.cn/#/query/webSearch?code=37021202001661" rel="noreferrer" target="_blank">鲁公网安备37021202001661</a>
</div>
</div>
<p class="copy-right">
Copyright 2025 智聪网络科技 .All rights reserved
<br>
</p>
</footer>
</template>
<script>
import './less/footer.less'
export default {}
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div class="zui-form-item">
<label class="zui-form-label">{{label}}</label>
<slot></slot>
</div>
</template>
<script>
export default {
props: {
label: {
default: ''
}
}
}
</script>

17
src/components/Header.vue Normal file
View File

@@ -0,0 +1,17 @@
<template>
<header class="zui-header">
<slot></slot>
</header>
</template>
<script>
import './less/header.less'
import Logo from './Logo'
export default {
props: {
logoType: {
default: 'zhichou'
}
},
components: {Logo}
}
</script>

10
src/components/Label.vue Normal file
View File

@@ -0,0 +1,10 @@
<template>
<label class="zui-label">
<slot></slot>
<span class="zui-label-triangle"></span>
</label>
</template>
<script>
import './less/label.less'
export default {}
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div class="zui-loading">
<div class="zui-loading-content">
<div class="zui-loading-dot white"></div>
<div class="zui-loading-dot"></div>
<div class="zui-loading-dot"></div>
<div class="zui-loading-dot"></div>
<div class="zui-loading-dot"></div>
</div>
</div>
</template>
<script>
import './less/loading.less'
export default {}
</script>

56
src/components/Logo.vue Normal file
View File

@@ -0,0 +1,56 @@
<template>
<img alt="xiaoyanyun" class="zui-logo" :src="src" @click="onClick"/>
</template>
<script>
import './less/logo.less'
import logo from './img/logo.png'
import zlogo from './img/zlogo.png'
import hrLogo from './img/hr-logo.png'
import plusLogo from './img/plus-logo.png'
import mlogo from './img/m-logo.png'
import mhrLogo from './img/m-hr-logo.png'
import mplusLogo from './img/m-plus-logo.png'
export default {
name: 'Logo',
props: {
type: {
default: 'xiaoyanyun'
},
href: {
default: '/'
}
},
computed: {
src: function () {
if (this.type === 'xiaoyanyun') {
return logo
}
if (this.type === 'zhongtai') {
return zlogo
}
if (this.type === 'mzhichou') {
return mlogo
}
if (this.type === 'hr') {
return hrLogo
}
if (this.type === 'mhr') {
return mhrLogo
}
if (this.type === 'plus') {
return plusLogo
}
if (this.type === 'mplus') {
return mplusLogo
}
}
},
methods: {
onClick: function (e) {
if(this.type==="xiaoyanyun"){
location.assign(this.href)
}
}
}
}
</script>

37
src/components/Page.vue Normal file
View File

@@ -0,0 +1,37 @@
<template>
<div :class="cls">
<slot></slot>
<zui-toast v-if="toastText!==''">
{{toastText}}
</zui-toast>
<zui-loading v-if="loadingVisible"/>
</div>
</template>
<script>
import './less/page.less'
import '../assets/css/vivify.min.css'
import ZuiToast from './Toast'
import ZuiLoading from './Loading'
import Util from '../Util'
export default {
props: {
title: '智聪'
},
components: {
ZuiToast,
ZuiLoading
},
computed: {
cls () {
return 'zui-page'
},
toastText () {
return this.$store.state.toastText
},
loadingVisible () {
return this.$store.state.loadingVisible
}
}
}
</script>

9
src/components/Toast.vue Normal file
View File

@@ -0,0 +1,9 @@
<template>
<div class="zui-toast">
<slot></slot>
</div>
</template>
<script>
import './less/toast.less'
export default {}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
src/components/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

View File

@@ -0,0 +1,24 @@
@import "./mixin";
.@{prefix}-button{
color: #fff;
font-size: 14px;
line-height: 50px;
border-radius: 10px;
background: linear-gradient(135deg, #00b8ff, #007bff);
border: none;
min-width: 190px;
box-shadow: 0 0 0 rgba(0, 212, 255, 0);
transition: all .2s ease;
.cursor();
}
.@{prefix}-button:hover{
background: linear-gradient(135deg, #00c2ff, #0088ff);
box-shadow: 0 0 12px rgba(0, 212, 255, 0.5);
}
.@{prefix}-button:active{
background: linear-gradient(135deg, #00a8f0, #006fe6);
transform: translateY(1px);
}

View File

@@ -0,0 +1,126 @@
.customer-case {
margin: 0 auto;
max-width: 1120px;
padding: 90px 0 100px 0;
h2 {
color: #F7931E;
font-size: 40px;
text-align: center;
}
p {
color: #808080;
font-size: 20px;
text-align: center;
margin-top: 15px;
}
.customer-case-carousel {
margin-top: 35px;
.customer-case-carousel-item {
float: left;
max-width: 540px;
min-height: 320px;
margin: 10px;
padding: 20px 0;
background: #DEF0EF;
border: 2px dashed #6AC2B5;
position: relative;
&:after {
clear: both;
content: '';
display: table;
}
h3 {
font-size: 30px;
text-align: center;
margin: 0 50px;
padding: 0 0 10px 0;
border-bottom: 3px solid #6AC2B5;
}
h5{
color: #808080;
font-size: 20px;
text-align: center;
font-weight: normal;
margin-top: 10px;
}
.labels{
position: relative;
.zui-label {
top: -5px;
left: 20px;
display: block;
min-width: 116px;
position: absolute;
&:nth-child(2){
top: 50px;
}
}
p {
color: #000;
font-size: 25px;
text-align: left;
padding: 0 30px 0 165px;
margin-top: 20px;
}
}
}
}
}
@media (max-width: 420px) {
.customer-case{
max-width: 100%;
padding: 25px 10px;
h2{
font-size:24px;
}
p{
font-size: 12px;
margin-top: 10px;
}
.customer-case-carousel{
margin-top: 25px;
.customer-case-carousel-item{
margin: 10px 0;
padding: 10px 0;
min-width: 100%;
min-height: auto;
h3{
font-size: 16px;
margin: 0 20px;
}
h5{
font-size: 12px;
}
.labels{
.zui-label{
top: -5px;
left: 20px;
font-size: 12px;
min-width: 85px;
&:nth-child(2){
top: 30px;
}
}
p{
font-size: 14px;
margin: 10px 0 0 0;
padding: 0 20px 0 125px;
}
}
}
.VueCarousel-pagination{
.VueCarousel-dot-container{
.VueCarousel-dot{
margin-top: 0!important;
padding: 5px!important;
.VueCarousel-dot-inner{
width: 8px!important;
height: 8px!important;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,38 @@
.zui-flag {
padding: 20px 20px 0 20px;
width: 170px;
margin-bottom: 85px;
background: #32ADC6;
position: relative;
.zui-flag-border{
color: #fff;
font-size: 14px;
line-height: 40px;
width: 130px;
height: 117px;
border-top: 3px solid #fff;
border-left: 3px solid #fff;
border-right: 3px solid #fff;
display: inline-block;
}
.zui-label-triangle {
width: 0;
height: 0;
border-left: 85px solid transparent;
border-right: 85px solid transparent;
border-top: 80px solid #32ADC6;
bottom: -80px;
left: 0;
position: absolute;
}
.zui-label-small-triangle {
width: 0;
height: 0;
border-left: 85px solid transparent;
border-right: 85px solid transparent;
border-top: 80px solid #32ADC6;
bottom: -80px;
left: 0;
position: absolute;
}
}

View File

@@ -0,0 +1,102 @@
@import './mixin';
.@{prefix}-footer {
width: 100%;
min-height: 125px;
background: #646464;
padding: 40px 0 0 0;
border-top: 1px solid rgba(255,255,255,0.25);
.links {
color: #fff;
font-size: 16px;
text-align: center;
a {
color: #fff;
&:after {
content: '|';
margin: 0 10px;
}
&:last-child:after {
content: '';
}
&:hover {
color: #35A3BA;
&:after {
color: #fff;
}
}
}
br {
display: none;
}
}
.copy-right {
color: #fff;
font-size: 12px;
text-align: center;
margin: 8px 0 0 0;
padding-bottom: 10px;
}
.footer-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 12px;
padding: 0 16px;
}
.footer-qrcode img {
display: block;
max-width: 270px;
height: auto;
}
}
@media (max-width: 768px) {
.@{prefix}-footer {
padding: 25px 15px 15px 15px;
.footer-content {
flex-direction: column;
gap: 15px;
padding: 0;
}
.footer-qrcode {
width: 100%;
text-align: center;
}
.footer-qrcode img {
width: 200px !important;
max-width: 200px;
height: auto !important;
margin: 0 auto 10px;
}
.links {
width: 100%;
padding: 0 5px;
a {
display: inline-block;
margin: 0 3px;
padding: 4px 6px;
font-size: 11px;
line-height: 1.6;
border-radius: 4px;
&:after {
content: none;
}
}
br {
display: block;
}
img {
width: 14px !important;
height: 16px !important;
vertical-align: middle;
}
}
.copy-right {
font-size: 11px;
padding: 10px 5px;
line-height: 1.5;
}
}
}

View File

@@ -0,0 +1,57 @@
.zui-form {
.zui-form-item {
font-size: 0;
margin: 15px 0;
.zui-form-label {
font-size: 16px;
min-width: 95px;
text-align: right;
display: inline-block;
padding: 10px 30px 10px 0;
}
.zui-form-input{
min-width: 610px;
font-size: 16px;
line-height: 50px;
padding: 0 10px;
border: 1px solid #B3B3B3;
background: #F2F2F2;
&:focus{
border-color: #F7931E;
}
}
.zui-button{
min-width: 610px;
}
}
}
@media (max-width: 420px) {
.zui-form{
padding: 20px;
.zui-form-item{
margin: 10px 0;
position: relative;
.zui-form-label{
padding: 0;
text-align: left;
line-height: 25px;
top: 2px;
left: 5px;
position: absolute;
}
.zui-form-input{
width: 100%;
min-width: 100px;
line-height: 25px;
padding-left: 75px;
text-align: right;
}
.zui-button{
margin: 0;
width: 100%;
min-width: 100px;
line-height: 30px;
}
}
}
}

View File

@@ -0,0 +1,116 @@
@import "./mixin.less";
.@{prefix}-header {
width: 100%;
height: 100px;
background: rgba(255,255,255,0.75);
backdrop-filter: saturate(180%) blur(8px);
box-shadow: 0 4px 14px rgba(16,24,40,0.08);
position: sticky;
top: 0;
z-index: 100;
.float-clear;
.@{prefix}-logo{
width: 135px;
height: 100px;
margin: 0 0 0 20px;
float: left;
}
.@{prefix}-logo-text{
float: left;
height: 100px;
color: #36A4BB;
font-size: 16px;
// padding-top: 28px;
line-height: 100px;
text-align: center;
margin: 0 0 0 0px;
}
.@{prefix}-logo-text a{
color: var(--color-text);
text-decoration: none;
margin: 0 8px;
font-weight: 600;
}
.@{prefix}-logo-text a:hover{
color: var(--color-accent);
text-decoration: underline;
}
.@{prefix}-button{
float: right;
line-height: 40px;
margin: 30px 30px 0 0;
min-width: 100px;
}
.@{prefix}-rightcol{
display: none;
}
.@{prefix}-logo-line {
width: 1px;
height: 45px;
top: 30px;
left: 10px;
float: left;
position: relative;
background: #32adc6;
}
}
@media (max-width: 768px) {
.@{prefix}-header{
height: 60px;
.zui-logo{
height: 60px;
width: 100px;
margin: 0 0 0 10px;
}
.@{prefix}-logo-text{
height: 60px;
line-height: 60px;
font-size: 10px;
margin: 0;
a {
margin: 0 4px;
font-size: 10px;
}
}
.@{prefix}-button{
display: none !important;
}
.@{prefix}-rightcol{
display: flex !important;
align-items: center;
justify-content: center;
font-size: 14px;
float: right;
line-height: 35px;
margin: 12px 10px 0 0;
min-width: 60px;
padding: 0 12px;
font-weight: bold;
color: #fff;
background: linear-gradient(135deg, #35A3BA, #0088ff);
border-radius: 6px;
cursor: pointer;
box-shadow: 0 2px 6px rgba(53, 163, 186, 0.3);
transition: all 0.2s ease;
}
.@{prefix}-rightcol:active {
transform: scale(0.96);
box-shadow: 0 1px 3px rgba(53, 163, 186, 0.4);
}
.@{prefix}-logo-line {
display: none;
}
}
}
@media (min-width: 769px) {
.@{prefix}-header{
.@{prefix}-rightcol{
display: none !important;
}
}
}

View File

@@ -0,0 +1,35 @@
.zui-label {
color: #fff;
font-size: 14px;
line-height: 40px;
text-align: center;
padding: 0 20px;
margin-right: 20px;
background: #6AC2B5;
position: relative;
display: inline-block;
.zui-label-triangle {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-left: 20px solid #6AC2B5;
border-bottom: 20px solid transparent;
right: -20px;
top: 0;
position: absolute;
}
}
@media (max-width: 420px) {
.zui-label{
line-height: 25px;
padding: 0 10px;
min-width: 85px;
.zui-label-triangle{
border-top: 11px solid transparent;
border-left: 12px solid #6AC2B5;
border-bottom: 15px solid transparent;
right: -11px;
}
}
}

View File

@@ -0,0 +1,151 @@
@import './mixin';
.@{prefix}-loading {
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
width: 3em;
height: 3em;
margin: auto;
position: fixed;
-webkit-animation: rotate .8s linear infinite;
-moz-animation: rotate .8s linear infinite;
-o-animation: rotate .8s linear infinite;
animation: rotate .8s linear infinite;
.@{prefix}-loading-content{
.@{prefix}-loading-dot{
position: absolute;
margin: auto;
width: 1em;
height: 1em;
border-radius: 100%;
-webkit-transition: all .8s ease;
-moz-transition: all .8s ease;
-o-transition: all .8s ease;
transition: all .8s ease;
&.white {
top: 0;
bottom: 0;
left: 0;
right: 0;
background: white;
opacity: 0;
-webkit-animation: flash .8s linear infinite;
-moz-animation: flash .8s linear infinite;
-o-animation: flash .8s linear infinite;
animation: flash .8s linear infinite;
}
&:nth-child(2) {
top: 0;
bottom: 0;
left: 0;
background: #FF4444;
-webkit-animation: dotsY .8s linear infinite;
-moz-animation: dotsY .8s linear infinite;
-o-animation: dotsY .8s linear infinite;
animation: dotsY .8s linear infinite;
}
&:nth-child(3) {
left: 0;
right: 0;
top: 0;
background: #FFBB33;
-webkit-animation: dotsX .8s linear infinite;
-moz-animation: dotsX .8s linear infinite;
-o-animation: dotsX .8s linear infinite;
animation: dotsX .8s linear infinite;
}
&:nth-child(4) {
top: 0;
bottom: 0;
right: 0;
background: #99CC00;
-webkit-animation: dotsY .8s linear infinite;
-moz-animation: dotsY .8s linear infinite;
-o-animation: dotsY .8s linear infinite;
animation: dotsY .8s linear infinite;
}
&:nth-child(5) {
left: 0;
right: 0;
bottom: 0;
background: #33B5E5;
-webkit-animation: dotsX .8s linear infinite;
-moz-animation: dotsX .8s linear infinite;
-o-animation: dotsX .8s linear infinite;
animation: dotsX .8s linear infinite;
}
}
@keyframes rotate {
0% {
-webkit-transform: rotate(0);
-moz-transform: rotate(0);
-o-transform: rotate(0);
transform: rotate(0);
}
10% {
width: 3em;
height: 3em;
}
66% {
width: 1em;
height: 1em;
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
width: 3em;
height: 3em;
}
}
@keyframes dotsY {
66% {
opacity: .1;
width: 1em;
}
77% {
opacity: 1;
width: 0;
}
}
@keyframes dotsX {
66% {
opacity: .1;
height: 1em;
}
77% {
opacity: 1;
height: 0;
}
}
@keyframes flash {
33% {
opacity: 0;
border-radius: 0%;
}
55% {
opacity: .6;
border-radius: 100%;
}
66% {
opacity: 0;
}
}
}
}

View File

@@ -0,0 +1,5 @@
.zui-logo {
width: 150px;
height: 52px;
cursor: pointer;
}

View File

@@ -0,0 +1,280 @@
.transform(@t) {
-webkit-transform: @t;
transform: @t;
}
.transform-origin(@to) {
-webkit-transform-origin: @to;
transform-origin: @to;
}
.transition(@value) {
-webkit-transition: @value;
}
.hairline-top(@color) {
&:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: auto;
right: auto;
height: 2px;
width: 100%;
background-color: transparent;
border-top: 1px solid @color;
display: block;
z-index: 15;
.transform-origin(50% 0%);
html.pixel-ratio-2 & {
.transform(scaleY(0.5));
}
html.pixel-ratio-3 & {
.transform(scaleY(0.33));
}
html.pixel-ratio-4 & {
.transform(scaleY(0.25));
}
}
}
.hairline-left(@color) {
&:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: auto;
right: auto;
width: 1px;
height: 100%;
background-color: @color;
display: block;
z-index: 15;
.transform-origin(0% 50%);
html.pixel-ratio-2 & {
.transform(scaleX(0.5));
}
html.pixel-ratio-3 & {
.transform(scaleX(0.33));
}
html.pixel-ratio-4 & {
.transform(scaleX(0.25));
}
}
}
.hairline-bottom(@color, @left:0) {
&:after {
content: '';
position: absolute;
left: @left;
bottom: 0;
right: auto;
top: auto;
height: 2px;
width: 100%;
background-color: transparent;
border-bottom: 1px solid @color;
display: block;
z-index: 15;
.transform-origin(50% 100%);
html.pixel-ratio-2 & {
.transform(scaleY(0.5));
}
html.pixel-ratio-3 & {
.transform(scaleY(0.33));
}
html.pixel-ratio-4 & {
.transform(scaleY(0.25));
}
}
}
.hairline-right(@color) {
&:after {
content: '';
position: absolute;
right: 0;
top: 0;
left: auto;
bottom: auto;
width: 1px;
height: 100%;
background-color: @color;
display: block;
z-index: 15;
.transform-origin(100% 50%);
html.pixel-ratio-2 & {
.transform(scaleX(0.5));
}
html.pixel-ratio-3 & {
.transform(scaleX(0.33));
}
html.pixel-ratio-4 & {
.transform(scaleX(0.25));
}
}
}
// For right and bottom
.hairline-remove-right-bottom {
&:after {
display: none;
}
}
// For left and top
.hairline-remove-left-top {
&:before {
display: none;
}
}
// Encoded SVG Background
.encoded-svg-background(@svg) {
@url: `encodeURIComponent(@{svg})`;
background-image: url("data:image/svg+xml;charset=utf-8,@{url}");
}
.align-self(@as) {
-ms-flex-item-align: @as;
-webkit-align-self: @as;
align-self: @as;
}
.ellipsis() {
width: auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.backgroundSize(@width,@height) {
-webkit-background-size: @width @height;
}
.display-box() {
display: flex;
}
.flex-direction(@direction: row) {
flex-direction: @direction;
}
.flex-wrap(@wrap: nowrap) {
flex-wrap: @wrap;
}
.flex-justify(@justify: flex-start) {
justify-content: @justify;
}
.box-align(@align: center) {
align-items: @align;
}
.box-align-content(@alignContent: stretch) {
align-content: @alignContent;
}
.box-flex(@scale: 1) {
flex: @scale;
}
.border-radius(@radius: 0) {
border-top-left-radius: @radius;
border-top-right-radius: @radius;
border-bottom-left-radius: @radius;
border-bottom-right-radius: @radius;
-webkit-background-clip: padding-box;
}
.background(@start: #ffffff, @end: #000000) {
background: @end;
background-image: -webkit-gradient(linear, left top, left bottom, from(@start), to(@end)); /* Saf4+, Chrome */
background-image: linear-gradient(@start, @end);
}
.border-1px-bottom(@color: #d2d2d2) {
background: left bottom repeat-x;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(.5, transparent), color-stop(.5, @color), to(@color));
background-image: linear-gradient(left top, left bottom, color-stop(.5, transparent), color-stop(.5, @color), to(@color));
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
.border-1px-top(@color: #d2d2d2) {
background: left top repeat-x;
background-image: -webkit-gradient(linear, left top, left bottom, from(@color), color-stop(.5, @color), color-stop(.5, transparent));
background-image: linear-gradient(left top, left bottom, from(@color), color-stop(.5, @color), color-stop(.5, transparent));
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
.border-1px-both(@color: #d2d2d2) {
background-position: left top, left bottom;
background-repeat: repeat-x, repeat-x;
background-image: -webkit-gradient(linear, left top, left bottom, from(@color), color-stop(.5, @color), color-stop(.5, transparent)), -webkit-gradient(linear, left top, left bottom, color-stop(.5, transparent), color-stop(.5, @color), to(@color));
background-image: linear-gradient(left top, left bottom, from(@color), color-stop(.5, @color), color-stop(.5, transparent)), linear-gradient(left top, left bottom, color-stop(.5, transparent), color-stop(.5, @color), to(@color));
-webkit-background-size: 100% 1px, 100% 1px;
background-size: 100% 1px, 100% 1px;
}
.border-1px-scale(@color: #d2d2d2) {
position: relative;
&:before {
content: '';
position: absolute;
bottom: -1px;
left: 0px;
right: 0px;
border-bottom: 1px solid @color;
-webkit-transform: scaleY(.5);
-webkit-transform-origin: 0px 0px;
}
}
.box-sizing(@sizing: border-box) {
-webkit-box-sizing: @sizing;
}
.box-shadow(@value) {
-webkit-box-shadow: @value;
}
.box-shadow(@value1, @value2) {
-webkit-box-shadow: @value1, @value2;
}
.ellipsis(@w:auto) {
width: @w;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
}
.float-clear() {
&:after {
visibility: hidden;
display: block;
font-size: 0px;
content: ' ';
clear: both;
height: 0px;
}
}
.cursor() {
cursor: pointer;
}
.overflow-scroll() {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
@colorMain: #6ac2b6;
@prefix: zui;

View File

@@ -0,0 +1,109 @@
@import './reset.less';
:root {
--color-bg: #edf7f7;
--color-text: #1f2a37;
--color-accent: #35A3BA;
--color-accent-strong: #0ea5b7;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--radius-1: 10px;
--radius-2: 16px;
--shadow-1: 0 2px 8px rgba(16,24,40,.06);
--shadow-2: 0 8px 24px rgba(16,24,40,.08);
--transition-fast: 180ms;
}
.zui-page {
width: 100%;
min-height: 100%;
margin: 0 auto;
font-family: "微软雅黑", "Helvetica Neue", Helvetica, Arial, sans-serif;
background: var(--color-bg);
color: var(--color-text);
a {
text-decoration: none;
}
a:hover {
color: #35A3BA;
text-decoration: underline;
}
.zui-nav-link {
text-decoration: none;
color: inherit;
margin-left: 12px;
}
.zui-nav-link:hover {
text-decoration: underline;
color: #35A3BA;
}
.zui-nav-link--mobile {
font-size: 12px;
}
.clear:after {
content: '';
display: table;
clear: both;
}
}
/* Drawer menu */
.zui-drawer-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
z-index: 999;
}
.zui-drawer {
position: fixed;
top: 0;
right: 0;
width: 70%;
max-width: 300px;
height: 100%;
background: #fff;
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.06);
z-index: 1000;
padding: 16px;
}
.zui-drawer__header {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #333;
}
.zui-drawer__list {
list-style: none;
margin: 0;
padding: 0;
}
.zui-drawer__list li {
padding: 12px 8px;
border-bottom: 1px solid #f0f0f0;
}
.zui-drawer__list li:hover {
background: #f6f8fa;
cursor: pointer;
}
@media (max-width: 600px) {
.zui-page {
overflow-x: hidden;
}
}
@media (min-width: 1200px) {
.zui-drawer,
.zui-drawer-overlay {
display: none;
}
}
@media (min-width: 1200px) {
.zui-page {
min-width: 1200px;
}
}

View File

@@ -0,0 +1,84 @@
* {
margin: 0;
padding: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
html {
-ms-touch-action: none;
}
html, body {
-webkit-text-size-adjust: none;
margin: 0;
height: 100%;
font-size: 14px !important;
::-webkit-scrollbar {
width: 0;
}
}
ul,
ol {
list-style: none;
}
a {
color: #32ADC6;
text-decoration: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
button {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
input, button, textarea {
-webkit-appearance: none;
appearance: none;
border: none;
outline: none;
}
input:active, textarea:active, select:active {
border: none;
}
input, textarea, select {
font-size: 14px;
}
img {
border: none;
}
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
/* WebKit browsers */
color: #999;
}
input:-moz-placeholder, textarea:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #999;
}
input::-moz-placeholder, textarea::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #999;
}
input:-ms-input-placeholder, textarea:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #999;
}
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
width: 0;
height: 0;
}

View File

@@ -0,0 +1,23 @@
@import "./mixin";
.@{prefix}-toast{
top: 50%;
left: 50%;
width: 250px;
padding: 20px;
position: fixed;
color: #fff;
font-size: 16px;
text-align: center;
border-radius: 10px;
background: rgba(0,0,0,.7);
animation: toastScaleIn .2s ease forwards;
@keyframes toastScaleIn {
0%{
transform: scale(.8, .8) translate(-50%, -50%);
}
100%{
transform: scale(1, 1) translate(-50%, -50%);
}
}
}

View File

@@ -0,0 +1,44 @@
$color-blue: #26a2ff;
$color-white: #fff;
$color-grey: #d9d9d9;
$border-color: #c8c8cd;
$success-color: #4caf50;
$error-color: #f44336;
$warning-color: #ffc107;
/* Cell Component */
$cell-value-color: #888;
/* Header Component */
$header-height: 40px;
/* Button Component */
$button-default-color: #656b79;
$button-default-background-color: #f6f8fa;
$button-default-plain-color: #5a5a5a;
$button-default-box-shadow: 0 0 1px #b8bbbf;
$button-primary-color: #fff;
$button-primary-background-color: #26a2ff;
$button-danger-color: #fff;
$button-danger-background-color: #ef4f4f;
/* Tab Item Component */
$tab-item-font-size: 12px;
/* Tabbar Component */
$tabbar-background-color: #fafafa;
$tabbar-tab-item-selected-background-color: #eaeaea;
$tabbar-tab-item-selected-color: $color-blue;
/* Navbar Component */
$navbar-background-color: #fafafa;
$tabbar-tab-item-selected-background-color: #eaeaea;
/* Checklist Component */
$checklist-title-color: #888;
/* Radio Component */
$radio-title-color: #888;
/* z-index */
$z-index-normal: 1;

12
src/main.js Normal file
View File

@@ -0,0 +1,12 @@
import Vue from 'vue'
import store from './store'
import router from './router'
import App from './components/App'
new Vue({
router,
store,
template: '<App/>',
components: { App }
}).$mount('#app')

16
src/router/index.js Normal file
View File

@@ -0,0 +1,16 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const HomePage = () => import('../views/HomePage')
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [{
path: '/',
component: HomePage
}]
});
export default router;

View File

@@ -0,0 +1,81 @@
'use strict'
import jsonp from 'jsonp'
import store from '../store'
const buildQuery = (data) => {
let query = ''
for (let i in data) {
let queryItem = ''
if (Object.prototype.toString.call(data[i]) === '[object Array]') {
queryItem = data[i].map((item, key) => {
return i + '[' + key + ']=' + item
}).join('&')
} else {
queryItem = i + '=' + encodeURIComponent(data[i])
}
query += queryItem + '&'
}
return query.substr(0, query.length - 1)
}
const buildUrl = (path, data) => {
const protocol = location.href.indexOf('https') === -1 ? 'http://' : 'https://'
const host = path.indexOf('//') === -1 ? protocol + process.env.API_HOST + '/' : ''
const query = data ? '?' + buildQuery(data) : ''
return host + path + query
}
const beforeSend = (data) => {
if (data && data.loading === false) {
store.commit('loading', false)
} else {
store.commit('loading', true)
window.ajaxnum = (window.ajaxnum || 0) + 1
}
}
const afterSend = (data) => {
store.commit('loading', false)
window.ajaxnum = (window.ajaxnum || 0) + 1
}
const onStatusError = (res) => {
if (res.status === 40001) {
store.commit('requireLogin')
return false
}
store.commit('toast', res.message || '请求错误, 请稍候重试')
}
const onRequestError = (err) => {
store.commit('requestError', err)
}
export default class BaseService {
/**
* send jsonp request
* @param url
* @param data
* @param onSuccess
* @param onError
*/
static jsonp = (url, data, onSuccess, onError) => {
beforeSend(data)
jsonp(buildUrl(url, data), {
timeout: 10000
}, (err, res) => {
afterSend(res)
if (err != null) {
onRequestError(err)
return false
}
if (res.status !== 0 && res.status !== 40006 && res.status !== 80001) {
onStatusError(res)
return false
}
onSuccess && onSuccess(res)
})
}
}

View File

@@ -0,0 +1,7 @@
import BaseService from './BaseService'
export default class FeedbackService {
static create = (data, success) => {
BaseService.jsonp('feedback/create', data, success)
}
}

View File

@@ -0,0 +1,7 @@
import BaseService from './BaseService'
export default class UserService {
static feedback = (data, success) => {
BaseService.jsonp('user/feedback', data, success)
}
}

28
src/store/index.js Normal file
View File

@@ -0,0 +1,28 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
toastText: '',
loadingVisible: false
},
mutations: {
increment (state) {
state.count++
},
toast (state, text) {
state.toastText = text
setTimeout(() => {
state.toastText = ''
}, 2000)
},
loading (state, loadingVisible) {
state.loadingVisible = loadingVisible
},
requireLogin (state) {
const host = process.env.NODE_ENV === 'development' ? 'wxtest.zhichou.com' : 'wx.zhichou.com'
location.assign('http://' + host + '/#/me/login?rurl=' + encodeURIComponent(location.href))
}
}
})

610
src/views/HomePage.vue Normal file
View File

@@ -0,0 +1,610 @@
<template>
<page class="home-page workbench-page">
<div class="workbench-header">
<h1>Qdintc - 统一工作平台</h1>
</div>
<div class="workbench-container">
<div class="tools-container">
<!-- 代码管理 -->
<div class="tool-category" v-if="codeTools.length > 0">
<h2 class="category-title">代码管理</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in codeTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 持续集成 -->
<div class="tool-category" v-if="ciTools.length > 0">
<h2 class="category-title">持续集成</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in ciTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 项目管理 -->
<div class="tool-category" v-if="projectTools.length > 0">
<h2 class="category-title">项目管理</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in projectTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 数据库 -->
<div class="tool-category" v-if="databaseTools.length > 0">
<h2 class="category-title">数据库</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in databaseTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 监控告警 -->
<div class="tool-category" v-if="monitorTools.length > 0">
<h2 class="category-title">监控告警</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in monitorTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 文档知识 -->
<div class="tool-category" v-if="docTools.length > 0">
<h2 class="category-title">文档知识</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in docTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 测试工具 -->
<div class="tool-category" v-if="testTools.length > 0">
<h2 class="category-title">测试工具</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in testTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 安全扫描 -->
<div class="tool-category" v-if="securityTools.length > 0">
<h2 class="category-title">安全扫描</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in securityTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 云平台 -->
<div class="tool-category" v-if="cloudTools.length > 0">
<h2 class="category-title">云平台</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in cloudTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
<!-- 其他工具 -->
<div class="tool-category" v-if="otherTools.length > 0">
<h2 class="category-title">其他工具</h2>
<div class="category-items">
<div class="tool-card" v-for="tool in otherTools" :key="tool.name" @click="openTool(tool.url)">
<div class="tool-icon" :style="{background: tool.color}">
<span class="icon-text">{{ tool.icon }}</span>
</div>
<div class="tool-info">
<h4 class="tool-name">{{ tool.name }}</h4>
<p class="tool-desc">{{ tool.desc }}</p>
<p class="tool-url">{{ tool.displayUrl }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</page>
</template>
<script>
import './less/home-page.less'
import Page from '../components/Page'
export default{
components: {Page},
data () {
return {
// 代码管理工具
codeTools: [
{
name: 'Gitea',
desc: 'Git代码仓库管理',
url: 'http://your-gitea-url.com',
displayUrl: 'gitea.company.com',
icon: 'Git',
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
},
{
name: 'GitLab',
desc: 'DevOps生命周期工具',
url: 'http://your-gitlab-url.com',
displayUrl: 'gitlab.company.com',
icon: 'GL',
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)'
}
],
// 持续集成工具
ciTools: [
{
name: 'Jenkins',
desc: '持续集成构建平台',
url: 'http://your-jenkins-url.com',
displayUrl: 'jenkins.company.com',
icon: 'JK',
color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)'
},
{
name: 'Harbor',
desc: 'Docker镜像仓库',
url: 'http://your-harbor-url.com',
displayUrl: 'harbor.company.com',
icon: 'HB',
color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)'
}
],
// 项目管理工具
projectTools: [
{
name: '禅道',
desc: '项目管理与Bug追踪',
url: 'http://your-zentao-url.com',
displayUrl: 'zentao.company.com',
icon: '禅',
color: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)'
},
{
name: 'Jira',
desc: '敏捷项目管理工具',
url: 'http://your-jira-url.com',
displayUrl: 'jira.company.com',
icon: 'JR',
color: 'linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%)'
}
],
// 数据库工具
databaseTools: [
{
name: 'MySQL',
desc: 'MySQL数据库管理',
url: 'http://your-mysql-url.com',
displayUrl: 'mysql.company.com',
icon: 'SQL',
color: 'linear-gradient(135deg, #f8b500 0%, #fceabb 100%)'
},
{
name: 'Redis',
desc: '缓存数据库管理',
url: 'http://your-redis-url.com',
displayUrl: 'redis.company.com',
icon: 'RD',
color: 'linear-gradient(135deg, #e43a15 0%, #e65245 100%)'
}
],
// 监控告警工具
monitorTools: [
{
name: 'Grafana',
desc: '监控数据可视化',
url: 'http://your-grafana-url.com',
displayUrl: 'grafana.company.com',
icon: 'GF',
color: 'linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%)'
},
{
name: 'Prometheus',
desc: '系统监控告警平台',
url: 'http://your-prometheus-url.com',
displayUrl: 'prometheus.company.com',
icon: 'PM',
color: 'linear-gradient(135deg, #d299c2 0%, #fef9d7 100%)'
}
],
// 文档知识工具
docTools: [
{
name: 'Confluence',
desc: '团队协作知识库',
url: 'http://your-confluence-url.com',
displayUrl: 'wiki.company.com',
icon: 'CF',
color: 'linear-gradient(135deg, #fbc2eb 0%, #a6c1ee 100%)'
},
{
name: 'GitBook',
desc: '文档编写平台',
url: 'http://your-gitbook-url.com',
displayUrl: 'docs.company.com',
icon: 'GB',
color: 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)'
}
],
// 测试工具
testTools: [
{
name: 'Selenium',
desc: '自动化测试平台',
url: 'http://your-selenium-url.com',
displayUrl: 'test.company.com',
icon: 'SE',
color: 'linear-gradient(135deg, #96fbc4 0%, #f9f586 100%)'
},
{
name: 'Postman',
desc: 'API测试工具',
url: 'http://your-postman-url.com',
displayUrl: 'api-test.company.com',
icon: 'PM',
color: 'linear-gradient(135deg, #ff9966 0%, #ff5e62 100%)'
}
],
// 安全扫描工具
securityTools: [
{
name: 'SonarQube',
desc: '代码质量检测平台',
url: 'http://your-sonar-url.com',
displayUrl: 'sonar.company.com',
icon: 'SQ',
color: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)'
},
{
name: 'Trivy',
desc: '容器安全扫描',
url: 'http://your-trivy-url.com',
displayUrl: 'security.company.com',
icon: 'TV',
color: 'linear-gradient(135deg, #30cfd0 0%, #330867 100%)'
}
],
// 云平台工具
cloudTools: [
{
name: 'Kubernetes',
desc: '容器编排平台',
url: 'http://your-k8s-url.com',
displayUrl: 'k8s.company.com',
icon: 'K8s',
color: 'linear-gradient(135deg, #2af598 0%, #009efd 100%)'
},
{
name: 'Rancher',
desc: 'K8s集群管理',
url: 'http://your-rancher-url.com',
displayUrl: 'rancher.company.com',
icon: 'RC',
color: 'linear-gradient(135deg, #0ba360 0%, #3cba92 100%)'
}
],
// 其他工具
otherTools: [
{
name: 'Nexus',
desc: 'Maven私服仓库',
url: 'http://your-nexus-url.com',
displayUrl: 'nexus.company.com',
icon: 'NX',
color: 'linear-gradient(135deg, #fdcbf1 0%, #e6dee9 100%)'
},
{
name: 'Portainer',
desc: 'Docker容器管理',
url: 'http://your-portainer-url.com',
displayUrl: 'portainer.company.com',
icon: 'PT',
color: 'linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%)'
}
]
}
},
created() {
this.init()
},
methods: {
openTool: function (url) {
if(url && url !== 'http://your-gitea-url.com') {
window.open(url, '_blank')
} else {
alert('请先配置该工具的访问地址')
}
}
}
};
</script>
<style scoped lang="less">
.workbench-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 0;
padding-top: 76px;
}
.workbench-container {
max-width: 1920px;
margin: 0 auto;
padding: 30px 20px;
}
.workbench-header {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
text-align: center;
padding: 20px 0;
background: rgba(255,255,255,0.08);
z-index: 1000;
backdrop-filter: blur(15px);
border-bottom: 1px solid rgba(255,255,255,0.15);
h1 {
font-size: 32px;
font-weight: 700;
color: #fff;
margin: 0;
text-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
p {
font-size: 16px;
color: rgba(255,255,255,0.85);
margin: 8px 0 0 0;
}
}
.tools-container {
display: flex;
flex-wrap: wrap;
gap: 25px 20px;
align-items: flex-start;
}
.tool-category {
flex: 0 1 auto;
.category-title {
font-size: 20px;
font-weight: 600;
color: #fff;
margin-bottom: 15px;
padding-left: 12px;
border-left: 4px solid rgba(255,255,255,0.8);
line-height: 1.5;
}
.category-items {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
}
.tool-card {
display: flex;
align-items: center;
padding: 14px 18px;
background: rgba(255,255,255,0.95);
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
width: 260px;
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
background: #fff;
}
}
.tool-icon {
width: 60px;
height: 60px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-right: 16px;
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
.icon-text {
font-size: 24px;
font-weight: bold;
color: #fff;
text-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
}
.tool-info {
flex: 1;
min-width: 0;
}
.tool-name {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0 0 4px 0;
}
.tool-desc {
font-size: 13px;
color: #666;
margin: 0 0 4px 0;
}
.tool-url {
font-size: 12px;
color: #999;
font-family: 'Consolas', 'Monaco', monospace;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: 1024px) {
.tools-container {
gap: 25px 30px;
}
.tool-category {
flex-direction: column;
width: 100%;
.category-title {
width: auto;
text-align: left;
padding: 10px 12px;
}
.category-items {
width: 100%;
}
}
.tool-card {
width: calc(50% - 8px);
}
.workbench-header h1 {
font-size: 36px;
}
}
@media (max-width: 600px) {
.workbench-container {
padding: 30px 15px;
}
.workbench-header {
margin-bottom: 30px;
h1 {
font-size: 28px;
}
p {
font-size: 14px;
}
}
.tools-container {
gap: 20px;
}
.tool-category {
.category-title {
font-size: 16px;
padding: 8px 10px;
}
}
.tool-card {
padding: 14px;
width: 100%;
}
.tool-icon {
width: 50px;
height: 50px;
margin-right: 12px;
.icon-text {
font-size: 20px;
}
}
.tool-name {
font-size: 16px;
}
.tool-desc {
font-size: 12px;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
src/views/img/feature10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
src/views/img/feature11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
src/views/img/feature12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
src/views/img/feature13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
src/views/img/feature14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/views/img/feature8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
src/views/img/feature9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -0,0 +1,306 @@
.home-page {
overflow-x: hidden;
.banner {
text-align: center;
padding: 180px 20px;
background: url('../img/zhichou-banner.jpg') center no-repeat;
background-size: cover;
position: relative;
overflow: hidden;
&:before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(180deg, rgba(13,38,56,0.00) 0%, rgba(13,38,56,0.35) 100%);
pointer-events: none;
}
img {
top: 0;
left: 0;
right: 0;
width: 100%;
height: auto;
margin: 0 auto;
position: absolute;
}
h1 {
color: #fff;
font-size: 42px;
margin: 0;
text-shadow: 0 2px 12px rgba(0,0,0,0.25);
}
h3 {
color: #fff;
font-size: 24px;
margin-top: 28px;
text-shadow: 0 1px 6px rgba(0,0,0,0.2);
}
}
.nav {
padding-left: 0;
list-style: none;
max-width: 1065px;
margin: 20px auto 0 auto;
a {
float: left;
margin: 17px;
width: 320px;
color: #32ADC6;
text-align: center;
display: block;
padding: 60px 0 40px 0;
border: 1px solid #32ADC6;
position: relative;
&:hover {
text-decoration: none;
.watermark {
color: #fff !important;
}
.zui-logo {
display: none;
}
.zui-logo.mobile {
display: block;
}
}
&.zhichou:hover {
color: #fff;
background: #35A3BA;
}
&.hr:hover {
color: #fff;
background: #6AC2B5;
}
&.plus:hover {
color: #fff;
background: #35A3BA;
}
.watermark {
top: 0;
left: 0;
opacity: .1;
font-size: 70px;
line-height: 70px;
position: absolute;
&.blue {
color: #35A3BA;
}
&.green {
color: #00d6b2;
}
}
.zui-logo {
display: block;
margin: 0 auto;
}
.zui-logo.mobile {
display: none;
}
h3 {
font-size: 24px;
margin-top: 15px;
}
p {
font-size: 18px;
margin-top: 14px;
}
&.hr {
color: #6AC2B5;
border-bolor: #6AC2B5;
}
&.plus {
color: #35A3BA;
border-color: #35A3BA;
}
}
}
.join-zhichou {
color: #32ADC6;
font-size: 16px;
text-align: center;
width: 100%;
display: block;
margin: 30px 0 165px 0;
}
.service {
padding: 72px 0;
text-align: center;
h1 {
color: #6AC2B5;
font-size: 52px;
line-height: 70px;
}
h3 {
color: #000;
font-size: 40px;
margin-top: 15px;
}
h4 {
font-size: 29px;
line-height: 32px;
font-weight: normal;
margin-top: 40px;
}
}
.apply-hr {
color: #fff;
text-align: center;
background: #6AC2B5;
padding: 49px 0 50px 0;
h2 {
font-size: 39px;
}
h4 {
font-size: 29px;
font-weight: normal;
margin-top: 20px;
}
}
.features {
background: #DEF0EF;
padding: 50px 0;
ul{
max-width: 500px;
margin: 0 auto;
li {
margin-top: 20px;
padding: 10px 0 10px 100px;
position: relative;
img {
width: 80px;
top: 5px;
left: 0;
right: 10px;
position: absolute;
}
h4 {
font-size: 25px;
font-weight: bold;
}
p {
font-size: 25px;
font-weight: normal;
}
}
}
}
}
@media (max-width: 768px) {
.home-page {
overflow-x: hidden;
width: 100%;
.banner {
padding: 60px 15px;
h1 {
font-size: 20px;
line-height: 1.4;
.br {
display: block;
}
}
h3 {
font-size: 12px;
line-height: 1.5;
margin-top: 15px;
}
}
.nav {
margin: 20px auto 0 auto;
padding: 0 15px;
a {
float: none;
width: 100%;
max-width: 300px;
margin: 15px auto;
padding: 25px 15px;
&.zhichou {
color: #fff;
background: #32ADC6;
}
&.hr {
color: #fff;
background: #6AC2B5;
}
&.plus {
color: #fff;
background: #236579;
}
.watermark {
color: #fff !important;
font-size: 50px;
}
.zui-logo {
width: 100px;
display: none;
}
.zui-logo.mobile {
display: block;
}
h3 {
font-size: 16px;
margin-top: 10px;
}
h4 {
font-size: 12px;
}
}
}
.join-zhichou {
margin: 0 0 30px 0;
}
.service{
padding: 30px 15px;
h1{
font-size: 22px;
line-height: 32px;
}
h3{
font-size: 16px;
line-height: 24px;
}
h4{
font-size: 14px;
line-height: 22px;
margin-top: 20px;
}
}
.features{
padding: 25px 15px;
ul{
max-width: 100%;
padding: 0 10px;
li{
margin-top: 15px;
padding-left: 50px;
img{
width: 40px;
}
h4{
font-size: 16px;
}
p{
font-size: 13px;
}
}
}
}
.apply-hr{
padding: 25px 15px;
h2{
font-size: 18px;
line-height: 26px;
}
h4{
font-size: 14px;
line-height: 20px;
margin-top: 10px;
}
}
.apply-hr-form{
padding: 20px 15px;
}
}
}