界面优化
parent
77fe6d4e77
commit
bf40b13383
|
|
@ -138,6 +138,7 @@ export default function Users() {
|
||||||
const [filterTenantId, setFilterTenantId] = useState<number | undefined>(undefined);
|
const [filterTenantId, setFilterTenantId] = useState<number | undefined>(undefined);
|
||||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||||
const [editing, setEditing] = useState<SysUser | null>(null);
|
const [editing, setEditing] = useState<SysUser | null>(null);
|
||||||
|
const [roleSelectOpen, setRoleSelectOpen] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [resetPasswordOpen, setResetPasswordOpen] = useState(false);
|
const [resetPasswordOpen, setResetPasswordOpen] = useState(false);
|
||||||
const [resetPasswordLoading, setResetPasswordLoading] = useState(false);
|
const [resetPasswordLoading, setResetPasswordLoading] = useState(false);
|
||||||
|
|
@ -264,6 +265,7 @@ export default function Users() {
|
||||||
|
|
||||||
const openCreate = () => {
|
const openCreate = () => {
|
||||||
setEditing(null);
|
setEditing(null);
|
||||||
|
setRoleSelectOpen(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
status: 1,
|
status: 1,
|
||||||
|
|
@ -277,6 +279,7 @@ export default function Users() {
|
||||||
|
|
||||||
const openEdit = async (record: SysUser) => {
|
const openEdit = async (record: SysUser) => {
|
||||||
setEditing(record);
|
setEditing(record);
|
||||||
|
setRoleSelectOpen(false);
|
||||||
try {
|
try {
|
||||||
const detail = await getUserDetail(record.userId);
|
const detail = await getUserDetail(record.userId);
|
||||||
const roleIds = await listUserRoles(record.userId);
|
const roleIds = await listUserRoles(record.userId);
|
||||||
|
|
@ -597,6 +600,9 @@ export default function Users() {
|
||||||
rules={[{required: true, message: t("users.roles")}]}><Select mode="multiple"
|
rules={[{required: true, message: t("users.roles")}]}><Select mode="multiple"
|
||||||
placeholder={t("users.roles")}
|
placeholder={t("users.roles")}
|
||||||
options={roleOptions}
|
options={roleOptions}
|
||||||
|
open={roleSelectOpen}
|
||||||
|
onDropdownVisibleChange={setRoleSelectOpen}
|
||||||
|
onChange={() => setRoleSelectOpen(false)}
|
||||||
optionFilterProp={isPlatformMode ? "searchText" : "label"}/></Form.Item>
|
optionFilterProp={isPlatformMode ? "searchText" : "label"}/></Form.Item>
|
||||||
{!isPlatformMode && <Form.Item label={t("users.orgNode")} name="orgId"><TreeSelect
|
{!isPlatformMode && <Form.Item label={t("users.orgNode")} name="orgId"><TreeSelect
|
||||||
placeholder={t("usersExt.selectOrgPlaceholder")} allowClear treeData={orgTreeData}/></Form.Item>}
|
placeholder={t("usersExt.selectOrgPlaceholder")} allowClear treeData={orgTreeData}/></Form.Item>}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
RightOutlined,
|
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
|
|
@ -136,6 +135,9 @@ const shouldPollMeetingCard = (item: MeetingVO) =>
|
||||||
const getUnifiedStatusCode = (progress: MeetingProgress | null | undefined) =>
|
const getUnifiedStatusCode = (progress: MeetingProgress | null | undefined) =>
|
||||||
progress?.unifiedStatus?.statusCode;
|
progress?.unifiedStatus?.statusCode;
|
||||||
|
|
||||||
|
const isWaitingUploadProgress = (progress: MeetingProgress | null | undefined) =>
|
||||||
|
getUnifiedStatusCode(progress) === "WAITING_UPLOAD";
|
||||||
|
|
||||||
const getEffectiveStatus = (item: MeetingVO, progress: MeetingProgress | null) => {
|
const getEffectiveStatus = (item: MeetingVO, progress: MeetingProgress | null) => {
|
||||||
const unifiedStatusCode = getUnifiedStatusCode(progress);
|
const unifiedStatusCode = getUnifiedStatusCode(progress);
|
||||||
if (unifiedStatusCode === "WAITING_UPLOAD") {
|
if (unifiedStatusCode === "WAITING_UPLOAD") {
|
||||||
|
|
@ -285,12 +287,17 @@ const MeetingCardItem: React.FC<{
|
||||||
}> = ({ item, config, progress, onOpenMeeting, onRetrySchedule, onDelete, retrying }) => {
|
}> = ({ item, config, progress, onOpenMeeting, onRetrySchedule, onDelete, retrying }) => {
|
||||||
const effectiveStatus = getEffectiveStatus(item, progress);
|
const effectiveStatus = getEffectiveStatus(item, progress);
|
||||||
const isProcessing = shouldTrackGenerationProgress(item);
|
const isProcessing = shouldTrackGenerationProgress(item);
|
||||||
|
const isWaitingUpload = isWaitingUploadProgress(progress) || effectiveStatus === 8;
|
||||||
const isPaused = effectiveStatus === PAUSED_DISPLAY_STATUS;
|
const isPaused = effectiveStatus === PAUSED_DISPLAY_STATUS;
|
||||||
const isRealtimeActive = effectiveStatus === REALTIME_ACTIVE_DISPLAY_STATUS;
|
const isRealtimeActive = effectiveStatus === REALTIME_ACTIVE_DISPLAY_STATUS;
|
||||||
const isRealtimeIdle = effectiveStatus === REALTIME_IDLE_DISPLAY_STATUS;
|
const isRealtimeIdle = effectiveStatus === REALTIME_IDLE_DISPLAY_STATUS;
|
||||||
const isCrossPlatformRealtime = (isPaused || isRealtimeActive || isRealtimeIdle) && !canControlRealtimeFromCurrentPlatform(item);
|
const isCrossPlatformRealtime = (isPaused || isRealtimeActive || isRealtimeIdle) && !canControlRealtimeFromCurrentPlatform(item);
|
||||||
const crossPlatformHint = `在 ${getRealtimeSourceLabel(item)} 继续`;
|
const crossPlatformHint = `在 ${getRealtimeSourceLabel(item)} 继续`;
|
||||||
const canRetry = canRetryQueuedMeeting(item, progress);
|
const canRetry = canRetryQueuedMeeting(item, progress);
|
||||||
|
const ownerName = item.creatorName || "未知";
|
||||||
|
const processingMessage = isWaitingUpload
|
||||||
|
? (progress?.message || progress?.unifiedStatus?.message || config.text)
|
||||||
|
: (progress?.unifiedStatus?.message || progress?.message || "深度分析中...");
|
||||||
|
|
||||||
const sourceColor = item.meetingSource === "ANDROID" ? "#10b981" : "#3b82f6";
|
const sourceColor = item.meetingSource === "ANDROID" ? "#10b981" : "#3b82f6";
|
||||||
|
|
||||||
|
|
@ -375,10 +382,11 @@ const MeetingCardItem: React.FC<{
|
||||||
fontSize: "12px"
|
fontSize: "12px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "6px", color: config.color, fontWeight: 600 }}>
|
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: "10px" }}>
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: "6px", minWidth: 0, color: config.color, fontWeight: 600 }}>
|
||||||
{isProcessing ? <SyncOutlined spin /> : <InfoCircleOutlined />}
|
{isProcessing ? <SyncOutlined spin /> : <InfoCircleOutlined />}
|
||||||
<span style={{ fontSize: "12px" }}>
|
<span style={{ fontSize: "12px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
{isProcessing ? (progress?.message || "深度分析中...") : (isCrossPlatformRealtime ? crossPlatformHint : config.text)}
|
{isProcessing ? processingMessage : (isCrossPlatformRealtime ? crossPlatformHint : config.text)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{canRetry && (
|
{canRetry && (
|
||||||
|
|
@ -390,22 +398,19 @@ const MeetingCardItem: React.FC<{
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
onRetrySchedule(item);
|
onRetrySchedule(item);
|
||||||
}}
|
}}
|
||||||
style={{ paddingInline: 0, height: "auto" }}
|
style={{ paddingInline: 0, height: 18, lineHeight: "18px", flexShrink: 0, fontSize: "12px", fontWeight: 600 }}
|
||||||
>
|
>
|
||||||
重新调度
|
重新调度
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ display: "flex", flexWrap: "wrap", gap: "12px", color: "#8c8c8c", fontSize: "12px" }}>
|
<div style={{ display: "flex", flexWrap: "wrap", gap: "12px", color: "#8c8c8c", fontSize: "12px" }}>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||||
<CalendarOutlined style={{ fontSize: "13px", opacity: 0.7 }} />
|
<CalendarOutlined style={{ fontSize: "13px", opacity: 0.7 }} />
|
||||||
<span>{dayjs(item.meetingTime).format("MM-DD HH:mm")}</span>
|
<span>{dayjs(item.meetingTime).format("MM-DD HH:mm")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
|
||||||
<UserOutlined style={{ fontSize: "13px", opacity: 0.7 }} />
|
|
||||||
<span style={{ maxWidth: "80px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.creatorName || "未知"}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -436,31 +441,27 @@ const MeetingCardItem: React.FC<{
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: "28px",
|
height: "28px",
|
||||||
|
maxWidth: "112px",
|
||||||
|
padding: "0 10px",
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
background: "rgba(95, 81, 255, 0.1)",
|
background: "rgba(15, 23, 42, 0.04)",
|
||||||
color: "var(--primary-blue)",
|
color: "#6b7280",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
gap: "5px",
|
||||||
padding: "0 10px",
|
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
minWidth: "28px"
|
flexShrink: 0,
|
||||||
}}
|
|
||||||
className="card-arrow"
|
|
||||||
>
|
|
||||||
<RightOutlined style={{ fontSize: "10px", flexShrink: 0 }} />
|
|
||||||
<span className="view-detail-text" style={{
|
|
||||||
fontSize: "11px",
|
fontSize: "11px",
|
||||||
fontWeight: 700,
|
fontWeight: 600
|
||||||
maxWidth: 0,
|
}}
|
||||||
opacity: 0,
|
title={`所属用户:${ownerName}`}
|
||||||
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
>
|
||||||
marginLeft: 0,
|
<UserOutlined style={{ fontSize: "12px", opacity: 0.75, flexShrink: 0 }} />
|
||||||
overflow: 'hidden',
|
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
display: 'inline-block'
|
{ownerName}
|
||||||
}}>查看详情</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -1001,8 +1002,6 @@ const Meetings: React.FC = () => {
|
||||||
|
|
||||||
<style>{`
|
<style>{`
|
||||||
.meeting-card-v2:hover { transform: translateY(-3px); box-shadow: 0 12px 24px rgba(95, 81, 255, 0.08) !important; border-color: rgba(95, 81, 255, 0.15) !important; }
|
.meeting-card-v2:hover { transform: translateY(-3px); box-shadow: 0 12px 24px rgba(95, 81, 255, 0.08) !important; border-color: rgba(95, 81, 255, 0.15) !important; }
|
||||||
.meeting-card-v2:hover .card-arrow { background: var(--primary-blue) !important; color: white !important; padding: 0 12px; }
|
|
||||||
.meeting-card-v2:hover .view-detail-text { max-width: 60px; opacity: 1; margin-left: 6px; }
|
|
||||||
.status-bar-active { animation: statusBreathing 2s infinite ease-in-out; }
|
.status-bar-active { animation: statusBreathing 2s infinite ease-in-out; }
|
||||||
@keyframes statusBreathing { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
|
@keyframes statusBreathing { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
|
||||||
.meetings-list-table.ant-table-wrapper,
|
.meetings-list-table.ant-table-wrapper,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue