add.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. const app = getApp();
  2. const nodeSetting = function (node) {
  3. node.label = node.name
  4. return node;
  5. };
  6. const edgeSetting = function (edge) {
  7. return edge;
  8. }
  9. //调试用
  10. // const prefix = 'http://192.168.1.197:15001/newCourt/race/v2/api'
  11. const prefix = ''
  12. Page({
  13. data: {
  14. frameStyle: { useTop: true, name: '添加赛程', leftArrow: true, useBar: false },
  15. match_id: '',
  16. group_id: '',
  17. project_id: '',
  18. loadChart: false,
  19. winData: {},
  20. loseData: {},
  21. schList: [],
  22. playerList: [],
  23. canvasWidth: 375,
  24. canvasHeight: 600,
  25. pixelRatio: 2,
  26. edgeSetting,
  27. nodeSetting,
  28. tabs: {
  29. active: 'a',
  30. menu: [
  31. { title: '比赛流程', active: 'a' },
  32. { title: '败者组流程', active: 'b' },
  33. { title: '赛事赛程', active: 'c' },
  34. ],
  35. },
  36. show: false,
  37. selectNode: {},
  38. dialog: { title: '添加信息', show: false, type: '1' },
  39. form: {},
  40. // 场地
  41. addressList: [],
  42. // 裁判列表
  43. refereeList: [],
  44. // 状态列表
  45. statusList: [],
  46. },
  47. // 返回
  48. back: function () { wx.navigateBack({ delta: 1 }) },
  49. // 修改
  50. toEdit: function (e) {
  51. const that = this;
  52. const { item } = e.currentTarget.dataset;
  53. if (item._id) {
  54. that.setData({ form: item })
  55. that.setData({ dialog: { title: '添加信息', show: true, type: '1' } })
  56. }
  57. },
  58. // 场地
  59. addressChange: async function (e) {
  60. const that = this;
  61. let data = that.data.addressList[e.detail.value];
  62. if (data) {
  63. that.setData({ 'form.address_id': data.id, 'form.address_id_name': data.name });
  64. }
  65. },
  66. // 裁判
  67. refereeChange: async function (e) {
  68. const that = this;
  69. let data = that.data.refereeList[e.detail.value];
  70. if (data) {
  71. that.setData({ 'form.referee_id': data.id, 'form.referee_id_name': data.name });
  72. }
  73. },
  74. // 选择时间
  75. datetimeChange: function (e) {
  76. const that = this;
  77. that.setData({ [`form.${e.detail.name}`]: e.detail.datetime });
  78. },
  79. // 选择状态
  80. statusChange: function (e) {
  81. const that = this;
  82. let data = that.data.statusList[e.detail.value];
  83. if (data) {
  84. that.setData({ 'form.status': data.value, 'form.zhStatus': data.label });
  85. }
  86. },
  87. //保存(单条)
  88. onSubmit: async function (e) {
  89. const that = this;
  90. let form = that.data.form;
  91. let player = that.data.schList.find(i => i.id == form.id)
  92. form = { ...form, player_one: player.player_one, player_two: player.player_two }
  93. let arr;
  94. if (form.id) {
  95. arr = await app.$post(`${prefix}/eliminate/${form.id}`, form, 'race');
  96. if (arr.errcode == 0) {
  97. let data = arr?.data;
  98. let ri = this.data.schList.findIndex(f => f._id === form._id)
  99. if (ri >= 0) {
  100. const list = this.data.schList
  101. this.setStatus(data);
  102. list[ri] = data;
  103. this.setData({ schList: list })
  104. }
  105. }
  106. }
  107. if (arr.errcode == '0') { wx.showToast({ title: `维护信息完成`, icon: 'success', duration: 2000 }); that.toClose(); }
  108. else wx.showToast({ title: `${arr.errmsg}`, icon: 'error', duration: 2000 })
  109. },
  110. // 关闭弹框
  111. toClose: function () {
  112. const that = this;
  113. that.setData({ form: {} })
  114. that.setData({ dialog: { title: '查询条件', show: false, type: '1' } })
  115. },
  116. /**
  117. * 生命周期函数--监听页面加载
  118. */
  119. onLoad: async function (options) {
  120. const that = this
  121. that.setData({ match_id: options.match_id, group_id: options.group_id, project_id: options.project_id })
  122. await this.search();
  123. await this.searchUser();
  124. that.searchLevel();
  125. },
  126. /**
  127. * 查询函数
  128. */
  129. search: async function () {
  130. const that = this;
  131. const match_id = that.data.match_id;
  132. const group_id = that.data.group_id;
  133. const project_id = that.data.project_id;
  134. let arr;
  135. arr = await app.$get(`${prefix}/eliminate/graphData`, { match_id, group_id, project_id }, 'race');
  136. if (arr.errcode == '0') {
  137. const { winData, loseData } = that.groupData(arr.data);
  138. const schList = that.schData(arr.data)
  139. that.setData({ winData, loseData, schList })
  140. }
  141. arr = await app.$get(`${prefix}/eliminate/playerList`, { match_id, group_id, project_id }, 'race');
  142. if (arr.errcode == '0' && arr.data.length > 0) {
  143. that.setData({ playerList: arr.data })
  144. }
  145. },
  146. // 查询赛事赛程
  147. searchUser: async function () {
  148. const that = this;
  149. const match_id = that.data.match_id;
  150. const group_id = that.data.group_id;
  151. const project_id = that.data.project_id;
  152. const playerList = that.data.playerList;
  153. let arr;
  154. arr = await app.$get(`${prefix}/eliminate`, { match_id: match_id, group_id: group_id, project_id: project_id }, 'race');
  155. if (arr.errcode == '0' && arr.total > 0) {
  156. for (const val of arr.data) {
  157. this.setNodeInfo(val)
  158. // 状态
  159. this.setStatus(val);
  160. }
  161. that.setData({ schList: arr.data });
  162. this.setTopPlayerName();
  163. }
  164. },
  165. searchLevel: function (e) {
  166. const that = this;
  167. let nodes = that.data.winData.nodes;
  168. nodes = nodes.filter(f => !f.id.includes('l'));
  169. let mls = nodes.map(i => i.level);
  170. let marr = [];
  171. for (const i of mls) {
  172. if (!marr.includes(i)) marr.push(i)
  173. }
  174. const group = marr.map(i => {
  175. const list = nodes.filter(f => f.level == i)
  176. return list;
  177. })
  178. const schList = that.data.schList;
  179. for (const i of nodes) {
  180. const { level, id } = i;
  181. const r1 = group.find(f => f[0].level == level)
  182. let J1 = r1.length, J2 = J1 / 2;
  183. const r2 = schList.find(f => f.player_one_node == id)
  184. if (!r2) continue;
  185. r2.J1 = J1, r2.J2 = J2;
  186. }
  187. // let levels = {};
  188. // for (const val of nodes) {
  189. // let level = val.level;
  190. // levels[level];
  191. // if (levels[level]) {
  192. // levels[level].push(val);
  193. // } else {
  194. // let dui = [val];
  195. // levels[level] = dui;
  196. // }
  197. // }
  198. // for (const val of nodes) {
  199. // let level = val.level;
  200. // let node = schList.find((i) => i.player_one_node == val.id);
  201. // let J1 = levels[level].length;
  202. // let J2 = levels[level].length / 2;
  203. // if (node) node.J1 = J1, node.J2 = J2;
  204. // }
  205. that.setData({ schList: schList })
  206. },
  207. /**
  208. * 同步图与赛程的人名
  209. * @param {Object} data 赛程数据
  210. */
  211. setNodeInfo(data) {
  212. const { player_one, player_one_node, player_one_name, player_two, player_two_node, player_two_name } = data
  213. const setNode = (node_id, name) => {
  214. let data = this.data.winData;
  215. let r = data.nodes.find(f => f.id === node_id)
  216. if (r) {
  217. const ri = data.nodes.findIndex(f => f.id === node_id)
  218. r.name = name;
  219. data.nodes[ri] = r;
  220. this.setData({ winData: data })
  221. return;
  222. }
  223. data = this.data.loseData;
  224. r = data.nodes.find(f => f.id === node_id)
  225. if (r) {
  226. const ri = data.nodes.findIndex(f => f.id === node_id)
  227. r.name = name;
  228. data.nodes[ri] = r;
  229. this.setData({ loseData: data })
  230. return;
  231. }
  232. }
  233. if (player_one && player_one_node) setNode(player_one_node, player_one_name)
  234. if (player_two && player_two_node) setNode(player_two_node, player_two_name)
  235. },
  236. /**
  237. * 设置状态中文
  238. * @param {Object} data 赛程数据
  239. */
  240. setStatus(data) {
  241. let status = this.data.statusList.find(i => i.value == data.status)
  242. if (status) data.zhStatus = status.label;
  243. },
  244. /**
  245. * 给所有顶点去找到选手
  246. */
  247. setTopPlayerName() {
  248. const func = type => {
  249. const { nodes, edges } = this.data[`${type}Data`];
  250. // 顶点:是其他的target且不是任何节点的source
  251. const tops = nodes.filter(f => {
  252. const { id } = f;
  253. const r = edges.find(f => f.source === id)
  254. if (!r) return true
  255. })
  256. if (tops.length <= 0) return;
  257. for (const t of tops) {
  258. const { id } = t;
  259. const es = edges.filter(f => f.target === id)
  260. const ns = nodes.filter(f => es.find(ef => ef.source === f.id))
  261. const headNodeId = ns[0]?.id;
  262. const lastNodeId = ns[ns.length - 1]?.id
  263. const r = this.data.schList.find(f => (f.player_one_node === headNodeId && f.player_two_node === lastNodeId) || (f.player_one_node === lastNodeId && f.player_two_node === headNodeId))
  264. if (!r) continue;
  265. const { player_one_score, player_one_name, player_two_score, player_two_name, status } = r
  266. // 未结束不查
  267. if (status !== '2') continue;
  268. if (player_one_score > player_two_score) t.name = player_one_name
  269. else t.name = player_two_name
  270. const ri = nodes.findIndex(f => f.id === t.id)
  271. nodes[ri] = t;
  272. }
  273. this.setData({ [`${type}Data.nodes`]: nodes })
  274. }
  275. func('win')
  276. func('lose')
  277. },
  278. /**
  279. * 选中选手的处理
  280. * @param {Object} selected 选中的选手数据
  281. */
  282. selectPlayer({ detail: selected }) {
  283. let node = this.data.selectNode;
  284. const { _id: player_id, name } = selected
  285. node = { ...node, player_id, name }
  286. let targetData;
  287. let type;
  288. if (node.mark && !node.mark.includes('w')) {
  289. // 需要进入胜者节点中进行查找
  290. targetData = this.data.loseData.nodes
  291. type = 'lose'
  292. } else {
  293. targetData = this.data.winData.nodes
  294. type = 'win'
  295. }
  296. const i = targetData.findIndex(f => f.id === node.id)
  297. if (i < 0) {
  298. console.warn('未在合理的范围内找到更改的节点')
  299. return false
  300. }
  301. targetData[i] = node;
  302. this.setData({ [`${type}Data.nodes`]: targetData })
  303. // 修改赛程部分
  304. // 找到该节点的数据
  305. const schList = this.data.schList;
  306. const sch = schList.find(f => f.player_one_node === node.id || f.player_two_node === node.id)
  307. if (!sch) {
  308. console.warn('没找到该节点所在的赛程')
  309. return
  310. }
  311. if (sch.player_one_node === node.id) {
  312. sch.player_one = node.player_id;
  313. sch.player_one_name = node.name;
  314. } else {
  315. sch.player_two = node.player_id;
  316. sch.player_two_name = node.name;
  317. }
  318. // const schIndex = schList.findIndex(f => f.player_one_node === node.id || f.player_two_node === node.id)
  319. // schList.splice(schIndex, 1, sch)
  320. // this.setData({ schList })
  321. this.setData({ form: sch })
  322. this.onSubmit();
  323. },
  324. /**
  325. * 选择节点并存储在selectNode变量中
  326. * @param {Object} node 节点数据
  327. */
  328. nodeSelect({ detail: node }) {
  329. this.setData({ show: true, selectNode: node })
  330. },
  331. /**
  332. * 给流程图数据分组
  333. * @param {Array} data 流程图数据
  334. */
  335. groupData(data) {
  336. const { nodes, edges } = data;
  337. // 按胜/败进行分组,显示在2个选项卡中
  338. const winNodes = nodes.filter(f => !f.mark || f.mark.includes('w'))
  339. const winEdges = this.getNodesEdges(winNodes, edges);
  340. const loseNodes = nodes.filter(f => f.mark && !f.mark.includes('w'))
  341. const loseEdges = this.getNodesEdges(loseNodes, edges);
  342. return { winData: { nodes: winNodes, edges: winEdges }, loseData: { nodes: loseNodes, edges: loseEdges } }
  343. },
  344. /**
  345. * 获取该图中的赛程列表
  346. * @param {Object} data 流程图数据
  347. */
  348. schData(data) {
  349. const { edges } = data;
  350. let stop = false;
  351. const schList = [];
  352. let dupAll = JSON.parse(JSON.stringify(edges))
  353. while (!stop) {
  354. const dup = JSON.parse(JSON.stringify(dupAll))
  355. // 取出第一个关系
  356. const head = dup[0]
  357. // 删除第一个关系
  358. dup.shift();
  359. // 查看是否有与第一个关系指向一个目标的地方
  360. const r = dup.find(f => f.target === head.target)
  361. if (r) {
  362. // 有,则将这俩关系组为一个比赛,然后在dup中删除
  363. const sch = { player_one_node: head.source, player_two_node: r.source }
  364. schList.push(sch)
  365. const ri = dup.find(f => f.target === head.target)
  366. dup.splice(ri, 1)
  367. }
  368. dupAll = dup;
  369. if (dupAll.length <= 0) stop = true
  370. }
  371. return schList;
  372. },
  373. /**
  374. * 找到这些节点的边关系
  375. * @param {Array} list 节点数据
  376. * @param {Array} edges 所有的辺数据
  377. */
  378. getNodesEdges(list, edges) {
  379. const fedges = [];
  380. for (let i = 0; i < list.length; i += 2) {
  381. const n1 = list[i];
  382. const n2 = list[i + 1]
  383. const n1id = n1.id;
  384. const n2id = n2.id
  385. if (!n1id || !n2id) continue;
  386. const n1e = edges.find(f => f.source === n1id)
  387. const n2e = edges.find(f => f.source === n2id)
  388. if (!n1e || !n2e) continue;
  389. const n1et = n1e.target;
  390. const n2et = n2e.target;
  391. if (n1et === n2et) fedges.push(n1e, n2e)
  392. }
  393. return fedges;
  394. },
  395. tabsChange: function (e) {
  396. const that = this;
  397. let { active } = e.detail;
  398. that.setData({ 'tabs.active': active });
  399. },
  400. /**
  401. * 生命周期函数--监听页面显示
  402. */
  403. onShow: function () {
  404. this.setData({ loadChart: true })
  405. const that = this;
  406. // 监听用户是否登录
  407. that.watchLogin();
  408. },
  409. // 监听用户是否登录
  410. watchLogin: async function () {
  411. const that = this;
  412. wx.getStorage({
  413. key: 'raceuser',
  414. success: async res => {
  415. // 场地
  416. let arr;
  417. arr = await app.$get(`${prefix}/matchAddress`, { belong_id: res.data._id, is_use: '0' }, 'race');
  418. if (arr.errcode == '0') { that.setData({ addressList: arr.data }) }
  419. // 裁判
  420. arr = await app.$get(`${prefix}/user`, { parent_id: res.data._id, type: '2' }, 'race')
  421. if (arr.errcode == '0') {
  422. for (const val of arr.data) { val.name = val.user_id.name }
  423. that.setData({ refereeList: arr.data })
  424. }
  425. // 状态
  426. arr = await app.$get(`/dict`, { code: 'schedule_status' });
  427. if (arr.errcode == '0' && arr.total > 0) that.setData({ statusList: arr.data[0].list });
  428. },
  429. fail: async res => {
  430. wx.redirectTo({ url: '/pages/index/index' })
  431. }
  432. })
  433. },
  434. })