SettingItem.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import { useIntl } from "react-intl";
  2. import { useEffect, useState } from "react";
  3. import {
  4. Switch,
  5. Typography,
  6. Radio,
  7. type RadioChangeEvent,
  8. Select,
  9. Transfer,
  10. } from "antd";
  11. import {
  12. onChange as onSettingChanged,
  13. settingInfo,
  14. type ISettingItem,
  15. } from "../../../reducers/setting";
  16. import { useAppSelector } from "../../../hooks";
  17. import store from "../../../store";
  18. import type { ISetting } from "./default"
  19. import type { TransferDirection } from "antd/lib/transfer"
  20. const { Text } = Typography;
  21. interface IWidgetSettingItem {
  22. data?: ISetting;
  23. autoSave?: boolean;
  24. bordered?: boolean;
  25. onChange?: Function;
  26. }
  27. const SettingItemWidget = ({
  28. data,
  29. bordered = true,
  30. onChange,
  31. autoSave = true,
  32. }: IWidgetSettingItem) => {
  33. const intl = useIntl();
  34. const settings: ISettingItem[] | undefined = useAppSelector(settingInfo);
  35. const [value, setValue] = useState(data?.defaultValue);
  36. const [targetKeys, setTargetKeys] = useState<string[]>([]);
  37. useEffect(() => {
  38. if (typeof data?.defaultValue === "object") {
  39. setTargetKeys(data.defaultValue);
  40. }
  41. }, [data?.defaultValue]);
  42. useEffect(() => {
  43. setValue(data?.defaultValue);
  44. }, [data?.defaultValue]);
  45. useEffect(() => {
  46. const currSetting = settings?.find((element) => element.key === data?.key);
  47. if (typeof currSetting !== "undefined") {
  48. setValue(currSetting.value);
  49. }
  50. }, [data?.key, settings]);
  51. let content: JSX.Element = <></>;
  52. if (typeof data === "undefined") {
  53. return content;
  54. } else {
  55. const description: string | undefined = data.description
  56. ? intl.formatMessage({ id: data.description })
  57. : undefined;
  58. switch (typeof data.defaultValue) {
  59. case "number":
  60. break;
  61. case "object":
  62. switch (data.widget) {
  63. case "transfer":
  64. if (typeof data.options !== "undefined") {
  65. content = (
  66. <Transfer
  67. dataSource={data.options.map((item) => {
  68. return {
  69. key: item.value,
  70. title: intl.formatMessage({ id: item.label }),
  71. };
  72. })}
  73. titles={[
  74. "备选",
  75. intl.formatMessage({ id: "labels.selected" }),
  76. ]}
  77. targetKeys={targetKeys}
  78. onChange={(
  79. newTargetKeys: string[],
  80. _direction: TransferDirection,
  81. _moveKeys: string[]
  82. ) => {
  83. setTargetKeys(newTargetKeys);
  84. store.dispatch(
  85. onSettingChanged({
  86. key: data.key,
  87. value: newTargetKeys,
  88. })
  89. );
  90. if (typeof onChange !== "undefined") {
  91. onChange(data.key, newTargetKeys);
  92. }
  93. }}
  94. render={(item) => item.title}
  95. oneWay
  96. />
  97. );
  98. }
  99. break;
  100. }
  101. break;
  102. case "string":
  103. switch (data.widget) {
  104. case "radio-button":
  105. if (typeof data.options !== "undefined") {
  106. content = (
  107. <>
  108. <Radio.Group
  109. value={value}
  110. buttonStyle="solid"
  111. onChange={(e: RadioChangeEvent) => {
  112. setValue(e.target.value);
  113. if (autoSave) {
  114. store.dispatch(
  115. onSettingChanged({
  116. key: data.key,
  117. value: e.target.value,
  118. })
  119. );
  120. }
  121. if (typeof onChange !== "undefined") {
  122. onChange(data.key, e.target.value);
  123. }
  124. }}
  125. >
  126. {data.options.map((item, id) => {
  127. return (
  128. <Radio.Button key={id} value={item.value}>
  129. {intl.formatMessage({ id: item.label })}
  130. </Radio.Button>
  131. );
  132. })}
  133. </Radio.Group>
  134. </>
  135. );
  136. }
  137. break;
  138. default:
  139. if (typeof data.options !== "undefined") {
  140. content = (
  141. <div>
  142. <Select
  143. defaultValue={data.defaultValue}
  144. style={{ width: 120 }}
  145. bordered={bordered}
  146. onChange={(value: string) => {
  147. console.log(`selected ${value}`);
  148. if (autoSave) {
  149. store.dispatch(
  150. onSettingChanged({
  151. key: data.key,
  152. value: value,
  153. })
  154. );
  155. }
  156. if (typeof onChange !== "undefined") {
  157. onChange(data.key, value);
  158. }
  159. }}
  160. options={data.options.map((item) => {
  161. return {
  162. value: item.value,
  163. label: intl.formatMessage({ id: item.label }),
  164. };
  165. })}
  166. />
  167. </div>
  168. );
  169. } else {
  170. }
  171. break;
  172. }
  173. break;
  174. case "boolean":
  175. content = (
  176. <div>
  177. <Switch
  178. defaultChecked={value as boolean}
  179. onChange={(checked) => {
  180. console.log("setting changed", data.key, checked);
  181. if (autoSave) {
  182. store.dispatch(
  183. onSettingChanged({ key: data.key, value: checked })
  184. );
  185. }
  186. if (typeof onChange !== "undefined") {
  187. onChange(data.key, checked);
  188. }
  189. }}
  190. />
  191. </div>
  192. );
  193. break;
  194. default:
  195. break;
  196. }
  197. return (
  198. <div style={{ marginBottom: 10 }}>
  199. <div
  200. style={{
  201. display: "flex",
  202. justifyContent: "space-between",
  203. flexWrap: "wrap",
  204. }}
  205. >
  206. <div>
  207. <div>
  208. <Text>{intl.formatMessage({ id: data.label })}</Text>
  209. </div>
  210. <Text type="secondary">{description}</Text>
  211. </div>
  212. <div style={{ marginLeft: "auto" }}>{content}</div>
  213. </div>
  214. </div>
  215. );
  216. }
  217. };
  218. export default SettingItemWidget;