feat(login): 移除企业微信登录选项并调整样式
- 从登录页面移除企业微信登录相关UI组件和功能代码
- 将页脚文字从"服务全球"更新为"服务全国"
- 调整登录卡片底部边距从26px增加到34px
- 更新品牌组件中的服务范围文案为"服务全国"
- 修改品牌Logo样式,移除白色背景和阴影,使用正片叠底混合模式
- 在登录页面增加 Claude IDE 配置文件忽略规则
- 新增全局设计令牌系统,包含颜色、圆角、阴影等设计变量
- 添加数字滚动动效Hook,支持千分位格式化和动画效果
| | |
| | | # Editor directories and files |
| | | .idea |
| | | .vscode |
| | | .claude |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å
¨å±è®¾è®¡ä»¤çï¼é¢è²ãåè§ãé´å½±ãé´è·ç»ä¸æ¥æº |
| | | // ç¨æ³ï¼var(--app-primary) çï¼æè²æ¨¡å¼æ html.dark èªå¨çæ |
| | | :root { |
| | | // åçä¸è¯ä¹è²ï¼å
å¶ä½¿ç¨ï¼ä»
ç¨äºå¼ºè°ãç¶æï¼ |
| | | --app-primary: #2c51d9; |
| | | --app-primary-hover: #4a6cf0; |
| | | --app-primary-soft: rgba(44, 81, 217, 0.08); |
| | | --app-success: #0f9960; |
| | | --app-success-soft: rgba(15, 153, 96, 0.1); |
| | | --app-warning: #d97706; |
| | | --app-warning-soft: rgba(217, 119, 6, 0.1); |
| | | --app-danger: #d54941; |
| | | --app-danger-soft: rgba(213, 73, 65, 0.1); |
| | | --app-info: #1377ef; |
| | | --app-info-soft: rgba(19, 119, 239, 0.1); |
| | | |
| | | // 表é¢ä¸çº¿æ¡ |
| | | --app-bg: #f4f6f9; |
| | | --app-surface: #ffffff; |
| | | --app-surface-hover: #f8fafc; |
| | | --app-border: #e8ecf1; |
| | | --app-divider: #f0f2f5; |
| | | |
| | | // æå |
| | | --app-text: #1d2129; |
| | | --app-text-secondary: #4e5969; |
| | | --app-text-tertiary: #86909c; |
| | | --app-text-inverse: #ffffff; |
| | | |
| | | // åè§ |
| | | --app-radius-sm: 6px; |
| | | --app-radius: 10px; |
| | | --app-radius-lg: 14px; |
| | | |
| | | // é´å½±ï¼ä½é¥±åãæµ
ï¼ |
| | | --app-shadow: 0 1px 2px rgba(29, 33, 41, 0.04); |
| | | --app-shadow-md: 0 4px 16px rgba(29, 33, 41, 0.06); |
| | | |
| | | // å¸å± |
| | | --app-gap: 16px; |
| | | --app-gap-lg: 20px; |
| | | --app-transition: 0.2s ease; |
| | | } |
| | | |
| | | // æè²æ¨¡å¼ï¼ä¸ element-plus dark åéåå |
| | | html.dark { |
| | | --app-primary-soft: rgba(74, 108, 240, 0.16); |
| | | --app-success-soft: rgba(15, 153, 96, 0.18); |
| | | --app-warning-soft: rgba(217, 119, 6, 0.18); |
| | | --app-danger-soft: rgba(213, 73, 65, 0.18); |
| | | --app-info-soft: rgba(19, 119, 239, 0.18); |
| | | |
| | | --app-bg: #131720; |
| | | --app-surface: #1c212b; |
| | | --app-surface-hover: #232935; |
| | | --app-border: #2a3140; |
| | | --app-divider: #232935; |
| | | |
| | | --app-text: #e8eaee; |
| | | --app-text-secondary: #a6adba; |
| | | --app-text-tertiary: #7b8494; |
| | | |
| | | --app-shadow: none; |
| | | --app-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.35); |
| | | } |
| | | |
| | | // ç»ä¸é¢æ¿å¡ç |
| | | .app-panel { |
| | | background: var(--app-surface); |
| | | border: 1px solid var(--app-border); |
| | | border-radius: var(--app-radius); |
| | | box-shadow: var(--app-shadow); |
| | | } |
| | | |
| | | // ç宽æ°åï¼é¿å
æ°æ®è·³å¨ |
| | | .app-num { |
| | | font-variant-numeric: tabular-nums; |
| | | font-feature-settings: 'tnum'; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { ref, watch, onScopeDispose } from 'vue' |
| | | |
| | | const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches |
| | | |
| | | // æ°åæ»å¨ï¼åªå¨å¼ååæ¶å䏿¬¡ 500ms ç¼å¨ï¼å°éç³»ç»åå¼±å¨æè®¾ç½® |
| | | export function useCountUp(source, duration = 500) { |
| | | const display = ref(0) |
| | | let raf = 0 |
| | | |
| | | const run = (to) => { |
| | | const target = Number(to) |
| | | if (!isFinite(target)) { |
| | | display.value = 0 |
| | | return |
| | | } |
| | | if (reduceMotion || target === display.value) { |
| | | display.value = target |
| | | return |
| | | } |
| | | cancelAnimationFrame(raf) |
| | | const from = Number(display.value) || 0 |
| | | const start = performance.now() |
| | | const step = (now) => { |
| | | const p = Math.min((now - start) / duration, 1) |
| | | const eased = 1 - Math.pow(1 - p, 3) |
| | | display.value = from + (target - from) * eased |
| | | if (p < 1) raf = requestAnimationFrame(step) |
| | | } |
| | | raf = requestAnimationFrame(step) |
| | | } |
| | | |
| | | watch(source, (v) => run(v), { immediate: true }) |
| | | onScopeDispose(() => cancelAnimationFrame(raf)) |
| | | |
| | | return display |
| | | } |
| | | |
| | | // åå使 ¼å¼åï¼ä¿çæ´æ°æå°æ°ï¼ |
| | | export function formatNum(n, digits) { |
| | | const num = Number(n || 0) |
| | | if (digits !== undefined) { |
| | | return num.toLocaleString('zh-CN', { minimumFractionDigits: digits, maximumFractionDigits: digits }) |
| | | } |
| | | return num.toLocaleString('zh-CN') |
| | | } |
| | |
| | | </el-button> |
| | | </el-form> |
| | | |
| | | <div class="login-card__others"> |
| | | <div class="login-card__divider"> |
| | | <span>å
¶ä»ç»å½æ¹å¼</span> |
| | | </div> |
| | | <div class="login-card__wecom" @click="handleWecom"> |
| | | <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"> |
| | | <path fill="#2C51D9" d="M12 3C7.6 3 4 5.9 4 9.5c0 2 1.1 3.8 2.9 5l-.7 2.1 2.4-1.2c1 .3 2.1.5 3.4.5 4.4 0 8-2.9 8-6.4S16.4 3 12 3z"/> |
| | | <circle cx="9" cy="9.5" r="1" fill="#fff"/> |
| | | <circle cx="15" cy="9.5" r="1" fill="#fff"/> |
| | | </svg> |
| | | <span>ä¼ä¸å¾®ä¿¡ç»å½</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <p class="login-card__foot">å¥é½¿ç§æ · æå¡å
¨ç</p> |
| | | <p class="login-card__foot">å¥é½¿ç§æ · æå¡å
¨å½</p> |
| | | </div> |
| | | </main> |
| | | </div> |
| | |
| | | |
| | | function handleForgot() { |
| | | proxy.$modal.msg("请è系系ç»ç®¡çåéç½®å¯ç ") |
| | | } |
| | | |
| | | function handleWecom() { |
| | | proxy.$modal.msg("ä¼ä¸å¾®ä¿¡ç»å½ææªå¼æ¾") |
| | | } |
| | | |
| | | function getCookie() { |
| | |
| | | } |
| | | } |
| | | |
| | | .login-card__others { |
| | | margin-top: 26px; |
| | | } |
| | | |
| | | .login-card__divider { |
| | | position: relative; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | color: var(--app-text-tertiary, #86909c); |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | top: 50%; |
| | | height: 1px; |
| | | background: var(--app-border, #e8ecf1); |
| | | } |
| | | |
| | | span { |
| | | position: relative; |
| | | padding: 0 12px; |
| | | background: #fff; |
| | | } |
| | | } |
| | | |
| | | .login-card__wecom { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | margin-top: 18px; |
| | | font-size: 14px; |
| | | color: var(--app-text-secondary, #4e5969); |
| | | cursor: pointer; |
| | | transition: color var(--app-transition, 0.2s); |
| | | |
| | | &:hover { |
| | | color: var(--app-primary, #2c51d9); |
| | | } |
| | | } |
| | | |
| | | .login-card__foot { |
| | | margin: 26px 0 0; |
| | | margin: 34px 0 0; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | letter-spacing: 4px; |
| | |
| | | const features = [ |
| | | { icon: 'CircleCheck', label: 'åè´¨ä¿é', sub: '严æ§è´¨éæ å' }, |
| | | { icon: 'Setting', label: 'æºè½å¶é ', sub: 'æ°ååç产管ç' }, |
| | | { icon: 'Connection', label: 'æå¡å
¨ç', sub: 'å©åå£è
å¥åº·äºä¸' } |
| | | { icon: 'Connection', label: 'æå¡å
¨å½', sub: 'å©åå£è
å¥åº·äºä¸' } |
| | | ] |
| | | </script> |
| | | |
| | |
| | | .brand__logo { |
| | | position: relative; |
| | | z-index: 2; |
| | | // åå¾èªå¸¦ç½åºï¼æ£çå åºè®©ç½è²é¨åéåºèæ¯ï¼çæå»åº |
| | | mix-blend-mode: multiply; |
| | | |
| | | img { |
| | | height: 46px; |
| | | padding: 6px 12px; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 16px rgba(16, 42, 96, 0.08); |
| | | display: block; |
| | | height: 76px; |
| | | width: auto; |
| | | object-fit: contain; |
| | | } |
| | | } |