SeatingPlanPageViewModel.ets 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { BasicType, IBestToast, YTAvoid, yTRouter } from "basic"
  2. import { window } from "@kit.ArkUI"
  3. import { unifiedDataChannel } from "@kit.ArkData"
  4. import { BusinessError } from "@kit.BasicServicesKit"
  5. import { undoData } from "../model/Index"
  6. @ObservedV2
  7. export class SeatingPlanPageViewModel{
  8. @Trace safeTop: number = 0
  9. // 学生列表
  10. @Trace dataSource: string[] = ['张三', '李四', '王五', '赵六', '孙七', '周八', '吴九', '小十', '张三', '李四', '王五', '赵六', '孙七', '周八', '吴九', '小十']
  11. // 座位表 - 二维数组 8*8
  12. @Trace seatingPlan: Array<string[]> = new Array(4).fill(new Array(8).fill(''))
  13. // 当前显示的模式: 1 - 单列 2 - 双列
  14. @Trace columnMode: number = 1
  15. // 是否保存了 - 上次的操作是否为保存
  16. isSave: boolean = false
  17. // 撤销数据
  18. undoDataList: Array<undoData> = []
  19. // 上下文对象
  20. conText: UIContext
  21. // 控制按钮
  22. controlBtn: Array<BasicType> = [
  23. {
  24. text: '添加行',
  25. click: () => {
  26. this._onAddRow()
  27. }
  28. },
  29. {
  30. text: '添加列',
  31. click: () => {
  32. this._onAddColumn()
  33. }
  34. },
  35. {
  36. text: '删除行',
  37. click: () => {
  38. this._onDeleteRow()
  39. }
  40. },
  41. {
  42. text: '删除列',
  43. click: () => {
  44. this._onDeleteColumn()
  45. }
  46. },
  47. {
  48. text: '单、双列切换',
  49. message: 'hh',
  50. click: () => {
  51. this._onChangeColumn()
  52. }
  53. },
  54. {
  55. text: '撤销操作',
  56. click: () => {
  57. this._onUndo()
  58. }
  59. },
  60. {
  61. text: '保存',
  62. click: () => {
  63. this._onSave()
  64. }
  65. },
  66. {
  67. text: '返回',
  68. click: () => {
  69. this._onBackPressed()
  70. }
  71. }
  72. ]
  73. // 拖拽结束了吗
  74. isDragEnd: boolean = true
  75. constructor(conText: UIContext) {
  76. this.safeTop = AppStorage.get(YTAvoid.SAFE_TOP_KEY) as number
  77. this.conText = conText
  78. window.getLastWindow(this.conText.getHostContext())
  79. .then(res => {
  80. res.setPreferredOrientation(window.Orientation.LANDSCAPE)
  81. })
  82. }
  83. /**
  84. * 点击学生
  85. * @param seating 当前维度的学生列表
  86. * @param x
  87. * @param y
  88. */
  89. _onStudentClick(seating: string[], x : number, y : number){
  90. if(!seating[y]) return
  91. let arr = [...seating]
  92. let i = arr[y]
  93. arr[y] = ''
  94. this._addUndoData()
  95. this.dataSource.push(i)
  96. this.seatingPlan.splice(x, 1, arr)
  97. }
  98. /**
  99. * 接收方 - 接收到拖拽的学生
  100. * @param seat 当前维度的学生列表
  101. * @param x
  102. * @param y
  103. * @param value 接收到的学生
  104. */
  105. _onDrag(seat: string[], x : number, y : number, value: string){
  106. this.isDragEnd = true
  107. let arr = [...seat]
  108. // 原位置上有学生
  109. if(arr[y]) {
  110. animateToImmediately({
  111. duration: 300
  112. } ,() => {
  113. this.dataSource.push(arr[y])
  114. })
  115. }
  116. arr[y] = value
  117. this.seatingPlan[x] = arr
  118. }
  119. /**
  120. * 数据源 - 拖拽事件结束
  121. * @param event 拖拽事件传递的事件参数
  122. */
  123. _onDragEnd(event: DragEvent){
  124. // 1. 拖拽失败 - 没有在接收方接收到数据, 撤销本次操作
  125. // 2. 拖拽成功 - 但是数据接收是系统控件接收,数据源并没有发生变化, 撤销本次操作
  126. if (event.getResult() === DragResult.DRAG_FAILED || !this.isDragEnd) {
  127. this._onUndo()
  128. }
  129. }
  130. /**
  131. * 添加行
  132. */
  133. _onAddRow() {
  134. let x = this.seatingPlan.length
  135. let y = this.seatingPlan[0].length
  136. if(x == 8) return
  137. this._addUndoData()
  138. this.seatingPlan.push(new Array(y).fill(''))
  139. }
  140. /**
  141. * 添加列
  142. */
  143. _onAddColumn() {
  144. let x = this.seatingPlan.length
  145. let y = this.seatingPlan[0].length
  146. if(y == 13) return
  147. this._addUndoData()
  148. for (let index = 0; index < this.seatingPlan.length; index++) {
  149. let arr = [...this.seatingPlan[index]]
  150. arr.push('')
  151. if(this.columnMode == 2) arr.push('')
  152. this.seatingPlan[index] = arr
  153. }
  154. }
  155. /**
  156. * 删除行
  157. */
  158. _onDeleteRow() {
  159. let x = this.seatingPlan.length
  160. let y = this.seatingPlan[0].length
  161. if(x == 4){
  162. IBestToast.show('行数不足4行')
  163. return
  164. }
  165. this._addUndoData()
  166. this.seatingPlan.splice(x-1, 1)
  167. }
  168. /**
  169. * 删除列
  170. */
  171. _onDeleteColumn() {
  172. let x = this.seatingPlan.length
  173. let y = this.seatingPlan[0].length
  174. if(y == 8) {
  175. IBestToast.show('列数不足8列')
  176. return
  177. }
  178. this._addUndoData()
  179. for (let index = 0; index < x; index++) {
  180. let arr = [...this.seatingPlan[index]]
  181. arr.splice(y-1, 1)
  182. this.seatingPlan[index] = arr
  183. }
  184. }
  185. /**
  186. * 单、双列切换
  187. */
  188. _onChangeColumn() {
  189. let x = this.seatingPlan[0].length
  190. if(x%2 == 1 && this.columnMode == 1) this._onAddColumn()
  191. this._addUndoData()
  192. this.columnMode = this.columnMode == 1 ? 2 : 1
  193. }
  194. /**
  195. * 撤销操作
  196. */
  197. _onUndo() {
  198. if(this.undoDataList.length == 0) return
  199. const undoDate: undoData = this.undoDataList.pop()!
  200. this.seatingPlan = [...undoDate.arr2!]
  201. this.dataSource = [...undoDate.arr!]
  202. this.columnMode = undoDate.columnMode!
  203. }
  204. /**
  205. * 保存
  206. */
  207. _onSave() {
  208. if(this.isSave) return
  209. this.isSave = true
  210. }
  211. /**
  212. * 添加 《撤销》 数据 - 仅保存 10 次操作
  213. */
  214. _addUndoData() {
  215. this.isSave = false
  216. const undoData: undoData = {
  217. arr2: [...this.seatingPlan],
  218. columnMode: this.columnMode,
  219. arr: [...this.dataSource],
  220. }
  221. this.undoDataList.push(undoData)
  222. if(this.undoDataList.length == 10) {
  223. this.undoDataList.splice(0, 1)
  224. }
  225. }
  226. /**
  227. * 回正屏幕并返回
  228. */
  229. _onBack(){
  230. window.getLastWindow(this.conText.getHostContext())
  231. .then(res => {
  232. res.setPreferredOrientation(window.Orientation.UNSPECIFIED)
  233. yTRouter.pop('')
  234. })
  235. }
  236. /**
  237. * 重写的返回逻辑
  238. * @returns
  239. */
  240. _onBackPressed(){
  241. if(!this.isSave) {
  242. yTRouter.router2DoubleConfirmDiaLog({
  243. text: '编辑内容未保存,确定离开吗?',
  244. color: '#7186F9'
  245. }, (res) => {
  246. if(res && res.result == 'true') {
  247. this._onBack()
  248. }
  249. })
  250. } else {
  251. this._onBack()
  252. }
  253. return true;
  254. }
  255. /******** 拖拽事件用的方法 ***********/
  256. getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
  257. if (this.getDataFromUdmfRetry(event, callback)) {
  258. return;
  259. }
  260. setTimeout(() => {
  261. this.getDataFromUdmfRetry(event, callback);
  262. }, 1500);
  263. }
  264. getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) {
  265. try {
  266. let data: UnifiedData = event.getData();
  267. if (!data) {
  268. return false;
  269. }
  270. let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
  271. if (!records || records.length <= 0) {
  272. return false;
  273. }
  274. callback(event);
  275. return true;
  276. } catch (e) {
  277. console.error("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
  278. return false;
  279. }
  280. }
  281. }