printSlice.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { createSlice, PayloadAction } from '@reduxjs/toolkit';
  2. export type FilmLayout = '1x1' | '1x2' | '2x1' | '2x2';
  3. export type FilmOrientation = 'horizontal' | 'vertical';
  4. interface Film {
  5. id: string;
  6. layout: FilmLayout;
  7. orientation: FilmOrientation;
  8. images: (string | null)[]; // 图像ID或null(空格子)
  9. }
  10. interface PrintState {
  11. films: Film[];
  12. activeFilmId: string;
  13. /**
  14. * 本质是 sop instance uid
  15. */
  16. selectedImageIndex: string | null; // 当前选中的图像在格子中的索引
  17. }
  18. const initialFilm: Film = {
  19. id: '1',
  20. layout: '1x1',
  21. orientation: 'vertical',
  22. /**
  23. * 存储每个成员本质上是个sop instance uid
  24. */
  25. images: [null], // 1x1只有一个格子
  26. };
  27. const initialState: PrintState = {
  28. films: [initialFilm],
  29. activeFilmId: '1',
  30. selectedImageIndex: null,
  31. };
  32. const printSlice = createSlice({
  33. name: 'print',
  34. initialState,
  35. reducers: {
  36. // 添加新胶片
  37. addFilm: (state) => {
  38. const newId = String(state.films.length + 1);
  39. const newFilm: Film = {
  40. id: newId,
  41. layout: '1x1',
  42. orientation: 'vertical',
  43. images: [null],
  44. };
  45. state.films.push(newFilm);
  46. state.activeFilmId = newId;
  47. },
  48. // 删除胶片
  49. deleteFilm: (state, action: PayloadAction<string>) => {
  50. if (state.films.length <= 1) {
  51. // 至少保留一个胶片
  52. return;
  53. }
  54. state.films = state.films.filter((film) => film.id !== action.payload);
  55. // 如果删除的是当前胶片,切换到第一个
  56. if (state.activeFilmId === action.payload) {
  57. state.activeFilmId = state.films[0].id;
  58. }
  59. },
  60. // 切换当前胶片
  61. setActiveFilm: (state, action: PayloadAction<string>) => {
  62. state.activeFilmId = action.payload;
  63. state.selectedImageIndex = null; // 切换胶片时清除选中
  64. },
  65. // 设置胶片布局
  66. setFilmLayout: (state, action: PayloadAction<FilmLayout>) => {
  67. const film = state.films.find((f) => f.id === state.activeFilmId);
  68. if (!film) return;
  69. film.layout = action.payload;
  70. // 根据布局调整images数组大小
  71. const layoutSizes = {
  72. '1x1': 1,
  73. '1x2': 2,
  74. '2x1': 2,
  75. '2x2': 4,
  76. };
  77. const newSize = layoutSizes[action.payload];
  78. // 保留现有图像,补充或裁剪
  79. if (film.images.length < newSize) {
  80. film.images = [...film.images, ...Array(newSize - film.images.length).fill(null)];
  81. } else {
  82. film.images = film.images.slice(0, newSize);
  83. }
  84. },
  85. // 切换胶片方向
  86. toggleFilmOrientation: (state) => {
  87. const film = state.films.find((f) => f.id === state.activeFilmId);
  88. if (!film) return;
  89. film.orientation = film.orientation === 'horizontal' ? 'vertical' : 'horizontal';
  90. },
  91. // 设置选中的图像格子
  92. setSelectedImageIndex: (state, action: PayloadAction<string | null>) => {
  93. state.selectedImageIndex = action.payload;
  94. },
  95. // 删除选中的图像
  96. deleteSelectedImage: (state) => {
  97. if (state.selectedImageIndex === null) return;
  98. const film = state.films.find((f) => f.id === state.activeFilmId);
  99. if (!film) return;
  100. film.images[state.selectedImageIndex] = null;
  101. state.selectedImageIndex = null;
  102. },
  103. // 添加图像到指定格子
  104. addImageToCell: (state, action: PayloadAction<{ index: number; imageId: string }>) => {
  105. const film = state.films.find((f) => f.id === state.activeFilmId);
  106. if (!film) return;
  107. film.images[action.payload.index] = action.payload.imageId;
  108. },
  109. },
  110. });
  111. export const {
  112. addFilm,
  113. deleteFilm,
  114. setActiveFilm,
  115. setFilmLayout,
  116. toggleFilmOrientation,
  117. setSelectedImageIndex,
  118. deleteSelectedImage,
  119. addImageToCell,
  120. } = printSlice.actions;
  121. export default printSlice.reducer;