index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. const app = getApp()
  2. Page({
  3. query: {
  4. "grouping_id": "62e601c72dc7343e137fff6f",
  5. "match_id": "62e388d4fd61d871861b80af",
  6. "project_id": "62e5fff82dc7343e137ffef5"
  7. },
  8. data: {
  9. view: 'graph',
  10. frameStyle: { useTop: true, name: '注册', leftArrow: false, useBar: false },
  11. canvasWidth: 375,
  12. canvasHeight: 600,
  13. pixelRatio: 1,
  14. forceMini: false,
  15. // 数据
  16. data: undefined,
  17. riseList: [],
  18. arrangeList: [],
  19. raceList: [],
  20. groundList: [],
  21. refereeList: [],
  22. // picker
  23. show: false,
  24. personList: [],
  25. selectNode: undefined
  26. },
  27. // 计算晋级图
  28. computedTreeData() {
  29. const getWinnerNumList = this.data.riseList; // 将每个小组取多少人收到1个纯数字的数组中
  30. const getWinnerNum = getWinnerNumList.reduce((p, n) => p + n, 0); // 小组赛选取人数: 应该是该比赛项目的 各组选取人数加和
  31. let level = 1;
  32. let loop = true;
  33. while (loop) {
  34. const needUserNum = 2 ** (level - 1);
  35. // 相等,说明已经计算出结果
  36. if (needUserNum === getWinnerNum) loop = false;
  37. // 小于,说明还可以继续往后计算
  38. else if (needUserNum < getWinnerNum) level++;
  39. else {
  40. // 大于,说明不符合淘汰赛安排,需要手动定位
  41. loop = false;
  42. level = NaN
  43. }
  44. }
  45. if (!level) {
  46. console.log('不继续,返回了,编不了数据')
  47. return;
  48. }
  49. const levelList = [];
  50. // 1:16;2:8;3:4;4:2
  51. for (let i = 0; i < level - 1; i++) {
  52. const t = level - i - 1;
  53. // 计算:该层的位置数量
  54. const number = 2 ** t;
  55. const arr = [];
  56. for (let j = 1; j <= number; j++) {
  57. const obj = { id: `${i}-${j}`, num: `${i}-${j}`, pos: [i, j] }
  58. arr.push(obj);
  59. }
  60. levelList.push(arr)
  61. }
  62. // 进行数据组合,从最少的入手,依次取回,然后将取出来的数据删除掉
  63. let getLevelIndex = levelList.length - 1;
  64. const data = this.resetData(levelList, getLevelIndex)
  65. let obj = { id: `${levelList.length}`, num: `${levelList.length}`, children: data }
  66. return obj;
  67. },
  68. resetData(dataList, index = 0) {
  69. const thisLevelList = dataList[index]
  70. // 取出2条数据
  71. const p1 = thisLevelList[0]
  72. const p2 = thisLevelList[1]
  73. // 删除取出的2条数据
  74. dataList[index].shift()
  75. dataList[index].shift()
  76. if (index - 1 < 0) return [p1, p2]
  77. const p1c = this.resetData(dataList, index - 1)
  78. const p2c = this.resetData(dataList, index - 1)
  79. p1.children = p1c
  80. p2.children = p2c;
  81. return [p1, p2]
  82. },
  83. // 点击节点事件
  84. nodeTap(e) {
  85. const node = e.detail;
  86. if (!node) return;
  87. this.setData({ selectNode: node })
  88. this.toOpen();
  89. },
  90. // 获取最基础的那一层节点数据
  91. getFirstLevelNodes(node) {
  92. if (!node.children) return node;
  93. const res = [];
  94. const nodes = node.children;
  95. for (const node of nodes) {
  96. if (node?.children) {
  97. let list = this.getFirstLevelNodes(node);
  98. res.push(list);
  99. } else {
  100. res.push(node)
  101. }
  102. }
  103. return res.flat();
  104. },
  105. // 选择人员的处理
  106. selectChange(changeNode, selectNode) {
  107. const obj = { player_name: changeNode.label, player_id: changeNode.value, node_id: selectNode.id, label: 'player_name', pos: selectNode.pos }
  108. const arrangeList = this.data.arrangeList;
  109. const i = arrangeList.findIndex(f => f.player_id === obj.player_id && f.pos && obj.pos && f.pos[0] === obj.pos[0])
  110. if (i >= 0) arrangeList.splice(i, 1)
  111. arrangeList.push(obj)
  112. this.setData({ arrangeList })
  113. // 并非使用数据重组的方式,将选择的数据放入创建晋级图的数据中心,而是使用一维数组,以节点id对应的方式进行数据更新,更为灵活
  114. // 接下来需要生成比赛信息的数据
  115. this.getRaceList();
  116. },
  117. // 设置比赛数据
  118. getRaceList() {
  119. const arrangeList = this.data.arrangeList;
  120. arrangeList.sort((a, b) => {
  121. if (!a.pos) return b - a
  122. else if (!b.pos) return a - b
  123. else {
  124. // 根据 晋级节点位置,小组内节点位置进行排序
  125. const a1 = a.pos[0]
  126. const b1 = b.pos[0]
  127. if (a1 - b1 !== 0) return a1 - b1
  128. else {
  129. const a2 = a.pos[1]
  130. const b2 = b.pos[1]
  131. return a2 - b2
  132. }
  133. }
  134. })
  135. const raceList = [];
  136. for (let i = 0; i < arrangeList.length; i += 2) {
  137. const d1 = arrangeList[i]
  138. const d2 = arrangeList[i + 1]
  139. // 前后缺项,没法比赛
  140. if (!(d1 && d2)) continue;
  141. const { pos: d1pos } = d1
  142. const { pos: d2pos } = d2;
  143. // 前后两项的层级不一样,不能形成比赛
  144. if (d1pos[0] !== d2pos[0]) continue
  145. // 前后两项层级一样,但是不是连续的数字,例如:1-1与1-3,不能进行比赛,必须是 前+1=后
  146. if (d1pos[1] + 1 !== d2pos[1]) continue
  147. const { player_id: player_one, player_name: player_name_one, node_id: node_id_one } = d1
  148. const { player_id: player_two, player_name: player_name_two, node_id: node_id_two } = d2
  149. raceList.push({ player_one, player_name_one, node_id_one, player_two, player_name_two, node_id_two })
  150. }
  151. // 因为是数组,所以需要将model特殊处理下,按照一定规则处理可以正常赋值
  152. for (let i = 0; i < raceList.length; i++) {
  153. const d = raceList[i];
  154. d.groundModelName = `ground_id-${i}`;
  155. d.refereeModelName = `referee_id-${i}`;
  156. d.timeModelName = `match_time-${i}`;
  157. }
  158. this.setData({ raceList })
  159. },
  160. async onLoad() {
  161. await this.getTeams()
  162. // 设置初始的晋级图
  163. const data = this.computedTreeData();
  164. this.setData({ data })
  165. // 请求 小组赛的 胜者列表
  166. await this.searchWinnerList();
  167. await this.searchOthers()
  168. },
  169. // 获取该项目的小组,形成晋级图
  170. async getTeams() {
  171. const res = await app.$get(`/newCourt/api/raceTeam`, this.query)
  172. if (app.$checkRes(res)) {
  173. const { data } = res
  174. const riseList = data.map(i => i.rise)
  175. this.setData({ riseList })
  176. }
  177. },
  178. // 获取小组赛胜者名单
  179. async searchWinnerList() {
  180. const res = await app.$post(`/newCourt/api/race/getWinnerList`, this.query)
  181. if (app.$checkRes(res)) {
  182. const { data } = res;
  183. const arr = [];
  184. for (const i of data) {
  185. const { personList, name } = i;
  186. for (const person of personList) {
  187. // person.player_name += `(${name})`;
  188. const obj = { label: person.player_name, value: person.player_id }
  189. arr.push(obj)
  190. }
  191. }
  192. this.setData({
  193. personList: arr
  194. })
  195. }
  196. },
  197. /**自动排列最底层,挨个放 */
  198. toAutoInitData() {
  199. const personList = this.data.personList;
  200. const data = this.data.data
  201. const getBaseList = data => {
  202. if (!data.children) return data;
  203. const arr = [];
  204. for (const d of data.children) {
  205. const r = getBaseList(d)
  206. arr.push(r);
  207. }
  208. return arr.flat();
  209. }
  210. const firstList = getBaseList(data);
  211. for (let i = 0; i < firstList.length; i++) {
  212. const f = firstList[i];
  213. const p = personList[i];
  214. this.selectChange(p, f);
  215. }
  216. },
  217. /**查询选项的数据 */
  218. async searchOthers() {
  219. let res;
  220. res = await app.$get(`/newCourt/api/ground`)
  221. if (app.$checkRes(res)) {
  222. this.setData({ groundList: res.data })
  223. }
  224. res = await app.$get(`/newCourt/api/user`, { type: '1' })
  225. if (app.$checkRes(res)) {
  226. this.setData({ refereeList: res.data })
  227. }
  228. },
  229. turnView(e) {
  230. const view = e?.target?.dataset?.view || 'graph';
  231. this.setData({ view })
  232. },
  233. //picker
  234. onChange(event) {
  235. const obj = event?.detail?.value;
  236. this.selectChange(obj, this.data.selectNode);
  237. this.toClose();
  238. },
  239. toOpen() {
  240. this.setData({ show: true })
  241. },
  242. toClose() {
  243. this.setData({ show: false, selectNode: undefined })
  244. },
  245. toSelected(event) {
  246. const data = event?.detail;
  247. const { value, model } = data;
  248. if (!model) return;
  249. const arr = model.split('-')
  250. const modelName = arr[0]
  251. const index = arr[1]
  252. const raceList = this.data.raceList;
  253. raceList[index][modelName] = value;
  254. this.setData({ raceList })
  255. },
  256. async toSubmit() {
  257. // 生成的比赛信息
  258. let raceList = this.data.raceList;
  259. // 安排信息
  260. let arrangeList = this.data.arrangeList;
  261. // arrangeList:需要将match_id,grouping_id,project_id 也放入,确定是这个项目的淘汰赛
  262. const arrange = { arrange: arrangeList, ...this.query }
  263. // raceList:淘汰赛的比赛赛程
  264. raceList = raceList.map(i => {
  265. const { groundModelName, refereeModelName, timeModelName, ...others } = i
  266. return { ...others, ...this.query }
  267. })
  268. // 创建安排
  269. let res = await app.$post('/newCourt/api/eliminatArrange', arrange)
  270. if(app.$checkRes(res)) {
  271. console.log('淘汰赛安排创建成功')
  272. }
  273. res = await app.$post('/newCourt/api/eliminateRace/saveAll', raceList)
  274. console.log(res)
  275. }
  276. });