You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.7 KiB

  1. import icon_check_s from '../assets/icon_check_s_s.svg';
  2. import icon_check_u from '../assets/icon_check_s_u.svg';
  3. import icon_arr from '../assets/icon_arr_p_r.svg';
  4. import icon_pending from '../assets/icon_upload_0.svg';
  5. import icon_uploading from '../assets/icon_upload_1.svg';
  6. import icon_uploaded from '../assets/icon_upload_2.svg';
  7. import { Measurement } from '../services/apiTypes';
  8. /*
  9. name: '测量名称1',
  10. time: '03-02 10:20',
  11. line: '京沪线',
  12. segment: 'A段',
  13. direction: '上行',
  14. railType: '60轨',
  15. */
  16. export type UpdateState = 'idle' | 'pending' | 'uploading' | 'uploaded';
  17. export default function MeasureItem({
  18. item,
  19. onDetail,
  20. }: {
  21. item: Measurement;
  22. onDetail?: () => void;
  23. }) {
  24. return (
  25. <div className="flex mx-2 gap-3">
  26. <main className="flex-1">
  27. <header className="flex items-center gap-2">
  28. <h1 className="text-[15px] font-medium ">{item.name}</h1>
  29. </header>
  30. <main className="flex my-2">
  31. <p className="flex-1 text-sm ">{`${item.line}`}</p>
  32. <p className="flex-1 text-sm ">{`${item.section}`}</p>
  33. <p className="flex-1 text-sm ">{`${item.direction}方向`}</p>
  34. </main>
  35. <footer>
  36. <span className="text-sm text-[#b7b7b7]">{item.createAt}</span>
  37. </footer>
  38. </main>
  39. <aside className="flex items-center" onClick={onDetail}>
  40. <span className="mr-2 text-sm text-primary font-medium"></span>
  41. <img src={icon_arr} alt="arr" className="h-[10px]" />
  42. </aside>
  43. </div>
  44. );
  45. }
  46. export function MeasureItemEx(props: {
  47. item: Measurement;
  48. selected: boolean;
  49. uploadState: UpdateState;
  50. onSelected?: () => void;
  51. onDetail?: () => void;
  52. }) {
  53. const stateImg = () => {
  54. if (props.uploadState === 'idle') {
  55. if (props.selected) {
  56. return <img src={icon_check_s} alt="icon" />;
  57. } else {
  58. return <img src={icon_check_u} alt="icon" />;
  59. }
  60. } else if (props.uploadState === 'pending') {
  61. return <img src={icon_pending} alt="icon" />;
  62. } else if (props.uploadState === 'uploading') {
  63. return <img src={icon_uploading} alt="icon" />;
  64. } else if (props.uploadState === 'uploaded') {
  65. return <img src={icon_uploaded} alt="icon" />;
  66. }
  67. return null;
  68. };
  69. const stateText = () => {
  70. if (props.uploadState === 'pending') {
  71. return <span className="text-[#A3ACC0] text-xs"></span>;
  72. } else if (props.uploadState === 'uploading') {
  73. return <span className="text-primary text-xs"></span>;
  74. } else if (props.uploadState === 'uploaded') {
  75. return <span className="text-[#04CA17] text-xs"></span>;
  76. }
  77. return null;
  78. };
  79. return (
  80. <div
  81. className="relative flex mx-2 gap-3"
  82. onClick={props.uploadState === 'idle' ? props.onSelected : undefined}
  83. >
  84. <main className="flex-1">
  85. <header className="flex items-center gap-2">
  86. {stateImg()}
  87. <h1 className="text-[15px] font-medium ">{props.item.name}</h1>
  88. </header>
  89. <main className="flex my-2">
  90. <p className="flex-1 text-sm ">{`${props.item.line}`}</p>
  91. <p className="flex-1 text-sm ">{`${props.item.section}`}</p>
  92. <p className="flex-1 text-sm ">{`${props.item.direction}方向`}</p>
  93. </main>
  94. <footer>
  95. <span className="text-sm text-[#b7b7b7]">{props.item.createAt}</span>
  96. </footer>
  97. </main>
  98. <aside className="flex items-center" onClick={props.onDetail}>
  99. <span className="mr-2 text-sm text-primary font-medium"></span>
  100. <img src={icon_arr} alt="arr" className="h-[10px]" />
  101. </aside>
  102. <div className="absolute right-0 bottom-0">{stateText()}</div>
  103. </div>
  104. );
  105. }