const app = getApp() Page({ query: { "grouping_id": "62e601c72dc7343e137fff6f", "match_id": "62e388d4fd61d871861b80af", "project_id": "62e5fff82dc7343e137ffef5" }, data: { view: 'graph', frameStyle: { useTop: true, name: '注册', leftArrow: false, useBar: false }, canvasWidth: 375, canvasHeight: 600, pixelRatio: 1, forceMini: false, // 数据 data: undefined, riseList: [], arrangeList: [], raceList: [], groundList: [], refereeList: [], arrangeData: {}, // picker show: false, personList: [], selectNode: undefined }, // 计算晋级图 computedTreeData() { const getWinnerNumList = this.data.riseList; // 将每个小组取多少人收到1个纯数字的数组中 const getWinnerNum = getWinnerNumList.reduce((p, n) => p + n, 0); // 小组赛选取人数: 应该是该比赛项目的 各组选取人数加和 let level = 1; let loop = true; while (loop) { const needUserNum = 2 ** (level - 1); // 相等,说明已经计算出结果 if (needUserNum === getWinnerNum) loop = false; // 小于,说明还可以继续往后计算 else if (needUserNum < getWinnerNum) level++; else { // 大于,说明不符合淘汰赛安排,需要手动定位 loop = false; level = NaN } } if (!level) { console.log('不继续,返回了,编不了数据') return; } const levelList = []; // 1:16;2:8;3:4;4:2 for (let i = 0; i < level - 1; i++) { const t = level - i - 1; // 计算:该层的位置数量 const number = 2 ** t; const arr = []; for (let j = 1; j <= number; j++) { const obj = { id: `${i}-${j}`, num: `${i}-${j}`, pos: [i, j] } arr.push(obj); } levelList.push(arr) } // 进行数据组合,从最少的入手,依次取回,然后将取出来的数据删除掉 let getLevelIndex = levelList.length - 1; const data = this.resetData(levelList, getLevelIndex) let obj = { id: `${levelList.length}`, num: `${levelList.length}`, children: data } return obj; }, resetData(dataList, index = 0) { const thisLevelList = dataList[index] // 取出2条数据 const p1 = thisLevelList[0] const p2 = thisLevelList[1] // 删除取出的2条数据 dataList[index].shift() dataList[index].shift() if (index - 1 < 0) return [p1, p2] const p1c = this.resetData(dataList, index - 1) const p2c = this.resetData(dataList, index - 1) p1.children = p1c p2.children = p2c; return [p1, p2] }, // 点击节点事件 nodeTap(e) { const node = e.detail; if (!node) return; this.setData({ selectNode: node }) this.toOpen(); }, // 获取最基础的那一层节点数据 getFirstLevelNodes(node) { if (!node.children) return node; const res = []; const nodes = node.children; for (const node of nodes) { if (node?.children) { let list = this.getFirstLevelNodes(node); res.push(list); } else { res.push(node) } } return res.flat(); }, // 选择人员的处理 selectChange(changeNode, selectNode) { const obj = { player_name: changeNode.label, player_id: changeNode.value, node_id: selectNode.id, label: 'player_name', pos: selectNode.pos } const arrangeList = this.data.arrangeList; const i = arrangeList.findIndex(f => f.player_id === obj.player_id && f.pos && obj.pos && f.pos[0] === obj.pos[0]) if (i >= 0) arrangeList.splice(i, 1) arrangeList.push(obj) this.setData({ arrangeList }) // 并非使用数据重组的方式,将选择的数据放入创建晋级图的数据中心,而是使用一维数组,以节点id对应的方式进行数据更新,更为灵活 // 接下来需要生成比赛信息的数据 this.getRaceList(); }, // 设置比赛数据 getRaceList() { const arrangeList = this.data.arrangeList; arrangeList.sort((a, b) => { if (!a.pos) return b - a else if (!b.pos) return a - b else { // 根据 晋级节点位置,小组内节点位置进行排序 const a1 = a.pos[0] const b1 = b.pos[0] if (a1 - b1 !== 0) return a1 - b1 else { const a2 = a.pos[1] const b2 = b.pos[1] return a2 - b2 } } }) const raceList = []; for (let i = 0; i < arrangeList.length; i += 2) { const d1 = arrangeList[i] const d2 = arrangeList[i + 1] // 前后缺项,没法比赛 if (!(d1 && d2)) continue; const { pos: d1pos } = d1 const { pos: d2pos } = d2; // 前后两项的层级不一样,不能形成比赛 if (d1pos[0] !== d2pos[0]) continue // 前后两项层级一样,但是不是连续的数字,例如:1-1与1-3,不能进行比赛,必须是 前+1=后 if (d1pos[1] + 1 !== d2pos[1]) continue const { player_id: player_one, player_name: player_name_one, node_id: node_id_one } = d1 const { player_id: player_two, player_name: player_name_two, node_id: node_id_two } = d2 raceList.push({ player_one, player_name_one, node_id_one, player_two, player_name_two, node_id_two }) } // 因为是数组,所以需要将model特殊处理下,按照一定规则处理可以正常赋值 for (let i = 0; i < raceList.length; i++) { const d = raceList[i]; d.groundModelName = `ground_id-${i}`; d.refereeModelName = `referee_id-${i}`; d.timeModelName = `match_time-${i}`; } const oRaceList = this.data.raceList; for (const race of raceList) { const { node_id_one, node_id_two } = race; const r = oRaceList.find(f => f.node_id_one === node_id_one && f.node_id_two === node_id_two) if (r) { const ri = oRaceList.findIndex(f => f.node_id_one === node_id_one && f.node_id_two === node_id_two) const { groundModelName, refereeModelName, timeModelName } = race r = { ...r, groundModelName, refereeModelName, timeModelName } oRaceList.splice(ri, 1, r) } else { oRaceList.push(race) } } this.setData({ raceList: oRaceList }) }, async onLoad() { await this.getTeams() // 设置初始的晋级图 const data = this.computedTreeData(); this.setData({ data }) // 请求 小组赛的 胜者列表 await this.searchWinnerList(); await this.search(); await this.searchOthers() }, // 查询已安排的数据 async search() { let res = await app.$get(`/newCourt/api/eliminatArrange/getOne`, this.query) if (app.$checkRes(res)) { const { arrange } = res.data; this.setData({ arrangeData: res.data, arrangeList: arrange }) } res = await app.$get(`/newCourt/api/eliminateRace`, this.query) if (app.$checkRes(res)) { this.setData({ raceList: res.data }) } // 数据本地化处理下 this.getRaceList(); }, // 获取该项目的小组,形成晋级图 async getTeams() { const res = await app.$get(`/newCourt/api/raceTeam`, this.query) if (app.$checkRes(res)) { const { data } = res const riseList = data.map(i => i.rise) this.setData({ riseList }) } }, // 获取小组赛胜者名单 async searchWinnerList() { const res = await app.$post(`/newCourt/api/race/getWinnerList`, this.query) if (app.$checkRes(res)) { const { data } = res; const arr = []; for (const i of data) { const { personList, name } = i; for (const person of personList) { // person.player_name += `(${name})`; const obj = { label: person.player_name, value: person.player_id } arr.push(obj) } } this.setData({ personList: arr }) } }, /**自动排列最底层,挨个放 */ toAutoInitData() { const personList = this.data.personList; const data = this.data.data const getBaseList = data => { if (!data.children) return data; const arr = []; for (const d of data.children) { const r = getBaseList(d) arr.push(r); } return arr.flat(); } const firstList = getBaseList(data); for (let i = 0; i < firstList.length; i++) { const f = firstList[i]; const p = personList[i]; this.selectChange(p, f); } }, /**查询选项的数据 */ async searchOthers() { let res; res = await app.$get(`/newCourt/api/ground`) if (app.$checkRes(res)) { this.setData({ groundList: res.data }) } res = await app.$get(`/newCourt/api/user`, { type: '1' }) if (app.$checkRes(res)) { this.setData({ refereeList: res.data }) } }, turnView(e) { const view = e?.target?.dataset?.view || 'graph'; this.setData({ view }) }, //picker onChange(event) { const obj = event?.detail?.value; this.selectChange(obj, this.data.selectNode); this.toClose(); }, toOpen() { this.setData({ show: true }) }, toClose() { this.setData({ show: false, selectNode: undefined }) }, toSelected(event) { const data = event?.detail; const { value, model } = data; if (!model) return; const arr = model.split('-') const modelName = arr[0] const index = arr[1] const raceList = this.data.raceList; raceList[index][modelName] = value; this.setData({ raceList }) }, async toSubmit() { // 生成的比赛信息 let raceList = this.data.raceList; // 安排信息 let arrangeList = this.data.arrangeList; // arrangeList:需要将match_id,grouping_id,project_id 也放入,确定是这个项目的淘汰赛 let arrange = this.data.arrangeData; if (!arrange._id) { arrange = { arrange: arrangeList, ...this.query } } // raceList:淘汰赛的比赛赛程 raceList = raceList.map(i => { const { groundModelName, refereeModelName, timeModelName, ...others } = i return { ...others, ...this.query } }) // 创建安排 let res if (arrange._id) { res = await app.$post(`/newCourt/api/eliminatArrange/${arrange._id}`, arrange) if (app.$checkRes(res)) { console.log('淘汰赛安排创建成功') } } else { res = await app.$post(`/newCourt/api/eliminatArrange`, arrange) if (app.$checkRes(res)) { console.log('淘汰赛安排创建成功') } } res = await app.$post('/newCourt/api/eliminateRace/saveAll', raceList) wx.showToast({ title: '保存成功', }) } });