add.js 16 KB

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