14 小时以前 533353dbeb19b3fa45817e9f65874db4e2ce6f9e
feat(login): 移除企业微信登录选项并调整样式

- 从登录页面移除企业微信登录相关UI组件和功能代码
- 将页脚文字从"服务全球"更新为"服务全国"
- 调整登录卡片底部边距从26px增加到34px
- 更新品牌组件中的服务范围文案为"服务全国"
- 修改品牌Logo样式,移除白色背景和阴影,使用正片叠底混合模式
- 在登录页面增加 Claude IDE 配置文件忽略规则
- 新增全局设计令牌系统,包含颜色、圆角、阴影等设计变量
- 添加数字滚动动效Hook,支持千分位格式化和动画效果
已添加2个文件
已修改3个文件
202 ■■■■■ 文件已修改
.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/tokens.scss 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/useCountUp.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/components/LoginBrand.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -13,6 +13,7 @@
# Editor directories and files
.idea
.vscode
.claude
*.suo
*.ntvs*
*.njsproj
src/assets/styles/tokens.scss
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
// å…¨å±€è®¾è®¡ä»¤ç‰Œï¼šé¢œè‰²ã€åœ†è§’、阴影、间距统一来源
// ç”¨æ³•: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';
}
src/views/home/useCountUp.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
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')
}
src/views/login.vue
@@ -57,21 +57,7 @@
          </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>
@@ -133,10 +119,6 @@
function handleForgot() {
  proxy.$modal.msg("请联系系统管理员重置密码")
}
function handleWecom() {
  proxy.$modal.msg("企业微信登录暂未开放")
}
function getCookie() {
@@ -251,51 +233,8 @@
  }
}
.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;
src/views/login/components/LoginBrand.vue
@@ -44,7 +44,7 @@
const features = [
  { icon: 'CircleCheck', label: '品质保障', sub: '严控质量标准' },
  { icon: 'Setting', label: '智能制造', sub: '数字化生产管理' },
  { icon: 'Connection', label: '服务全球', sub: '助力口腔健康事业' }
  { icon: 'Connection', label: '服务全国', sub: '助力口腔健康事业' }
]
</script>
@@ -72,13 +72,13 @@
.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;
  }
}