[dev]update profile

This commit is contained in:
susie-laptop 2025-05-09 15:02:51 -04:00
parent 5502bd579c
commit b4d708d994
3 changed files with 314 additions and 273 deletions

View File

@ -1,294 +1,338 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { updateProfileThunk } from '../store/auth/auth.thunk';
import ChangePasswordModal from './ChangePasswordModal';
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { updateProfileThunk } from "../store/auth/auth.thunk";
import ChangePasswordModal from "./ChangePasswordModal";
//
const departmentGroups = {
达人部门: ['达人'],
商务部门: ['商务'],
样本中心: ['样本'],
产品部门: ['产品'],
AI自媒体: ['AI自媒体'],
HR: ['HR'],
技术部门: ['技术'],
达人部门: ["达人"],
商务部门: ["商务"],
样本中心: ["样本"],
产品部门: ["产品"],
AI自媒体: ["AI自媒体"],
HR: ["HR"],
技术部门: ["技术"],
};
function UserSettingsModal({ show, onClose }) {
const { user, loading } = useSelector((state) => state.auth);
const [lastPasswordChange] = useState('30天前'); // This would come from backend in real app
const [formData, setFormData] = useState({});
const [showChangePassword, setShowChangePassword] = useState(false);
//
const [availableGroups, setAvailableGroups] = useState([]);
const { user, loading } = useSelector((state) => state.auth);
const [lastPasswordChange] = useState("30天前"); // This would come from backend in real app
const [formData, setFormData] = useState({});
const [showChangePassword, setShowChangePassword] = useState(false);
//
const [availableGroups, setAvailableGroups] = useState([]);
const [submitted, setSubmitted] = useState(false);
const [errors, setErrors] = useState({});
const [submitted, setSubmitted] = useState(false);
const [errors, setErrors] = useState({});
const dispatch = useDispatch();
const dispatch = useDispatch();
useEffect(() => {
if (user) {
setFormData({
name: user.name,
email: user.email,
department: user.department,
group: user.group,
});
}
}, [user]);
useEffect(() => {
if (user) {
setFormData({
name: user.name,
email: user.email,
department: user.department,
group: user.group,
});
}
}, [user]);
//
useEffect(() => {
if (formData.department && departmentGroups[formData.department]) {
setAvailableGroups(departmentGroups[formData.department]);
} else {
setAvailableGroups([]);
}
}, [formData.department]);
//
useEffect(() => {
if (formData.department && departmentGroups[formData.department]) {
setAvailableGroups(departmentGroups[formData.department]);
} else {
setAvailableGroups([]);
}
}, [formData.department]);
if (!show) return null;
if (!show) return null;
const handleInputChange = (e) => {
const { name, value } = e.target;
const handleInputChange = (e) => {
const { name, value } = e.target;
if (name === 'department') {
setFormData({
...formData,
[name]: value,
['group']: '',
});
} else {
setFormData({
...formData,
[name]: value,
});
}
if (name === "department") {
setFormData({
...formData,
[name]: value,
["group"]: "",
});
} else {
setFormData({
...formData,
[name]: value,
});
}
//
if (errors[name]) {
setErrors({
...errors,
[name]: '',
});
}
};
//
if (errors[name]) {
setErrors({
...errors,
[name]: "",
});
}
};
const handleSubmit = async (e) => {
e.preventDefault();
setSubmitted(true);
const handleSubmit = async (e) => {
e.preventDefault();
setSubmitted(true);
if (validateForm()) {
console.log('Form submitted successfully!');
console.log('Update data:', formData);
try {
await dispatch(updateProfileThunk(formData)).unwrap();
} catch (error) {
console.error('Signup failed:', error);
}
}
};
if (validateForm()) {
console.log("Form submitted successfully!");
console.log("Update data:", formData);
try {
await dispatch(updateProfileThunk(formData)).unwrap();
} catch (error) {
console.error("Signup failed:", error);
}
}
};
const validateForm = () => {
const newErrors = {};
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(formData.email)) {
newErrors.email = 'Invalid email address';
}
const validateForm = () => {
const newErrors = {};
if (!formData.email) {
newErrors.email = "Email is required";
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(formData.email)
) {
newErrors.email = "Invalid email address";
}
if (!formData.name) {
newErrors.name = 'Name is required';
}
if (!formData.name) {
newErrors.name = "Name is required";
}
if (!formData.department) {
newErrors.department = '请选择部门';
}
if (!formData.department) {
newErrors.department = "请选择部门";
}
if (!formData.group) {
newErrors.group = '请选择组别';
}
if (!formData.group) {
newErrors.group = "请选择组别";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
return (
<div className='modal show d-block' style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
<div className='modal-dialog modal-dialog-centered'>
<form className='modal-content' onSubmit={handleSubmit}>
<div className='modal-header border-0'>
<h5 className='modal-title'>个人设置</h5>
<button type='button' className='btn-close' onClick={onClose}></button>
</div>
<div className='modal-body'>
<div className='mb-4'>
<h6 className='text-secondary mb-3'>个人信息</h6>
<div className='mb-3'>
<label className='form-label text-secondary'>用户名</label>
<input type='text' className='form-control' value={user?.username || ''} readOnly />
</div>
<div className='mb-3'>
<label className='form-label text-secondary'>姓名</label>
<input
type='text'
className='form-control'
value={formData?.name || ''}
onChange={handleInputChange}
disabled={loading}
/>
{submitted && errors.name && <div className='invalid-feedback'>{errors.name}</div>}
</div>
<div className='mb-3'>
<label className='form-label text-secondary'>邮箱</label>
<input
type='email'
className='form-control'
value={formData?.email || 'admin@ooin.com'}
onChange={handleInputChange}
disabled={loading}
/>
{submitted && errors.email && <div className='invalid-feedback'>{errors.email}</div>}
</div>
<div className='mb-3'>
<select
className={`form-select form-select-lg${
submitted && errors.department ? ' is-invalid' : ''
}`}
id='department'
name='department'
value={formData.department}
onChange={handleInputChange}
disabled={loading}
required
>
<option value='' disabled>
选择部门
</option>
{Object.keys(departmentGroups).map((dept, index) => (
<option key={index} value={dept}>
{dept}
</option>
))}
</select>
{submitted && errors.department && (
<div className='invalid-feedback'>{errors.department}</div>
)}
</div>
<div className='mb-3'>
<select
className={`form-select form-select-lg${
submitted && errors.group ? ' is-invalid' : ''
}`}
id='group'
name='group'
value={formData.group}
onChange={handleInputChange}
disabled={loading || !formData.department}
required
>
<option value='' disabled>
{formData.department ? '选择组别' : '请先选择部门'}
</option>
{availableGroups.map((group, index) => (
<option key={index} value={group}>
{group}
</option>
))}
</select>
{submitted && errors.group && <div className='invalid-feedback'>{errors.group}</div>}
</div>
</div>
<div className='mb-4'>
<h6 className='text-secondary mb-3'>安全设置</h6>
<div className='d-flex justify-content-between align-items-center p-3 bg-light rounded'>
<div>
<div className='d-flex align-items-center gap-2'>
<i className='bi bi-key'></i>
<span>修改密码</span>
</div>
<small className='text-secondary'>上次修改{lastPasswordChange}</small>
</div>
<button
className='btn btn-outline-dark btn-sm'
onClick={(e) => {
e.preventDefault();
setShowChangePassword(true);
}}
>
修改
</button>
</div>
</div>
<div className='d-none mb-4'>
<h6 className='text-secondary mb-3'>安全设置</h6>
<div className='d-flex justify-content-between align-items-center p-3 bg-light rounded'>
<div>
<div className='d-flex align-items-center gap-2'>
<i className='bi bi-key'></i>
<span>修改密码</span>
</div>
<small className='text-secondary'>上次修改{lastPasswordChange}</small>
</div>
<button className='btn btn-outline-dark btn-sm'>修改</button>
</div>
<div className='d-flex justify-content-between align-items-center p-3 bg-light rounded mt-3'>
<div>
<div className='d-flex align-items-center gap-2'>
<i className='bi bi-shield-check'></i>
<span>双重认证</span>
</div>
<small className='text-secondary'>增强账户安全性</small>
</div>
<button className='btn btn-outline-dark btn-sm'>设置</button>
</div>
</div>
<div className='d-none'>
<h6 className='text-secondary mb-3'>通知设置</h6>
<div className='form-check form-switch mb-3 dark-switch'>
<input
className='form-check-input'
type='checkbox'
id='notificationSwitch1'
defaultChecked
/>
<label className='form-check-label' htmlFor='notificationSwitch1'>
访问请求通知
</label>
<div className='text-secondary small'>新的数据集访问申请通知</div>
</div>
<div className='form-check form-switch dark-switch'>
<input
className='form-check-input'
type='checkbox'
id='notificationSwitch2'
defaultChecked
/>
<label className='form-check-label' htmlFor='notificationSwitch2'>
安全提醒
</label>
<div className='text-secondary small'>异常登录和权限变更提醒</div>
</div>
</div>
</div>
<div className='modal-footer border-0'>
<button type='button' disabled={loading} className='btn btn-outline-dark' onClick={onClose}>
取消
</button>
<button type='submit' className='btn btn-dark' disabled={loading}>
保存更改
</button>
</div>
</form>
return (
<div
className="modal show d-block"
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
>
<div className="modal-dialog modal-dialog-centered">
<form className="modal-content" onSubmit={handleSubmit}>
<div className="modal-header border-0">
<h5 className="modal-title">个人设置</h5>
<button
type="button"
className="btn-close"
onClick={onClose}
></button>
</div>
<div className="modal-body">
<div className="mb-4">
<h6 className="text-secondary mb-3">个人信息</h6>
<div className="mb-3">
<label className="form-label text-secondary">用户名</label>
<input
type="text"
className="form-control"
value={user?.username || ""}
readOnly
/>
</div>
<div className="mb-3">
<label className="form-label text-secondary">姓名</label>
<input
type="text"
className="form-control"
value={formData?.name || ""}
name="name"
onChange={handleInputChange}
disabled={loading}
/>
{submitted && errors.name && (
<div className="invalid-feedback">{errors.name}</div>
)}
</div>
<div className="mb-3">
<label className="form-label text-secondary">邮箱</label>
<input
type="email"
name="email"
className="form-control"
value={formData?.email || "admin@ooin.com"}
onChange={handleInputChange}
disabled={loading}
/>
{submitted && errors.email && (
<div className="invalid-feedback">{errors.email}</div>
)}
</div>
<div className="mb-3">
<select
className={`form-select form-select-lg${
submitted && errors.department ? " is-invalid" : ""
}`}
id="department"
name="department"
value={formData.department}
onChange={handleInputChange}
disabled={loading}
required
>
<option value="" disabled>
选择部门
</option>
{Object.keys(departmentGroups).map((dept, index) => (
<option key={index} value={dept}>
{dept}
</option>
))}
</select>
{submitted && errors.department && (
<div className="invalid-feedback">{errors.department}</div>
)}
</div>
<div className="mb-3">
<select
className={`form-select form-select-lg${
submitted && errors.group ? " is-invalid" : ""
}`}
id="group"
name="group"
value={formData.group}
onChange={handleInputChange}
disabled={loading || !formData.department}
required
>
<option value="" disabled>
{formData.department ? "选择组别" : "请先选择部门"}
</option>
{availableGroups.map((group, index) => (
<option key={index} value={group}>
{group}
</option>
))}
</select>
{submitted && errors.group && (
<div className="invalid-feedback">{errors.group}</div>
)}
</div>
</div>
{showChangePassword && (
<ChangePasswordModal show={showChangePassword} onClose={() => setShowChangePassword(false)} />
)}
</div>
);
<div className="mb-4">
<h6 className="text-secondary mb-3">安全设置</h6>
<div className="d-flex justify-content-between align-items-center p-3 bg-light rounded">
<div>
<div className="d-flex align-items-center gap-2">
<i className="bi bi-key"></i>
<span>修改密码</span>
</div>
<small className="text-secondary">
上次修改{lastPasswordChange}
</small>
</div>
<button
className="btn btn-outline-dark btn-sm"
onClick={(e) => {
e.preventDefault();
setShowChangePassword(true);
}}
>
修改
</button>
</div>
</div>
<div className="d-none mb-4">
<h6 className="text-secondary mb-3">安全设置</h6>
<div className="d-flex justify-content-between align-items-center p-3 bg-light rounded">
<div>
<div className="d-flex align-items-center gap-2">
<i className="bi bi-key"></i>
<span>修改密码</span>
</div>
<small className="text-secondary">
上次修改{lastPasswordChange}
</small>
</div>
<button className="btn btn-outline-dark btn-sm">修改</button>
</div>
<div className="d-flex justify-content-between align-items-center p-3 bg-light rounded mt-3">
<div>
<div className="d-flex align-items-center gap-2">
<i className="bi bi-shield-check"></i>
<span>双重认证</span>
</div>
<small className="text-secondary">增强账户安全性</small>
</div>
<button className="btn btn-outline-dark btn-sm">设置</button>
</div>
</div>
<div className="d-none">
<h6 className="text-secondary mb-3">通知设置</h6>
<div className="form-check form-switch mb-3 dark-switch">
<input
className="form-check-input"
type="checkbox"
id="notificationSwitch1"
defaultChecked
/>
<label
className="form-check-label"
htmlFor="notificationSwitch1"
>
访问请求通知
</label>
<div className="text-secondary small">
新的数据集访问申请通知
</div>
</div>
<div className="form-check form-switch dark-switch">
<input
className="form-check-input"
type="checkbox"
id="notificationSwitch2"
defaultChecked
/>
<label
className="form-check-label"
htmlFor="notificationSwitch2"
>
安全提醒
</label>
<div className="text-secondary small">
异常登录和权限变更提醒
</div>
</div>
</div>
</div>
<div className="modal-footer border-0">
<button
type="button"
disabled={loading}
className="btn btn-outline-dark"
onClick={onClose}
>
取消
</button>
<button type="submit" className="btn btn-dark" disabled={loading}>
保存更改
</button>
</div>
</form>
</div>
{showChangePassword && (
<ChangePasswordModal
show={showChangePassword}
onClose={() => setShowChangePassword(false)}
/>
)}
</div>
);
}
export default UserSettingsModal;

View File

@ -47,15 +47,12 @@ export default function Chat() {
// If we have a knowledgeBaseId but no chatId, check if we have an existing chat or create a new one
useEffect(() => {
console.log('Chat.jsx: chatHistory', chatHistory);
// knowledgeBaseId chatId
if (knowledgeBaseId && !chatId && status === 'succeeded' && !status.includes('loading')) {
console.log('Chat.jsx: 创建新聊天...');
// ID ()
const knowledgeBaseIds = knowledgeBaseId.split(',').map((id) => id.trim());
console.log('Chat.jsx: 处理知识库ID列表:', knowledgeBaseIds);
// - 使API
dispatch(

View File

@ -6,8 +6,8 @@ import KnowledgeBaseDetail from '../pages/KnowledgeBase/Detail/KnowledgeBaseDeta
import Chat from '../pages/Chat/Chat';
import PermissionsPage from '../pages/Permissions/PermissionsPage';
import Loading from '../components/Loading';
import Login from '../pages/Auth/Login';
import Signup from '../pages/Auth/Signup';
import Login from '../pages/auth/Login';
import Signup from '../pages/auth/Signup';
import ProtectedRoute from './protectedRoute';
import { useSelector } from 'react-redux';
import NotificationSnackbar from '../components/NotificationSnackbar';