修复部分样式bug
This commit is contained in:
@@ -12,6 +12,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
this.username = username
|
||||
localStorage.setItem('isLoggedIn', 'true')
|
||||
localStorage.setItem('username', username)
|
||||
// 记住密码:按需求将密码持久化到 localStorage
|
||||
localStorage.setItem('rememberedPassword', password)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="conversation-list-container">
|
||||
<!-- 筛选表单折叠面板 -->
|
||||
<el-collapse v-model="activeCollapse" class="filter-collapse">
|
||||
<el-collapse v-model="activeCollapse" class="filter-collapse" size="small">
|
||||
<el-collapse-item name="filter">
|
||||
<template #title>
|
||||
<div class="collapse-header">
|
||||
@@ -14,7 +14,8 @@
|
||||
</template>
|
||||
<el-form :model="filterForm" inline label-width="80px" size="small">
|
||||
<el-form-item label="快捷范围">
|
||||
<el-select v-model="filterForm.quickRange" placeholder="请选择" clearable style="width: 150px" @change="handleQuickRangeChange">
|
||||
<el-select v-model="filterForm.quickRange" placeholder="请选择" clearable style="width: 150px"
|
||||
@change="handleQuickRangeChange">
|
||||
<el-option label="今天" value="today"></el-option>
|
||||
<el-option label="最近3天" value="last3"></el-option>
|
||||
<el-option label="最近7天" value="last7"></el-option>
|
||||
@@ -23,27 +24,13 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker
|
||||
v-model="filterForm.startDate"
|
||||
type="date"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
class="date-picker"
|
||||
@change="handleManualDateChange"
|
||||
/>
|
||||
<el-date-picker v-model="filterForm.startDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
clearable class="date-picker" @change="handleManualDateChange" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker
|
||||
v-model="filterForm.endDate"
|
||||
type="date"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
class="date-picker"
|
||||
@change="handleManualDateChange"
|
||||
/>
|
||||
<el-date-picker v-model="filterForm.endDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
clearable class="date-picker" @change="handleManualDateChange" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用户">
|
||||
@@ -74,22 +61,18 @@
|
||||
<el-scrollbar :style="{ height: scrollbarHeight }" @scroll="handleScroll">
|
||||
<div v-loading="loading" class="descriptions-container">
|
||||
<div v-for="(item, index) in conversationList" :key="index" class="descriptions-item">
|
||||
<el-descriptions :column="1" size="small" label-width="0px">
|
||||
<el-descriptions-item label="">
|
||||
{{ formatDateTime(item.recordTime) }} | {{ item.userName }} | {{ item.department }}
|
||||
<el-tag :type="item.messageType === 1 ? 'success' : ''">
|
||||
{{ item.messageType === 1 ? '公有' : '私有' }}
|
||||
</el-tag>
|
||||
<el-tag :type="item.sendMethod === '文字' ? 'success' : ''">
|
||||
{{ item.sendMethod === 'text' ? '文字' : '语音' }}{{ item.speakingTime ? ' | ' + item.speakingTime + '秒' :
|
||||
''
|
||||
}}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="">
|
||||
{{ item.conversationContent }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-text type="info" size="small">
|
||||
{{ formatDateTime(item.recordTime) }} | {{ item.userName }} | {{ item.department }} |
|
||||
<el-icon v-if="item.messageType === 1"><OfficeBuilding /></el-icon>
|
||||
<el-icon v-else><User /></el-icon>
|
||||
|
|
||||
<el-icon v-if="item.sendMethod === 'text'"><EditPen /></el-icon>
|
||||
<el-icon v-else><Microphone /></el-icon>
|
||||
{{ item.speakingTime ? item.speakingTime + 's' : '' }}
|
||||
</el-text>
|
||||
|
||||
<br />
|
||||
<el-text size="small">{{ item.conversationContent }}</el-text>
|
||||
</div>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
@@ -112,7 +95,7 @@ import { ref, reactive, onMounted, computed, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '../utils/request'
|
||||
import { formatPhoneNumber, formatDateTime, formatTimestamp } from '../utils/formatters'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
import { Loading, OfficeBuilding, User, EditPen, Microphone } from '@element-plus/icons-vue'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
@@ -237,7 +220,7 @@ const handleUserSearch = (query) => {
|
||||
// 过滤用户列表
|
||||
setTimeout(() => {
|
||||
const allUsers = originalUserList.value
|
||||
userList.value = allUsers.filter(user =>
|
||||
userList.value = allUsers.filter(user =>
|
||||
user.userName.toLowerCase().includes(query.toLowerCase())
|
||||
)
|
||||
userLoading.value = false
|
||||
@@ -436,7 +419,7 @@ onMounted(() => {
|
||||
|
||||
/* 每个Descriptions项的样式 */
|
||||
.descriptions-item {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
@@ -102,6 +102,11 @@ const handleLogin = async () => {
|
||||
|
||||
// 组件挂载时添加键盘监听
|
||||
onMounted(() => {
|
||||
// 自动回填:如果曾经成功登录过,直接从 localStorage 取出密码
|
||||
const rememberedPassword = localStorage.getItem('rememberedPassword')
|
||||
if (rememberedPassword) {
|
||||
loginForm.password = rememberedPassword
|
||||
}
|
||||
window.addEventListener('keypress', handleKeyPress)
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Change: 管理端登录记住密码(localStorage 自动回填)
|
||||
|
||||
## Why
|
||||
后台管理登录当前每次都需要手动输入密码,重复操作影响效率。需要提供“曾经输入过一次密码后,后续自动记住并回填”的机制。
|
||||
|
||||
## What Changes
|
||||
- 登录成功后,将本次输入的密码写入 `localStorage`。
|
||||
- 下次进入登录页时,自动从 `localStorage` 读取并回填密码,使用户无需再次手动输入。
|
||||
|
||||
## Security Note
|
||||
该机制会将密码以明文形式存储在浏览器 `localStorage`,存在被同机用户或恶意脚本读取的风险。本变更仅按当前产品需求实现;建议后续升级为服务端鉴权与 token 机制,避免存储明文密码。
|
||||
|
||||
## Impact
|
||||
- Affected specs: `openspec/specs/backend-admin/spec.md`
|
||||
- Affected code:
|
||||
- `admin-web/src/views/Login.vue`
|
||||
- `admin-web/src/store/auth.js`
|
||||
@@ -0,0 +1,16 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 用户认证(前端验证)
|
||||
|
||||
管理端登录 SHALL 支持“记住密码”机制:
|
||||
- 当管理员首次成功登录后,系统将本次输入的密码持久化到浏览器 `localStorage`
|
||||
- 后续访问登录页时,系统自动从 `localStorage` 读取并回填密码,使管理员无需再次手动输入
|
||||
|
||||
#### Scenario: 首次登录后记住密码
|
||||
- **WHEN** 管理员使用正确用户名/密码登录成功
|
||||
- **THEN** 系统将密码写入 `localStorage`
|
||||
|
||||
#### Scenario: 进入登录页自动回填
|
||||
- **WHEN** 管理员再次进入登录页
|
||||
- **AND** `localStorage` 中存在已保存的密码
|
||||
- **THEN** 页面自动回填密码输入框
|
||||
@@ -0,0 +1,7 @@
|
||||
# Tasks — 管理端登录记住密码(localStorage)
|
||||
|
||||
- [x] 更新 delta spec:`openspec/changes/add-admin-login-remember-password/specs/backend-admin/spec.md`
|
||||
- [x] 更新现行 spec:`openspec/specs/backend-admin/spec.md`(登录能力增加记住密码)
|
||||
- [x] 登录实现:成功登录后写入 `localStorage`(保存密码)
|
||||
- [x] 登录页初始化:读取 `localStorage` 自动回填密码
|
||||
- [ ] 前端验证:确认刷新页面后不需要重新输入密码
|
||||
@@ -28,6 +28,9 @@
|
||||
### Requirement: 用户认证(前端验证)
|
||||
前端管理网站 SHALL 提供管理员登录功能,使用前端验证方式。
|
||||
|
||||
实现补充(效率优化):
|
||||
- 系统 SHOULD 提供“记住密码”机制:当管理员成功登录过一次后,将密码保存到浏览器 `localStorage` 并在下次进入登录页时自动回填,从而无需重复输入。
|
||||
|
||||
#### Scenario: 管理员登录
|
||||
- **WHEN** 管理员访问登录页面
|
||||
- **THEN** 显示登录表单(用户名、密码字段)
|
||||
@@ -35,6 +38,11 @@
|
||||
- **AND** 登录成功后跳转到首页
|
||||
- **AND** 登录状态保存在 Pinia store 中
|
||||
|
||||
#### Scenario: 记住密码并自动回填
|
||||
- **WHEN** 管理员成功登录一次
|
||||
- **THEN** 系统将本次输入的密码写入 `localStorage`
|
||||
- **AND** 下次进入登录页时自动回填密码输入框
|
||||
|
||||
#### Scenario: 登录验证失败
|
||||
- **WHEN** 管理员输入错误的用户名或密码
|
||||
- **THEN** 显示错误提示信息
|
||||
|
||||
Reference in New Issue
Block a user