123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- import React, { useEffect } from 'react';
- import { Modal, Select, Button, Space, Typography, message, Spin } from 'antd';
- import { GlobalOutlined } from '@ant-design/icons';
- import { useAppDispatch, useAppSelector } from '../states/store';
- import {
- loadAvailableLanguages,
- updateSystemLanguage,
- setSelectedLanguage,
- } from '../states/i18nSlice';
- const { Text } = Typography;
- interface LanguageSettingModalProps {
- visible: boolean;
- onClose: () => void;
- }
- const LanguageSettingModal: React.FC<LanguageSettingModalProps> = ({
- visible,
- onClose,
- }) => {
- const dispatch = useAppDispatch();
- // 从 Redux 获取状态
- const {
- availableLanguages,
- selectedLanguage,
- currentSystemLocale,
- languagesLoading,
- savingLanguage,
- languageError,
- } = useAppSelector((state) => state.i18n);
- // 加载语言列表
- useEffect(() => {
- if (visible && availableLanguages.length === 0) {
- dispatch(loadAvailableLanguages());
- }
- }, [visible, dispatch, availableLanguages.length]);
- // 显示错误消息
- useEffect(() => {
- if (languageError) {
- message.error({
- content: languageError,
- duration: 3,
- });
- }
- }, [languageError]);
- const handleSave = async (): Promise<void> => {
- if (!selectedLanguage) {
- message.warning('请选择一个语言');
- return;
- }
- try {
- await dispatch(updateSystemLanguage(selectedLanguage)).unwrap();
- message.success({
- content: '语言设置已保存',
- duration: 2,
- });
- message.info({
- content: '请重启电脑以应用新的语言设置',
- duration: 3,
- });
- onClose();
- } catch (error) {
- // 错误已经在 Redux slice 中处理并通过 languageError 显示
- console.error('修改语言失败:', error);
- }
- };
- const handleCancel = (): void => {
- onClose();
- };
- const handleLanguageChange = (value: string): void => {
- dispatch(setSelectedLanguage(value));
- };
- return (
- <Modal
- title={
- <Space>
- <GlobalOutlined />
- <span>语言设置</span>
- </Space>
- }
- open={visible}
- onCancel={handleCancel}
- footer={null}
- centered
- width={500}
- >
- <div style={{ padding: '20px 0' }}>
- {languagesLoading ? (
- <div style={{ textAlign: 'center', padding: '40px 0' }}>
- <Spin size="large" tip="加载中..." />
- </div>
- ) : (
- <>
- <Space direction="vertical" size="large" style={{ width: '100%' }}>
- {currentSystemLocale && (
- <div>
- <Text style={{ fontSize: 14 }}>
- 当前语言:<Text strong>{currentSystemLocale}</Text>
- </Text>
- </div>
- )}
- <div>
- <Text
- strong
- style={{ display: 'block', marginBottom: 8, fontSize: 14 }}
- >
- 选择语言:
- </Text>
- <Select
- style={{ width: '100%' }}
- size="large"
- value={selectedLanguage}
- onChange={handleLanguageChange}
- disabled={savingLanguage}
- placeholder="请选择语言"
- >
- {availableLanguages.map((lang) => (
- <Select.Option key={lang.language} value={lang.language}>
- {lang.display}
- </Select.Option>
- ))}
- </Select>
- </div>
- <Space
- style={{
- width: '100%',
- justifyContent: 'flex-end',
- marginTop: 16,
- }}
- >
- <Button
- size="large"
- onClick={handleCancel}
- disabled={savingLanguage}
- >
- 取消
- </Button>
- <Button
- type="primary"
- size="large"
- onClick={handleSave}
- loading={savingLanguage}
- disabled={!selectedLanguage}
- >
- 保存
- </Button>
- </Space>
- </Space>
- </>
- )}
- </div>
- </Modal>
- );
- };
- export default LanguageSettingModal;
|