From 07ceb7ce27206e02363b910c0c9f07a0fdc21ff2 Mon Sep 17 00:00:00 2001 From: Akirami <839592615@qq.com> Date: Wed, 26 May 2021 18:12:48 +0800 Subject: [PATCH] YoCool-v1.1.8 --- Origin/static/.gitignore | 1 + Origin/static/README.md | 13 + Origin/static/admin/groups.js | 57 + Origin/static/admin/pool-setting.js | 45 + Origin/static/admin/setting.js | 97 ++ Origin/static/admin/users.js | 134 ++ Origin/static/chara_marks.png | Bin 0 -> 4927 bytes Origin/static/clan/panel.js | 275 +++++ Origin/static/clan/progress.js | 282 +++++ Origin/static/clan/setting.js | 163 +++ Origin/static/clan/statistics.js | 42 + Origin/static/clan/statistics/deviation.png | Bin 0 -> 6213 bytes Origin/static/clan/statistics/many.png | Bin 0 -> 38200 bytes Origin/static/clan/statistics/order.png | Bin 0 -> 7094 bytes Origin/static/clan/statistics/pie.png | Bin 0 -> 5748 bytes Origin/static/clan/statistics/statistics2.js | 1095 +++++++++++++++++ Origin/static/clan/subscribers.js | 86 ++ Origin/static/clan/user.js | 136 ++ Origin/static/gacha.js | 64 + Origin/static/gongan.png | Bin 0 -> 3830 bytes Origin/static/marionette.js | 48 + Origin/static/password.js | 344 ++++++ Origin/static/small.ico | Bin 0 -> 16958 bytes .../static/yocool/css/style.1622013138001.css | 264 ++++ .../static/yocool/js/yocool.1622013138001.js | 1 + Origin/template/404.html | 14 + Origin/template/about.html | 76 ++ Origin/template/admin/groups.html | 38 + Origin/template/admin/pool-setting.html | 43 + Origin/template/admin/setting.html | 254 ++++ Origin/template/admin/users.html | 79 ++ Origin/template/clan/panel.html | 221 ++++ Origin/template/clan/progress.html | 339 +++++ Origin/template/clan/setting.html | 91 ++ Origin/template/clan/statistics.html | 126 ++ .../template/clan/statistics/statistics1.html | 94 ++ .../template/clan/statistics/statistics2.html | 177 +++ Origin/template/clan/subscribers.html | 54 + Origin/template/clan/unauthorized.html | 14 + Origin/template/clan/user.html | 98 ++ Origin/template/help.html | 239 ++++ Origin/template/homepage.html | 86 ++ Origin/template/login-code.html | 18 + Origin/template/login.html | 140 +++ Origin/template/manual.html | 81 ++ Origin/template/marionette.html | 31 + Origin/template/password.html | 157 +++ Origin/template/unauthorized.html | 16 + Origin/template/user-info.html | 155 +++ Origin/template/user.html | 140 +++ PrincessAdventure/template/about.html | 2 +- README.md | 10 +- 52 files changed, 5932 insertions(+), 8 deletions(-) create mode 100644 Origin/static/.gitignore create mode 100644 Origin/static/README.md create mode 100644 Origin/static/admin/groups.js create mode 100644 Origin/static/admin/pool-setting.js create mode 100644 Origin/static/admin/setting.js create mode 100644 Origin/static/admin/users.js create mode 100644 Origin/static/chara_marks.png create mode 100644 Origin/static/clan/panel.js create mode 100644 Origin/static/clan/progress.js create mode 100644 Origin/static/clan/setting.js create mode 100644 Origin/static/clan/statistics.js create mode 100644 Origin/static/clan/statistics/deviation.png create mode 100644 Origin/static/clan/statistics/many.png create mode 100644 Origin/static/clan/statistics/order.png create mode 100644 Origin/static/clan/statistics/pie.png create mode 100644 Origin/static/clan/statistics/statistics2.js create mode 100644 Origin/static/clan/subscribers.js create mode 100644 Origin/static/clan/user.js create mode 100644 Origin/static/gacha.js create mode 100644 Origin/static/gongan.png create mode 100644 Origin/static/marionette.js create mode 100644 Origin/static/password.js create mode 100644 Origin/static/small.ico create mode 100644 Origin/static/yocool/css/style.1622013138001.css create mode 100644 Origin/static/yocool/js/yocool.1622013138001.js create mode 100644 Origin/template/404.html create mode 100644 Origin/template/about.html create mode 100644 Origin/template/admin/groups.html create mode 100644 Origin/template/admin/pool-setting.html create mode 100644 Origin/template/admin/setting.html create mode 100644 Origin/template/admin/users.html create mode 100644 Origin/template/clan/panel.html create mode 100644 Origin/template/clan/progress.html create mode 100644 Origin/template/clan/setting.html create mode 100644 Origin/template/clan/statistics.html create mode 100644 Origin/template/clan/statistics/statistics1.html create mode 100644 Origin/template/clan/statistics/statistics2.html create mode 100644 Origin/template/clan/subscribers.html create mode 100644 Origin/template/clan/unauthorized.html create mode 100644 Origin/template/clan/user.html create mode 100644 Origin/template/help.html create mode 100644 Origin/template/homepage.html create mode 100644 Origin/template/login-code.html create mode 100644 Origin/template/login.html create mode 100644 Origin/template/manual.html create mode 100644 Origin/template/marionette.html create mode 100644 Origin/template/password.html create mode 100644 Origin/template/unauthorized.html create mode 100644 Origin/template/user-info.html create mode 100644 Origin/template/user.html diff --git a/Origin/static/.gitignore b/Origin/static/.gitignore new file mode 100644 index 0000000..4367d18 --- /dev/null +++ b/Origin/static/.gitignore @@ -0,0 +1 @@ +*.gz \ No newline at end of file diff --git a/Origin/static/README.md b/Origin/static/README.md new file mode 100644 index 0000000..77a9aeb --- /dev/null +++ b/Origin/static/README.md @@ -0,0 +1,13 @@ +# 开发注意事项 + +默认配置下,此目录下的文件会被 gzip 压缩缓存。修改源文件不会立刻反映在浏览器中。开发时请在配置文件中将 `web-gzp` 值设置为 `0` + +或者使用下面的命令删除所有缓存 + +```shell +# 查看所有 .gz 文件 +find . -name "*.gz" -type f + +# 删除所有 .gz 文件 +find . -name "*.gz" -type f -delete +``` diff --git a/Origin/static/admin/groups.js b/Origin/static/admin/groups.js new file mode 100644 index 0000000..2b0d2e2 --- /dev/null +++ b/Origin/static/admin/groups.js @@ -0,0 +1,57 @@ +var vm = new Vue({ + el: '#app', + data: { + groupData: [], + }, + mounted() { + this.refresh(); + }, + methods: { + refresh: function (event) { + var thisvue = this; + axios.post(api_path, { + action: 'get_data', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.groupData = res.data.data; + } else { + thisvue.$alert(res.data.message, '加载数据错误'); + } + }).catch(function (error) { + thisvue.$alert(error, '加载数据错误'); + }); + }, + delete_group: function (scope) { + var thisvue = this; + thisvue.$confirm('是否删除' + scope.row.group_name, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'danger' + }).then(() => { + axios.post(api_path, { + action: 'drop_group', + csrf_token: csrf_token, + group_id: scope.row.group_id, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.$message({ + message: '删除成功', + type: 'success', + }); + } else { + thisvue.$message.error('删除失败' + res.data.message); + } + }).catch(function (error) { + thisvue.$message.error(error); + }); + }).catch(() => { + thisvue.$message({ + type: 'info', + message: '已取消删除' + }); + }); + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/admin/pool-setting.js b/Origin/static/admin/pool-setting.js new file mode 100644 index 0000000..758e865 --- /dev/null +++ b/Origin/static/admin/pool-setting.js @@ -0,0 +1,45 @@ +var vm = new Vue({ + el: '#app', + data: { + settings: null, + }, + mounted() { + var thisvue = this; + axios.get(api_path).then(function (res) { + if (res.data.code == 0) { + thisvue.settings = res.data.settings; + } else { + alert(res.data.message, '加载数据错误'); + } + }).catch(function (error) { + alert(error, '加载数据错误'); + }); + }, + methods: { + addpool: function () { + let newname = "奖池" + (Object.keys(this.settings.pool).length+1); + this.$set(this.settings.pool, newname, { + prop: 0, + prop_last: 0, + prefix: "★★★", + pool: ["请输入内容"], + }); + }, + update: function () { + var thisvue = this; + axios.put(api_path, { + setting: thisvue.settings, + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + alert('设置成功,重启后生效'); + } else { + alert('设置失败:' + res.data.message); + } + }).catch(function (error) { + alert(error); + }); + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/admin/setting.js b/Origin/static/admin/setting.js new file mode 100644 index 0000000..46e8dc8 --- /dev/null +++ b/Origin/static/admin/setting.js @@ -0,0 +1,97 @@ +var vm = new Vue({ + el: '#app', + data: { + setting: {}, + activeNames: [], + bossSetting: false, + domain: '', + domainApply: false, + applyName: '', + loading: false, + }, + mounted() { + var thisvue = this; + axios.get(api_path).then(function (res) { + if (res.data.code == 0) { + thisvue.setting = res.data.settings; + } else { + alert(res.data.message); + } + }).catch(function (error) { + alert(error); + }); + }, + methods: { + update: function (event) { + this.setting.web_mode_hint = false; + axios.put( + api_path, + { + setting: this.setting, + csrf_token: csrf_token, + }, + ).then(function (res) { + if (res.data.code == 0) { + alert('设置成功,重启机器人后生效'); + } else { + alert('设置失败:' + res.data.message); + } + }).catch(function (error) { + alert(error); + }); + }, + sendApply: function (api) { + if (this.domain === '') { + alert('请选择后缀'); + return; + } + if (/^[0-9a-z]{1,16}$/.test(this.applyName)) { + ; + } else { + alert('只能包含字母、数字'); + return; + } + var thisvue = this; + this.loading = true; + axios.get( + api + '?name=' + thisvue.applyName + thisvue.domain + ).then(function (res) { + thisvue.domainApply = false; + if (res.data.code == 0) { + alert('申请成功,请等待1分钟左右解析生效'); + thisvue.setting.public_address = thisvue.setting.public_address.replace(/\/\/([^:\/]+)/, '//' + thisvue.applyName + thisvue.domain); + thisvue.update(null); + } else if (res.data.code == 1) { + alert('申请失败,此域已被占用'); + } else { + alert('申请失败,' + res.data.message); + } + thisvue.loading = false; + }).catch(function (error) { + thisvue.loading = false; + alert(error); + }); + }, + add_stage: function (area) { + this.setting.boss[area].push(this.setting.boss[area][this.setting.boss[area].length - 1].slice()); + const index = this.setting.stage_cycle[area].length - 1; + if (index >= 0) { + this.setting.stage_cycle[area].push(this.setting.stage_cycle[area][index] + 1); + } else { + this.setting.stage_cycle[area].push(2); + } + }, + remove_stage: function (area) { + if (this.setting.boss[area].length == 1) return; + this.setting.boss[area].pop(); + this.setting.stage_cycle[area].pop(); + }, + comfirm_change_clan_mode: function (event) { + this.$alert('修改模式后,公会战数据会重置。请不要在公会战期间修改!', '警告', { + confirmButtonText: '知道了', + type: 'warning', + }); + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/admin/users.js b/Origin/static/admin/users.js new file mode 100644 index 0000000..32d6b05 --- /dev/null +++ b/Origin/static/admin/users.js @@ -0,0 +1,134 @@ +var vm = new Vue({ + el: '#app', + data: { + isLoading: true, + moreLoading: false, + userData: [], + querys: { + page: 1, + page_size: 50, + qqid: null, + clan_group_id: null, + authority_group: null, + }, + query_input: { + qqid: null, + clan_group_id: null, + authority_group: null, + }, + has_more: true, + authtype: [{ + value: 100, + label: '成员', + }, { + value: 10, + label: '公会战管理员', + }, { + value: 1, + label: '主人', + }], + }, + mounted() { + this.load_more(); + }, + methods: { + datestr: function (ts) { + if (ts == 0) { + return null; + } + var nd = new Date(); + nd.setTime(ts * 1000); + return nd.toLocaleString('chinese', { hour12: false, timeZone: 'asia/shanghai' }); + }, + search: function (event) { + Object.assign(this.querys, this.query_input); + this.querys.page = 1; + this.isLoading = true; + this.userData = []; + this.load_more(); + }, + load_more: function (event) { + this.moreLoading = true; + var thisvue = this; + axios.post(api_path, { + action: 'get_data', + querys: thisvue.querys, + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.userData.push(...res.data.data); + thisvue.isLoading = false; + thisvue.moreLoading = false; + if (res.data.data.length < thisvue.querys.page_size) { + thisvue.has_more = false; + } else { + thisvue.querys.page += 1; + } + } else { + thisvue.$alert(res.data.message, '加载数据错误'); + } + }).catch(function (error) { + thisvue.$alert(error, '加载数据错误'); + }); + }, + modify: function (scope) { + var thisvue = this; + axios.post(api_path, { + action: 'modify_user', + csrf_token: csrf_token, + data: { + qqid: scope.row.qqid, + authority_group: scope.row.authority_group, + }, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.$message({ + message: '修改成功', + type: 'success', + }); + } else { + thisvue.$message.error('修改失败' + res.data.message); + } + }).catch(function (error) { + thisvue.$message.error(error); + }); + }, + delete_user: function (scope) { + var thisvue = this; + thisvue.$confirm('是否删除' + scope.row.nickname, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'danger' + }).then(() => { + axios.post(api_path, { + action: 'delete_user', + csrf_token: csrf_token, + data: { + qqid: scope.row.qqid, + }, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.$message({ + message: '删除成功', + type: 'success', + }); + } else { + thisvue.$message.error('删除失败' + res.data.message); + } + }).catch(function (error) { + thisvue.$message.error(error); + }); + }).catch(() => { + thisvue.$message({ + type: 'info', + message: '已取消删除' + }); + }); + + + + + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/chara_marks.png b/Origin/static/chara_marks.png new file mode 100644 index 0000000000000000000000000000000000000000..002240831bac79c9610f32c799f0a30fd88c9bcc GIT binary patch literal 4927 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 literal 0 HcmV?d00001 diff --git a/Origin/static/clan/panel.js b/Origin/static/clan/panel.js new file mode 100644 index 0000000..769aa44 --- /dev/null +++ b/Origin/static/clan/panel.js @@ -0,0 +1,275 @@ +if (!Object.defineProperty) { + alert('浏览器版本过低'); +} +var vm = new Vue({ + el: '#app', + data: { + activeIndex: "1", + groupData: {}, + bossData: { cycle: 0, full_health: 0, health: 0, num: 0 }, + is_admin: false, + self_id: 0, + today_sl: false, + members: [], + damage: 0, + defeat: null, + behalf: null, + boss_num: null, + recordFormVisible: false, + recordDefeatVisible: false, + recordBehalfVisible: false, + lockBossVisible: false, + subscribe: null, + message: '', + subscribeFormVisible: false, + subscribeCancelVisible: false, + suspendVisible: false, + statusFormVisible: false, + leavePage: false, + }, + mounted() { + var thisvue = this; + axios.post("./api/", { + action: 'get_data', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.groupData = res.data.groupData; + thisvue.bossData = res.data.bossData; + thisvue.is_admin = res.data.selfData.is_admin; + thisvue.self_id = res.data.selfData.user_id; + thisvue.today_sl = res.data.selfData.today_sl; + document.title = res.data.groupData.group_name + ' - 公会战'; + } else { + thisvue.$alert(res.data.message, '加载数据错误'); + } + }).catch(function (error) { + thisvue.$alert(error, '加载数据错误'); + }); + axios.post("./api/", { + action: 'get_member_list', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.members = res.data.members; + } else { + thisvue.$alert(res.data.message, '获取成员失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '获取成员失败'); + }); + this.status_long_polling(); + }, + destroyed: function () { + this.leavePage = true; + }, + computed: { + damageHint: function () { + if (this.damage < 10000) { + return ''; + } else if (this.damage < 100000) { + return '万'; + } else if (this.damage < 1000000) { + return '十万'; + } else if (this.damage < 10000000) { + return '百万'; + } else if (this.damage < 100000000) { + return '千万'; + } else { + return '`(*>﹏<*)′'; + } + }, + }, + methods: { + find_name: function (qqid) { + for (m of this.members) { + if (m.qqid == qqid) { + return m.nickname; + } + }; + return qqid; + }, + status_long_polling: function () { + var thisvue = this; + axios.post("./api/", { + action: 'update_boss', + timeout: 30, + csrf_token: csrf_token, + }, { + timeout: 40000, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.bossData = res.data.bossData; + thisvue.status_long_polling(); + if (res.data.notice) { + thisvue.$notify({ + title: '通知', + message: '(' + (new Date()).toLocaleTimeString('chinese', { hour12: false }) + ') ' + res.data.notice, + duration: 60000, + }); + } + } else if (res.data.code == 1) { + thisvue.status_long_polling(); + } else { + thisvue.$confirm(res.data.message, '刷新boss数据错误', { + confirmButtonText: '重试', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + thisvue.status_long_polling(); + }); + } + }).catch(function (error) { + if (thisvue.leavePage) { + return; + } + thisvue.$confirm(error, '刷新boss错误', { + confirmButtonText: '重试', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + thisvue.status_long_polling(); + }); + }); + }, + callapi: function (payload) { + var thisvue = this; + payload.csrf_token = csrf_token; + axios.post("./api/", payload).then(function (res) { + if (res.data.code == 0) { + if (res.data.bossData) { + thisvue.bossData = res.data.bossData; + } + if (res.data.notice) { + thisvue.$notify({ + title: '通知', + message: res.data.notice, + duration: 60000, + }); + } + } else { + thisvue.$alert(res.data.message, '数据错误'); + } + }).catch(function (error) { + thisvue.$alert(error, '数据错误'); + }); + }, + recordselfdamage: function (event) { + this.callapi({ + action: 'addrecord', + defeat: false, + damage: this.damage, + behalf: null, + message:this.message, + }); + this.recordFormVisible = false; + }, + recordselfdefeat: function (event) { + this.callapi({ + action: 'addrecord', + defeat: true, + behalf: null, + message:this.message, + }); + this.recordDefeatVisible = false; + }, + recorddamage: function (event) { + this.callapi({ + action: 'addrecord', + defeat: this.defeat, + behalf: this.behalf, + damage: this.damage, + message:this.message, + }); + this.recordBehalfVisible = false; + }, + recordundo: function (event) { + this.callapi({ + action: 'undo', + }); + }, + challengeapply: function (appli_type) { + this.callapi({ + action: 'apply', + extra_msg:this.message, + appli_type:appli_type, + }); + this.lockBossVisible=false; + }, + cancelapply: function (event) { + this.callapi({ + action: 'cancelapply', + }); + }, + addsuspend: function (event) { + this.callapi({ + action: 'addsubscribe', + boss_num: 0, + message: this.message, + }); + this.suspendVisible=false; + }, + cancelsuspend: function (event) { + this.callapi({ + action: 'cancelsubscribe', + boss_num: 0, + }); + }, + save_slot: function (event) { + this.today_sl = !this.today_sl; + this.callapi({ + action: 'save_slot', + today: this.today_sl, + }); + }, + addsubscribe: function (event) { + this.callapi({ + action: 'addsubscribe', + boss_num: parseInt(this.subscribe), + message: this.message, + }); + this.subscribeFormVisible = false; + }, + cancelsubscribe: function (event) { + this.callapi({ + action: 'cancelsubscribe', + boss_num: parseInt(this.subscribe), + }); + this.subscribeCancelVisible = false + }, + startmodify: function (event) { + if (this.is_admin) { + this.statusFormVisible = true; + } else { + this.$alert('此功能仅公会战管理员可用'); + } + }, + modify: function (event) { + this.callapi({ + action: 'modify', + cycle: this.bossData.cycle, + boss_num: this.bossData.num, + health: this.bossData.health, + }); + this.statusFormVisible = false; + }, + handleSelect(key, keyPath) { + this.leavePage = true; + switch (key) { + case '2': + window.location = './subscribers/'; + break; + case '3': + window.location = './progress/'; + break; + case '4': + window.location = './statistics/'; + break; + case '5': + window.location = `./${this.self_id}/`; + break; + } + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/clan/progress.js b/Origin/static/clan/progress.js new file mode 100644 index 0000000..d30ceca --- /dev/null +++ b/Origin/static/clan/progress.js @@ -0,0 +1,282 @@ +if (!Object.defineProperty) { + alert('浏览器版本过低'); +} +var vm = new Vue({ + el: '#app', + data: { + progressData: [], + members: [], + tailsData: [], + tailsDataVisible: false, + group_name: null, + reportDate: null, + activeIndex: '3', + multipleSelection: [], + sendRemindVisible: false, + send_via_private: false, + dropMemberVisible: false, + today: 0, + isMobile: false, + }, + mounted() { + var thisvue = this; + axios.all([ + axios.post('../api/', { + action: 'get_challenge', + csrf_token: csrf_token, + ts: (thisvue.get_now() / 1000), + }), + axios.post('../api/', { + action: 'get_member_list', + csrf_token: csrf_token, + }), + ]).then(axios.spread(function (res, memres) { + if (res.data.code != 0) { + thisvue.$alert(res.data.message, '获取记录失败'); + return; + } + if (memres.data.code != 0) { + thisvue.$alert(memres.data.message, '获取成员失败'); + return; + } + thisvue.members = memres.data.members; + for (m of thisvue.members) { + m.finished = 0; + m.detail = []; + } + thisvue.today = res.data.today; + thisvue.isToday = true; + thisvue.refresh(res.data.challenges); + })).catch(function (error) { + thisvue.$alert(error, '获取数据失败'); + }); + }, + beforeMount () { + var userAgentInfo = navigator.userAgent; + var Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']; + for (var v = 0; v < Agents.length; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + this.isMobile = true + break + } + } + }, + methods: { + clickCell: function (row, column) { + if (column.label === '昵称') { + this.$refs.multipleTable.toggleRowExpansion(row) + } + }, + getRowClass: function (e) { + return e.row.finished === 3 ? 'finishedRow' : '' + }, + get_now: function () { + let d = new Date(); + return Date.parse(d); + }, + csummary: function (cha) { + if (cha == undefined) { + return ''; + } + if (cha.behalf == null) { + return `(${cha.cycle}-${cha.boss_num}) ${cha.damage}`; + } + if (cha.behalf == cha.qqid) { + return `(${cha.cycle}-${cha.boss_num}) ${cha.damage}`; + } + return `(${cha.cycle}-${cha.boss_num}) ${cha.damage}
由 ${this.find_name(cha.behalf)}(${cha.behalf}) 上报
`; + }, + cdetail: function (cha) { + if (cha == undefined) { + return ''; + } + var nd = new Date(); + nd.setTime(cha.challenge_time * 1000); + var tz = Intl.DateTimeFormat().resolvedOptions().timeZone + var detailstr = nd.toLocaleString('chinese', { hour12: false, timeZone: tz }) + '\n'; + detailstr += cha.cycle + '周目' + cha.boss_num + '号boss\n'; + detailstr += (cha.health_ramain + cha.damage).toLocaleString(options = { timeZone: tz }) + '→' + cha.health_ramain.toLocaleString(options = { timeZone: tz }); + if (cha.message) { + detailstr += '\n留言:' + cha.message; + } + return detailstr; + }, + arraySpanMethod: function ({ row, column, rowIndex, columnIndex }) { + if (columnIndex >= 4) { + if (columnIndex % 2 == 0) { + var detail = row.detail[columnIndex - 4]; + if (detail != undefined && detail.health_ramain != 0) { + return [1, 2]; + } + } else { + var detail = row.detail[columnIndex - 5]; + if (detail != undefined && detail.health_ramain != 0) { + return [0, 0]; + } + } + } + }, + report_day: function (event) { + var thisvue = this; + var reportDatetime = (thisvue.reportDate ? (thisvue.reportDate.getTime() - thisvue.reportDate.getTimezoneOffset() * 60000) / 1000 : null); + axios.post('../api/', { + action: 'get_challenge', + csrf_token: csrf_token, + ts: reportDatetime, + }).then(function (res) { + if (res.data.code != 0) { + thisvue.$alert(res.data.message, '获取记录失败'); + } else { + thisvue.refresh(res.data.challenges); + thisvue.isToday = (thisvue.reportDate ? thisvue.today == Math.floor(reportDatetime / 86400) : true); + } + }).catch(function (error) { + thisvue.$alert(error, '获取记录失败'); + }) + }, + refresh: function (challenges) { + challenges.sort((a, b) => a.qqid - b.qqid); + this.progressData = [...this.members]; + // for (m of this.progressData) m.today_total_damage = 0; + var thisvue = this; + var m = { qqid: -1 }; + for (c of challenges) { + if (m.qqid != c.qqid) { + thisvue.update_member_info(m); + m = { + qqid: c.qqid, + finished: 0, + detail: [], + // today_total_damage: 0, + } + } + m.detail[2 * m.finished] = c; + // m.today_total_damage += c.damage; + if (c.is_continue) { + m.finished += 0.5; + } else { + if (c.health_ramain != 0) { + m.finished += 1; + } else { + m.finished += 0.5; + } + } + } + thisvue.update_member_info(m); + }, + viewTails: function () { + this.tailsData = []; + for (const m of this.progressData) { + if (m.finished % 1 != 0) { + let c = m.detail[m.finished * 2 - 1]; + this.tailsData.push({ + qqid: m.qqid, + nickname: m.nickname, + boss: c.cycle + '-' + c.boss_num, + damage: c.damage, + message: c.message, + }); + } + } + this.tailsDataVisible = true; + }, + update_member_info: function (m) { + if (m.qqid == -1) { + return + } + for (let index = 0; index < this.progressData.length; index++) { + if (m.qqid == this.progressData[index].qqid) { + m.nickname = this.progressData[index].nickname; + m.sl = this.progressData[index].sl; + this.progressData[index] = m; + return + } + } + m.nickname = '(未加入)'; + this.progressData.push(m); + }, + find_name: function (qqid) { + for (m of this.members) { + if (m.qqid == qqid) { + return m.nickname; + } + }; + return qqid; + }, + viewInExcel: function () { + var icons = document.getElementsByTagName('span'); + while (icons[0]) { + icons[0].remove(); + } + var uri = 'data:application/vnd.ms-excel;base64,'; + var ctx = '' + document.getElementsByTagName('thead')[0].innerHTML + document.getElementsByTagName('tbody')[0].innerHTML + '
'; + window.location.href = uri + window.btoa(unescape(encodeURIComponent(ctx))); + document.documentElement.innerHTML = "请在Excel中查看(如果无法打开,请安装最新版本Excel)\n或者将整个表格复制,粘贴到Excel中使用"; + }, + handleTitleSelect(key, keyPath) { + switch (key) { + case '1': + window.location = '../'; + break; + case '2': + window.location = '../subscribers/'; + break; + case '3': + window.location = '../progress/'; + break; + case '4': + window.location = '../statistics/'; + break; + case '5': + window.location = `../my/`; + break; + } + }, + handleSelectionChange(val) { + this.multipleSelection = val; + }, + selectUnfinished(event) { + this.progressData.forEach(row => { + if (row.finished < 3) { + this.$refs.multipleTable.toggleRowSelection(row, true); + } else { + this.$refs.multipleTable.toggleRowSelection(row, false); + } + }); + }, + sendRequest(action) { + if (this.multipleSelection.length === 0) { + this.$alert('请先勾选成员', '失败'); + } + var memberlist = []; + this.multipleSelection.forEach(row => { + memberlist.push(row.qqid); + }); + var thisvue = this; + var payload = { + action: action, + csrf_token: csrf_token, + memberlist: memberlist, + }; + if (action === 'send_remind') { + payload.send_private_msg = thisvue.send_via_private; + } + axios.post('../api/', payload).then(function (res) { + if (res.data.code != 0) { + if (res.data.code == 11) { + res.data.message = '你的权限不足,如需提升权限,请联系维护组操作'; + } + thisvue.$alert(res.data.message, '无操作权限'); + } else { + thisvue.$notify({ + title: '提醒', + message: res.data.notice, + }); + } + }).catch(function (error) { + thisvue.$alert(error, '请求失败'); + }) + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/clan/setting.js b/Origin/static/clan/setting.js new file mode 100644 index 0000000..66eb533 --- /dev/null +++ b/Origin/static/clan/setting.js @@ -0,0 +1,163 @@ +if (!Object.defineProperty) { + alert('浏览器版本过低'); +} +var vm = new Vue({ + el: '#app', + data: { + activeIndex: null, + groupData: {}, + battle_id: null, + data_slot_record_count: [], + form: { + game_server: null, + privacy: { + allow_guest: false, + allow_statistics_api: false, + }, + notify: { + challenge: false, + undo: false, + apply: false, + cancelapply: false, + subscribe: false, + cancelsubscribe: false, + suspend: false, + cancelsuspend: false, + modify: false, + sl: false, + }, + }, + switchVisible: false, + confirmVisible: false, + }, + mounted() { + var thisvue = this; + axios.post('./api/', { + action: 'get_setting', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.groupData = res.data.groupData; + thisvue.battle_id = res.data.groupData.battle_id; + thisvue.form.game_server = res.data.groupData.game_server; + thisvue.form.privacy.allow_guest = Boolean(res.data.privacy & 0x1); + thisvue.form.privacy.allow_statistics_api = Boolean(res.data.privacy & 0x2); + document.title = res.data.groupData.group_name + ' - 公会战设置'; + var notify_code = res.data.notification; + for (key in thisvue.form.notify) { + thisvue.form.notify[key] = Boolean(notify_code & 1); + notify_code >>= 1; + } + } else { + thisvue.$alert(res.data.message, '加载数据失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '加载数据失败'); + }); + }, + methods: { + submit: function (event) { + var thisvue = this; + var privacy = (thisvue.form.privacy.allow_guest * 0x1) + (thisvue.form.privacy.allow_statistics_api * 0x2); + var notify_code = 0; + var magnitude = 1; + for (key in thisvue.form.notify) { + notify_code += thisvue.form.notify[key] * magnitude; + magnitude <<= 1; + } + axios.post('./api/', { + action: 'put_setting', + csrf_token: csrf_token, + game_server: thisvue.form.game_server, + privacy: privacy, + notification: notify_code, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.$notify({ + title: '通知', + message: '设置成功', + }); + } else { + thisvue.$alert(res.data.message, '保存设置失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '保存设置失败'); + }); + }, + export_data: function (event) { + window.location = '../statistics/api/'; + }, + call_api: function (payload) { + var thisvue = this; + payload.csrf_token = csrf_token; + axios.post('./api/', payload).then(function (res) { + if (res.data.code == 0) { + thisvue.$notify({ + title: '通知', + message: '成功', + }); + } else { + thisvue.$alert(res.data.message, '失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '失败'); + }); + }, + clear_data_slot: function (event) { + this.call_api({ + action: 'clear_data_slot', + }); + this.confirmVisible = false; + }, + // new_data_slot: function (event) { + // this.call_api({ + // action: 'new_data_slot', + // }); + // }, + switch_data_slot: function (event) { + this.call_api({ + action: 'switch_data_slot', + battle_id: this.battle_id, + }); + this.switchVisible = false; + }, + get_data_slot_record_count: function () { + if (this.data_slot_record_count.length !== 0) { + return + } + var thisvue = this; + axios.post('./api/', { + action: 'get_data_slot_record_count', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.data_slot_record_count = res.data.counts; + } else { + thisvue.$alert(res.data.message, '失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '失败'); + }); + }, + handleSelect(key, keyPath) { + switch (key) { + case '1': + window.location = '../'; + break; + case '2': + window.location = '../subscribers/'; + break; + case '3': + window.location = '../progress/'; + break; + case '4': + window.location = '../statistics/'; + break; + case '5': + window.location = `../my/`; + break; + } + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/clan/statistics.js b/Origin/static/clan/statistics.js new file mode 100644 index 0000000..daf4c71 --- /dev/null +++ b/Origin/static/clan/statistics.js @@ -0,0 +1,42 @@ +if (!Object.defineProperty) { + alert('浏览器版本过低'); +} +var vm = new Vue({ + el: '#app', + data: { + progressData: [], + members: [], + tailsData: [], + tailsDataVisible: false, + group_name: null, + reportDate: null, + activeIndex: '4', + multipleSelection: [], + sendRemindVisible: false, + send_via_private: false, + dropMemberVisible: false, + today: 0, + }, + methods: { + handleTitleSelect(key, keyPath) { + switch (key) { + case '1': + window.location = '../'; + break; + case '2': + window.location = '../subscribers/'; + break; + case '3': + window.location = '../progress/'; + break; + case '4': + window.location = '../statistics/'; + break; + case '5': + window.location = `../my/`; + break; + } + }, + } +}) + diff --git a/Origin/static/clan/statistics/deviation.png b/Origin/static/clan/statistics/deviation.png new file mode 100644 index 0000000000000000000000000000000000000000..a091026cdb52b2beac75b229f3f0aa1780540e88 GIT binary patch literal 6213 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 aUw<&)S=W8(Zn|}Xb6J_&AsS6Rlm8Fi?5i^X literal 0 HcmV?d00001 diff --git a/Origin/static/clan/statistics/order.png b/Origin/static/clan/statistics/order.png new file mode 100644 index 0000000000000000000000000000000000000000..87920686f34ea60c171990d22ddbc206d95e4159 GIT binary patch literal 7094 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 { + if (num < 10000) + return `${num.toLocaleString()}` + if (num < 100000000) + return `${(num / 10000).toLocaleString()} W` + return `${(num / 100000000).toLocaleString()} E` +} + +if (!Object.defineProperty) { + alert('浏览器版本过低'); +} +// 这代码很乱,到时候重构一下 +var vm = new Vue({ + el: '#app', + data: { + members: [], + range: '', + pickerOptions: { + shortcuts: [{ + text: '最近一周', + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + picker.$emit('pick', [start, end]); + } + }, { + text: '最近半个月', + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime(start.getTime() - 3600 * 1000 * 24 * 15); + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + picker.$emit('pick', [start, end]); + } + }, { + text: '最近一个月', + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + picker.$emit('pick', [start, end]); + } + }, { + text: '最近三个月', + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + picker.$emit('pick', [start, end]); + } + }, { + text: '最近一年', + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime(start.getTime() - 3600 * 1000 * 24 * 365); + start.setHours(0, 0, 0, 0); + end.setHours(0, 0, 0, 0); + picker.$emit('pick', [start, end]); + } + }] + }, + allChallenges: [], + activeIndex: '4', + challengeMap: {}, + challenges: [], + playerDamages: {}, + totalDamage: {}, + containTailAndContinue: true, + globalTableData: [], + playerData: { + damage: [ + + ], + }, + colorList: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'], + challengeChart: null, + bossDmgChart: null, + missChart: null, + lastChart: null, + bossBloodChart: null, + totalTimeChart: null, + bossHitChart: null, + personalProgressChart: null, + personalTimeChart: null, + totalDamageChart: null, + isLoading: true, + selectingTab: "table", + selectingQQid: parseInt(qqid) + }, + mounted() { + this.bossDmgChart = echarts.init(document.getElementById("bossDmgChart")); + this.challengeChart = echarts.init(document.getElementById("challengeChart")); + this.sumDmgChart = echarts.init(document.getElementById("sumDmgChart")); + this.missChart = echarts.init(document.getElementById("missChart")); + this.lastChart = echarts.init(document.getElementById("lastChart")); + this.bossBloodChart = echarts.init(document.getElementById("bossBloodChart")); + this.totalTimeChart = echarts.init(document.getElementById("totalTimeChart")); + this.bossHitChart = echarts.init(document.getElementById("bossHitChart")); + this.personalProgressChart = echarts.init(document.getElementById("personalProgressChart")); + this.personalTimeChart = echarts.init(document.getElementById("personalTimeChart")); + this.totalDamageChart = echarts.init(document.getElementById("totalDamageChart")); + this.selectingTab = "total"; + this.fetchData(); + }, + watch: { + containTailAndContinue: function() { + this.init(); + }, + selectingQQid: function() { + this.initChart(this.playerDamage(this.selectingQQid).bossDamageList); + this.initPlayerData(); + }, + selectingTab: function() { + this.init(); + setTimeout("vm.resizeAll()", 100); + }, + range: function() { + this.refreshData(); + this.init(); + }, + }, + + methods: { + // tools function + sum: (iterable) => { + let sum = 0; + iterable.forEach(v => sum += v); + return sum; + }, + formatTo2: (num) => { return (num >= 10) ? num.toString() : '0' + num.toString() }, + + fetchData: function() { + const that = this; + axios.get('../api/').then(res=> { + if (res.data.code != 0) { + that.$alert(res.data.message, '获取记录失败'); + that.isLoading = false; + return; + } + that.allChallenges = res.data.challenges; + that.members = res.data.members; + if (that.members.filter((elem) => {return elem.qqid == that.selectingQQid}).length == 0) { + that.selectingQQid = that.members[0].qqid; + } + that.refreshData(); + }).catch(function (error) { + that.$alert(error, '获取数据失败,请联系维护人员'); + that.isLoading = false; + console.error(error); + console.error(error.stack); + }); + }, + + filtedChallenge: function() { + if (!this.range) return this.allChallenges; + const leftRange = this.range[0].getTime() / 1000 + 18000; + const rightRange = this.range[1].getTime() / 1000 + 18000 + 86400; + return this.allChallenges.filter((elem) => {return elem.challenge_time <= rightRange && elem.challenge_time >= leftRange}); + }, + + refreshData: function() { + this.challenges = this.filtedChallenge(); + this.challengeMap = {}; + for (let challenge of this.challenges) { + let arr = this.challengeMap[challenge.qqid]; + if (arr == undefined) { + arr = []; + this.challengeMap[challenge.qqid] = arr; + } + arr.push(challenge); + } + for (let member of this.members) { + member.challenges = this.challengeMap[member.qqid]; + } + this.sortAndDivide(); + this.init(); + this.isLoading = false; + }, + + init: function() { + this.initTotalDamage(); + this.initPlayerDamage(); + this.initGlobalTableData(); + this.initPlayerData(); + if (this.selectingTab === 'total') { + this.initChart(this.totalDamage.bossDamageList); + } + else if (this.selectingTab === 'channel') { + this.initChart(this.totalDamage.bossDamageList); + } + else { + this.initChart(this.playerDamage(this.selectingQQid).bossDamageList); + } + }, + // function for init + initChart: function(bossDamageList) { + let temp = this.bossAverageDamageForChart(bossDamageList, this.containTailAndContinue); + let option = { + title: { + text: '不同 Boss 刀均伤害' + }, + tooltip: {}, + legend: { + data: ['伤害'] + }, + xAxis: { + data: temp[0], + }, + yAxis: { + axisLabel: { + formatter: numberFormatter + } + }, + series: [{ + name: '伤害', + type: 'bar', + data: temp[1], + itemStyle: { + color: (params) => { + let bossId = parseInt(temp[0][params.dataIndex][0]) - 1; + return this.colorList[bossId]; + }, + } + }] + } + + let temp2 = this.bossChallengeCountForChart(bossDamageList, true); + let option2 = { + title: { + text: '不同 Boss 出刀数' + }, + tooltip: {}, + series: [{ + type: 'pie', + center: ['50%', '50%'], + data: temp2, + itemStyle: { + color: (params) => { + let bossId = parseInt(temp2[params.dataIndex].name[0]) - 1; + return this.colorList[bossId]; + } + } + }] + } + let temp3 = this.bossSumDamageForChart(bossDamageList); + let option3 = { + title: { + text: 'Boss 总伤害' + }, + tooltip: {}, + legend: { + data: ['伤害'] + }, + xAxis: { + data: temp3[0] + }, + yAxis: { + axisLabel: { + formatter: numberFormatter + } + }, + series: [{ + name: '伤害', + type: 'bar', + data: temp3[1], + itemStyle: { + color: (params) => { + let bossId = parseInt(temp3[0][params.dataIndex][0]) - 1; + return this.colorList[bossId]; + }, + } + }] + } + let temp4 = this.bossMissForChart(this.globalTableData); + let option4 = { + title: { + text: '成员出刀考勤' + }, + tooltip: {}, + legend: { + data: ['次数'] + }, + // grid: { + // bottom: 60 + // }, + xAxis: { + type: 'category', + data: temp4[0], + axisLabel: { + interval: 0, + rotate: 45 + } + }, + yAxis: { + type: 'value', + max: Math.max.apply(temp4[1]), + min: 0 + }, + series: [{ + name: '出刀次数', + data: temp4[1], + type: 'bar', + showBackground: true, + backgroundStyle: { + color: 'rgba(220, 220, 220, 0.8)' + } + }] + } + let temp5 = this.bossLastForChart(); + let option5 = { + title: { + text: '尾刀统计', + }, + tooltip: { + trigger: 'item', + formatter: '{a}
{b} : {c} ({d}%)' + }, + series: [ + { + name: '次数', + type: 'pie', + radius: '55%', + data: temp5, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + } + ] + }; + let temp6 = this.bossBloodForChart(); + let option6 = { + title: { + text: 'BOSS血量曲线', + }, + grid: { + bottom: 80 + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + animation: false, + label: { + formatter: params => { + if (params.axisDimension === "x") { + return (new Date(params.value)).toLocaleString(options = { timeZone: 'asia/shanghai' }); + } + if (params.axisDimension === "y") { + return params.value.toLocaleString(); + } + return params.value; + } + } + }, + formatter: (params) => { + const series = params[0]; + const [ts, value] = series.data; + const matched = temp6[1].find(f => (!f.gte || f.gte <= ts) && (!f.lt || f.lt > ts)); + return `${(new Date(ts)).toLocaleString(options = { timeZone: 'asia/shanghai' })}
${series.marker}${(matched && matched.label) + "
" || ""}血量:${value.toLocaleString()}` + } + }, + toolbox: { + show: true, + feature: { + dataZoom: { + yAxisIndex: 'none' + }, + restore: {}, + saveAsImage: {} + } + }, + xAxis: { + type: 'time', + boundaryGap: false, + }, + yAxis: { + type: 'value', + axisLabel: { + formatter: numberFormatter + }, + axisPointer: { + snap: true + } + }, + dataZoom: [ + { + type: 'inside' + }, + { + show: true, + realtime: true, + handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z', + handleSize: '80%', + handleStyle: { + color: '#fff', + shadowBlur: 3, + shadowColor: 'rgba(0, 0, 0, 0.6)', + shadowOffsetX: 2, + shadowOffsetY: 2 + }, + } + ], + visualMap: { + type: "piecewise", + show: false, + dimension: 0, + seriesIndex: 0, + pieces: temp6[1] + }, + series: [ + { + name: '血量', + type: 'line', + // smooth: true, + data: temp6[0], + areaStyle: {}, + } + ] + }; + let temp7 = this.timeForChart(this.challenges); + let option7 = { + title: { + text: '出刀时间', + }, + tooltip: { + trigger: 'axis', + axisPointer: { + animation: true, + label: { + backgroundColor: '#505765' + } + } + }, + xAxis: { + type: 'category', + boundaryGap: true, + axisLine: {onZero: false}, + data: [...Array(24).keys()].map(i => `${i}时`), + }, + yAxis: { + name: '刀', + type: 'value' + }, + visualMap: [{ + type: "piecewise", + show: false, + dimension: 0, + seriesIndex: 0, + pieces: [ + {lte: 5, label: '凌晨', color: 'grey'}, + {gt: 5,lte: 12, label: '上午', color: '#9cc5b0'}, + {gt: 12,lte: 18, label: '下午', color: '#c54730'}, + {gt: 18, label: '晚上', color: '#384b5a'}, + ] + }], + series: { + name: '刀数', + type: 'bar', + animation: true, + lineStyle: { + width: 2 + }, + data: temp7 + } + } + let temp8 = this.bossPlayerHitCountForChart(); + let option8 = { + title: { + text: '成员BOSS出刀数' + }, + tooltip: { + position: 'top' + }, + animation: true, + xAxis: { + type: 'category', + data: temp8[1], + splitArea: { + show: true + }, + axisLabel: { + interval: 0, + rotate: 45 + } + }, + yAxis: { + type: 'category', + data: temp8[0], + splitArea: { + show: true + } + }, + visualMap: { + min: 0, + max: 10, + calculable: true, + orient: 'horizontal', + left: 'center', + top: 0 + }, + series: [{ + name: 'Punch Card', + type: 'heatmap', + data: temp8[2], + label: { + show: true + }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + }] + }; + let temp9 = this.membersDamageForChart(this.globalTableData); + let option9 = { + title: { + text: '成员伤害统计' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + crossStyle: { + color: '#999' + } + } + }, + toolbox: { + feature: { + dataView: {show: true, readOnly: false}, + magicType: {show: true, type: ['line', 'bar']}, + restore: {show: true}, + saveAsImage: {show: true} + } + }, + legend: { + data: ['总伤害', '刀均伤害'] + }, + xAxis: [ + { + type: 'category', + data: temp9[0], + axisPointer: { + type: 'shadow' + }, + axisLabel: { + interval: 0, + rotate: 45 + }, + boundaryGap: true, + } + ], + yAxis: [ + { + type: 'value', + name: '总伤害', + axisLabel: { + formatter: numberFormatter + } + }, + { + type: 'value', + name: '刀均伤害', + axisLabel: { + formatter: numberFormatter + } + } + ], + series: [ + { + name: '总伤害', + type: 'bar', + data: temp9[1] + }, + { + name: '刀均伤害', + type: 'bar', + yAxisIndex: 1, + data: temp9[2] + } + ] + }; + + + this.bossDmgChart.setOption(option); + this.challengeChart.setOption(option2); + this.sumDmgChart.setOption(option3); + this.missChart.setOption(option4); + this.lastChart.setOption(option5); + try{ + // 这里有时会出现一个错误,原因未知 + this.bossBloodChart.setOption(option6); + }catch(e){console.error(e)} + this.totalTimeChart.setOption(option7); + this.bossHitChart.setOption(option8); + this.totalDamageChart.setOption(option9); + }, + + resizeAll: function() { + this.sumDmgChart.resize(); + this.missChart.resize(); + this.lastChart.resize(); + this.bossBloodChart.resize(); + this.totalTimeChart.resize(); + this.personalProgressChart.resize(); + this.personalTimeChart.resize(); + this.bossHitChart.resize(); + this.totalDamageChart.resize(); + }, + + initPlayerData: function() { + let max = 0, min = 2147483647, s = [0, 0, 0], c = [0, 0, 0]; + let pchallenge = this.challengeMap[this.selectingQQid]; + if (pchallenge != undefined) { + for (let date in pchallenge) { + let clist = pchallenge[date]; + let dmglist = [] + for (let i = 0; i < clist.length; i++) { + let damage = 0; + if (clist[i].health_ramain != 0) { + damage = clist[i].damage; + } + else if (clist[i+1] && clist[i+1].is_continue) { + damage = clist[i].damage + clist[i+1].damage + i++; + } + if (max < damage) max = damage; + if (min > damage) min = damage; + dmglist.push(damage); + dmglist.sort((a, b) => {return b - a}); + } + for (let i = 0; i < dmglist.length; i++) { + s[i] += dmglist[i]; + c[i]++; + } + } + this.playerData.damage = [ + {label: '最高单次伤害', value: max}, + {label: '最低单次伤害', value: min}, + {label: '伤害最高刀均伤害', value: Math.floor(s[0] / c[0])}, + {label: '伤害次高刀均伤害', value: Math.floor(s[1] / c[1])}, + {label: '伤害最低刀均伤害', value: Math.floor(s[2] / c[2])} + ] + } else { + this.playerData.damage = [ + {label: '最高单次伤害', value: 0}, + {label: '最低单次伤害', value: 0}, + {label: '伤害最高刀均伤害', value: 0}, + {label: '伤害次高刀均伤害', value: 0}, + {label: '伤害最低刀均伤害', value: 0} + ] + } + const playerChalls = this.challenges.filter(c => c.qqid == this.selectingQQid); + const param1 = this.timeForChart(playerChalls); + const option1 = { + title: { + text: '出刀时间', + }, + tooltip: { + trigger: 'axis', + axisPointer: { + animation: true, + label: { + backgroundColor: '#505765' + } + } + }, + xAxis: { + type: 'category', + boundaryGap: true, + axisLine: {onZero: false}, + data: [...Array(24).keys()].map(i => `${i}时`), + }, + yAxis: { + name: '刀', + type: 'value' + }, + visualMap: [{ + type: "piecewise", + show: false, + dimension: 0, + seriesIndex: 0, + pieces: [ + {lte: 5, label: '凌晨', color: 'grey'}, + {gt: 5,lte: 12, label: '上午', color: '#9cc5b0'}, + {gt: 12,lte: 18, label: '下午', color: '#c54730'}, + {gt: 18, label: '晚上', color: '#384b5a'}, + ] + }], + series: { + name: '刀数', + type: 'bar', + + animation: true, + lineStyle: { + width: 2 + }, + data: param1 + } + }; + const param2 = this.dayDamageForChart(playerChalls); + const option2 = { + title: { + text: "伤害成长曲线" + }, + xAxis: { + type: 'category', + boundaryGap: false + }, + yAxis: { + type: 'value', + scale: true, + axisLabel: { + formatter: numberFormatter + } + }, + tooltip: { + trigger: 'axis', + axisPointer: { + animation: true, + } + }, + series: [ + { + type: 'line', + name: '三刀总伤害', + smooth: 0.6, + symbolSize: 10, + color: 'green', + lineStyle: { + width: 5 + }, + data: param2 + } + ] + }; + + this.personalTimeChart.setOption(option1) + this.personalProgressChart.setOption(option2) + + }, + + initTotalDamage: function() { + this.totalDamage = []; + let bossDamageList = {}; + let result = {normalDamage: [], continueDamage: [], tailDamage: [], count: 0, countContinue: 0, countTail: 0}; + for (let challenge of this.challenges) { + let dict = bossDamageList[challenge.boss_num]; + if (dict == undefined) { + dict = {normalDamage: [], continueDamage: [], tailDamage: [], count: 0, countContinue: 0, countTail: 0} + bossDamageList[challenge.boss_num] = dict; + } + let damage = challenge.damage; + if (challenge.health_ramain == 0) { + result.tailDamage.push(damage); + result.countTail++; + dict.tailDamage.push(damage); + dict.countTail++; + continue; + } + if (challenge.is_continue) { + result.continueDamage.push(damage); + result.countContinue++; + dict.continueDamage.push(damage); + dict.countContinue++; + continue; + } + result.normalDamage.push(damage); + result.count++; + dict.normalDamage.push(damage); + dict.count++; + } + result.bossDamageList = bossDamageList; + this.totalDamage = result; + }, + + initPlayerDamage: function () { + for (const elem of this.members) { + const playerQQid = elem.qqid; + let challenges = this.challengeMap[playerQQid]; + let bossDamageList = {}; + let result = {normalDamage: [], continueDamage: [], tailDamage: [], count: 0, countContinue: 0, countTail: 0}; + for (let day in challenges) { + for (let challenge of challenges[day]) { + let dict = bossDamageList[challenge.boss_num]; + if (dict == undefined) { + dict = {normalDamage: [], continueDamage: [], tailDamage: [], count: 0, countContinue: 0, countTail: 0} + bossDamageList[challenge.boss_num] = dict; + } + let damage = challenge.damage; + if (challenge.health_ramain == 0) { + result.tailDamage.push(damage); + result.countTail++; + dict.tailDamage.push(damage); + dict.countTail++; + continue; + } + if (challenge.is_continue) { + result.continueDamage.push(damage); + result.countContinue++; + dict.continueDamage.push(damage); + dict.countContinue++; + continue; + } + result.normalDamage.push(damage); + result.count++; + dict.normalDamage.push(damage); + dict.count++; + } + } + result.bossDamageList = bossDamageList; + this.playerDamages[playerQQid] = result; + } + }, + + initGlobalTableData: function () { + this.globalTableData = []; + for (const member of this.members) { + const sum = this.totalSumDamage(); + const pdmg = this.playerDamage(member.qqid); + const playerSum = this.playerSumDamage(member.qqid); + const tempAvgDmg = this.playerAverageDamage(member.qqid, this.containTailAndContinue); + const tempSumDmgRate = (100 * playerSum / sum); + let dict = { + qqid: member.qqid, + nickname: member.nickname, + count: pdmg.count + pdmg.countContinue / 2 + pdmg.countTail / 2, + countContinue: pdmg.countContinue, + countTail: pdmg.countTail, + avgDmg: isNaN(tempAvgDmg) ? 0 : tempAvgDmg, + sumDmg: playerSum, + sumDmgRate: isNaN(tempSumDmgRate) ? '--' : tempSumDmgRate.toFixed(2) + '%' + } + this.globalTableData.push(dict); + } + }, + + tsToDay: function (ts) { + // 减去5点 + let date = new Date((ts - 18000) * 1000); + return date.getFullYear() + '-' + this.formatTo2(date.getMonth() + 1) + '-' + this.formatTo2(date.getDate()); + }, + sortChallengeByTime: function(c1, c2) { + return c1.challenge_time - c2.challenge_time; + }, + sortAndDivide: function() { + for (let m of this.members) { + let detail = {}; + let challenges = m.challenges; + if (!challenges) { + continue; + } + for (let challenge of challenges) { + if (detail[this.tsToDay(challenge.challenge_time)] == undefined) { + detail[this.tsToDay(challenge.challenge_time)] = []; + } + detail[this.tsToDay(challenge.challenge_time)].push(challenge); + } + for (let key in detail) { + detail[key].sort(this.sortChallengeByTime); + } + m.challenges = detail; + this.challengeMap[m.qqid] = detail; + } + }, + + totalAverageDamage: function(containTailAndContinue = false) { + return this.averageDamage(this.totalDamage, containTailAndContinue); + }, + playerAverageDamage: function(playerQQid, containTailAndContinue = false) { + return this.averageDamage(this.playerDamage(playerQQid), containTailAndContinue); + }, + + bossAverageDamageForChart: function(bossDamageList, containTailAndContinue = false) { + let l1 = [], l2 = []; + for (let index in bossDamageList) { + let damage = bossDamageList[index]; + let ret = this.averageDamage(damage, containTailAndContinue); + if (!isNaN(ret)) { + l1.push(index + "号Boss"); + l2.push(ret); + } + } + return [l1, l2]; + }, + bossMissForChart: function(globalTableData) { + const counts = globalTableData.map(elem => elem.count); + const names = globalTableData.map(elem => elem.nickname); + return [names, counts]; + }, + bossLastForChart: function() { + const map = {}; + for (const i in this.challenges) { + if (this.challenges[i].is_continue) { + const name = this.getPlayer(this.challenges[i].qqid).nickname; + if (name in map) + map[name] += 1; + else + map[name] = 1; + } + } + return Object.keys(map).map(name => ({name: name, value: map[name]})); + }, + bossBloodForChart: function() { + const challs = this.challenges.sort((a, b) => a.challenge_time - b.challenge_time); + let bosses = []; + let nowBoss, lastPosition, lastCircle; + for (const i in challs) { + if (nowBoss === undefined) + nowBoss = challs[i].boss_num; + if (lastPosition === undefined) + lastPosition = challs[i].challenge_time * 1000; + if (lastCircle === undefined) + lastCircle = challs[i].cycle; + if (challs[i].boss_num !== nowBoss) { + const time = challs[i].challenge_time * 1000; + bosses.push({ + gte: lastPosition, + lt: time, + color: this.colorList[nowBoss - 1], + label: `${lastCircle}周目${nowBoss}王` + }); + nowBoss = challs[i].boss_num; + lastPosition = time; + lastCircle = challs[i].cycle; + } + } + if (nowBoss && lastPosition) { + bosses.push({ + gte: lastPosition, + color: this.colorList[nowBoss - 1], + label: `${lastCircle}周目${nowBoss}王` + }); + } + return [challs.map(c => [c.challenge_time * 1000, c.health_ramain]), bosses]; + }, + bossSumDamageForChart: function(bossDamageList) { + let l1 = [], l2 = []; + for (let index in bossDamageList) { + let damage = bossDamageList[index]; + let ret = this.sumDamage(damage); + if (!isNaN(ret)) { + l1.push(index + "号Boss"); + l2.push(ret); + } + } + return [l1, l2]; + }, + bossChallengeCountForChart: function(bossDamageList, containTailAndContinue = false) { + let l1 = [] + for (let index in bossDamageList) { + let damage = bossDamageList[index]; + let ret = damage.count + (containTailAndContinue ? (damage.countContinue + damage.countTail) / 2 : 0); + if (ret != 0) l1.push({name: index + "号Boss", value: ret}); + } + return l1; + }, + bossPlayerHitCountForChart: function() { + const names = [], counter = {}; + const hanzi = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"] + const maxBossNum = Math.max.apply(Math, [0, ...this.challenges.map(c => c.boss_num)]); + const bosses = [...Array(maxBossNum || 0).keys()].map(k => `${k in hanzi ? hanzi[k] : k}王`).reverse() + + this.challenges.forEach(c => { + const boss = c.boss_num; + const name = this.getPlayer(c.qqid).nickname; + if (!(boss in counter)) { + counter[boss] = {} + } + const bossCount = counter[boss]; + if (!(name in bossCount)) { + bossCount[name] = 0 + } + const isFull = c.health_ramain && !c.is_continue; + bossCount[name] += isFull ? 1 : 0.5; + }) + const result = []; + const getNicknameIndex = name => { + if (!names.includes(name)) + names.push(name) + return names.findIndex(n => n === name); + } + const getBossIndex = num => maxBossNum - parseInt(num); + Object.keys(counter).forEach(num => { + Object.keys(counter[num]).forEach(name => { + result.push([ + getBossIndex(num), + getNicknameIndex(name), + counter[num][name] + ]) + }) + }) + return [ + bosses, + names, + result.map(function (item) { + return [item[1], item[0], item[2] || '-']; + }) + ]; + }, + timeForChart: function(challenges) { + const time = {}; + [...Array(24).keys()].forEach(i => time[i] = 0); + for (const i in challenges) { + const t = new Date(challenges[i].challenge_time * 1000); + time[t.getHours()] += 1; + } + return Object.values(time); + }, + dayDamageForChart: function(challenges) { + const dates = {}; + challenges.forEach(c => { + const date = this.tsToDay(c.challenge_time); + if (date in dates) { + dates[date] += c.damage; + } else { + dates[date] = c.damage; + } + }); + return Object.entries(dates).sort( + (a, b) => + new Date(a[0]) - new Date(b[0]) + ); + }, + + membersDamageForChart: function(globalTableData) { + const data = globalTableData.sort((a, b) => b.sumDmg - a.sumDmg); + const full = data.map(elem => elem.sumDmg); + const average = data.map(elem => elem.avgDmg); + const names = data.map(elem => elem.nickname); + return [names, full, average]; + }, + + averageDamage: function(damage, containTailAndContinue) { + let sum = this.sum(damage.normalDamage); + let count = damage.count; + if (containTailAndContinue) { + sum += this.sum(damage.continueDamage) + this.sum(damage.tailDamage); + count += (damage.countContinue + damage.countTail) / 2; + } + return Math.floor(sum / count); + }, + + totalSumDamage: function() { + return this.sumDamage(this.totalDamage); + }, + playerSumDamage: function(playerQQid) { + return this.sumDamage(this.playerDamage(playerQQid)); + }, + sumDamage: function(damage) { + return this.sum(damage.normalDamage) + this.sum(damage.continueDamage) + this.sum(damage.tailDamage); + }, + + challengeCount: function(damage, containTailAndContinue) { + return damage.count + (containTailAndContinue ? (damage.countTail + damage.countContinue) / 2 : 0); + }, + + getPlayer: function(qqid) { + return this.members.find(o => o.qqid === qqid) || {nickname:'未加入',qqid:qqid,sl:null}; + }, + + playerDamage: function(playerQQid) { + return this.playerDamages[playerQQid]; + }, + getToday: function () { + let d = new Date(); + d -= 18000000; + d = new Date(d).setHours(0, 0, 0, 0); + return d; + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/clan/subscribers.js b/Origin/static/clan/subscribers.js new file mode 100644 index 0000000..1af060c --- /dev/null +++ b/Origin/static/clan/subscribers.js @@ -0,0 +1,86 @@ +var vm = new Vue({ + el: '#app', + data: { + bosstag: ['挂树', '预约1', '预约2', '预约3', '预约4', '预约5'], + subscribers: [ + [], [], [], [], [], [], + ], + members: [], + group_name: null, + activeIndex: '2', + }, + mounted() { + var thisvue = this; + axios.post('../api/', { + action: 'get_subscribers', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + for (sub of res.data.subscribers) { + thisvue.subscribers[sub.boss].push(sub); + } + thisvue.group_name = res.data.group_name; + document.title = res.data.group_name + ' - 公会战设置'; + } else { + thisvue.$alert(res.data.message, '获取数据失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '获取数据失败'); + }); + axios.post('../api/', { + action: 'get_member_list', + csrf_token: csrf_token, + }).then(function (res) { + if (res.data.code == 0) { + thisvue.members = res.data.members; + } else { + thisvue.$alert(res.data.message, '获取成员失败'); + } + }).catch(function (error) { + thisvue.$alert(error, '获取成员失败'); + }); + }, + methods: { + find_name: function (qqid) { + for (m of this.members) { + if (m.qqid == qqid) { + return m.nickname; + } + }; + return qqid; + }, + get_time_delta: function (time) { + var dateBegin = new Date(time); + var dateEnd = new Date(); + var dateDiff = dateEnd.getTime() - dateBegin.getTime(); + if (dateDiff >= 86400000) { + return '24小时+' + } + var leave1 = dateDiff % (24 * 3600 * 1000); + var hours = Math.floor(leave1 / (3600 * 1000)); + var leave2 = leave1 % (3600 * 1000); + var minutes = Math.floor(leave2 / (60 * 1000)); + return (hours + "小时" + minutes + "分钟"); + }, + handleSelect(key, keyPath) { + switch (key) { + case '1': + window.location = '../'; + break; + case '2': + window.location = '../subscribers/'; + break; + case '3': + window.location = '../progress/'; + break; + case '4': + window.location = '../statistics/'; + break; + case '5': + window.location = `../my/`; + break; + } + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/clan/user.js b/Origin/static/clan/user.js new file mode 100644 index 0000000..04b90c6 --- /dev/null +++ b/Origin/static/clan/user.js @@ -0,0 +1,136 @@ +var gs_offset = { jp: 4, tw: 5, kr: 4, cn: 5 }; +function pad2(num) { + return String(num).padStart(2, '0'); +} +function ts2ds(timestamp) { + var d = new Date(); + d.setTime(timestamp * 1000); + return d.getFullYear() + '/' + pad2(d.getMonth() + 1) + '/' + pad2(d.getDate()); +} +var vm = new Vue({ + el: '#app', + data: { + isLoading: true, + challengeData: [], + activeIndex: '5', + qqid: 0, + nickname: '', + }, + mounted() { + var thisvue = this; + var pathname = window.location.pathname.split('/'); + thisvue.qqid = parseInt(pathname[pathname.length - 2]); + axios.post('../api/', { + action: 'get_user_challenge', + csrf_token: csrf_token, + qqid: thisvue.qqid, + }).then(function (res) { + if (res.data.code != 0) { + thisvue.$alert(res.data.message, '获取记录失败'); + return; + } + thisvue.nickname = res.data.user_info.nickname; + thisvue.refresh(res.data.challenges, res.data.game_server); + thisvue.isLoading = false; + }).catch(function (error) { + thisvue.$alert(error, '获取数据失败'); + }); + }, + methods: { + csummary: function (cha) { + if (cha == undefined) { + return ''; + } + return `(${cha.cycle}-${cha.boss_num}) ${cha.damage}`; + }, + cdetail: function (cha) { + if (cha == undefined) { + return ''; + } + var nd = new Date(); + nd.setTime(cha.challenge_time * 1000); + var detailstr = nd.toLocaleString('chinese', { hour12: false, timeZone: 'asia/shanghai' }) + '\n'; + detailstr += cha.cycle + '周目' + cha.boss_num + '号boss\n'; + detailstr += (cha.health_ramain + cha.damage).toLocaleString(options = { timeZone: 'asia/shanghai' }) + '→' + cha.health_ramain.toLocaleString(options = { timeZone: 'asia/shanghai' }); + if (cha.message) { + detailstr += '\n留言:' + cha.message; + } + return detailstr; + }, + arraySpanMethod: function ({ row, column, rowIndex, columnIndex }) { + if (columnIndex >= 2) { + if (columnIndex % 2 == 0) { + var detail = row.detail[columnIndex - 2]; + if (detail != undefined && detail.health_ramain != 0) { + return [1, 2]; + } + } else { + var detail = row.detail[columnIndex - 3]; + if (detail != undefined && detail.health_ramain != 0) { + return [0, 0]; + } + } + } + }, + refresh: function (challenges, game_server) { + var thisvue = this; + var m = { pcrdate: -1 }; + for (c of challenges) { + var pcrdate = ts2ds(c.challenge_time - (gs_offset[game_server] * 3600)); + if (m.pcrdate != pcrdate) { + if (m.pcrdate != -1) { + thisvue.challengeData.push(m); + } + m = { + pcrdate: pcrdate, + finished: 0, + detail: [], + } + } + m.detail[2 * m.finished] = c; + if (c.is_continue) { + m.finished += 0.5; + } else { + if (c.health_ramain != 0) { + m.finished += 1; + } else { + m.finished += 0.5; + } + } + } + if (m.pcrdate != -1) { + thisvue.challengeData.push(m); + } + }, + viewInExcel: function () { + var icons = document.getElementsByTagName('span'); + while (icons[0]) { + icons[0].remove(); + } + var uri = 'data:application/vnd.ms-excel;base64,'; + var ctx = '' + document.getElementsByTagName('thead')[0].innerHTML + document.getElementsByTagName('tbody')[0].innerHTML + '
'; + window.location.href = uri + window.btoa(unescape(encodeURIComponent(ctx))); + document.documentElement.innerHTML = '请在Excel中查看(如果无法打开,请安装最新版本Excel)\n或者将整个表格复制,粘贴到Excel中使用'; + }, + handleTitleSelect(key, keyPath) { + switch (key) { + case '1': + window.location = '../'; + break; + case '2': + window.location = '../subscribers/'; + break; + case '3': + window.location = '../progress/'; + break; + case '4': + window.location = '../statistics/'; + break; + case '5': + window.location = `../my/`; + break; + } + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/gacha.js b/Origin/static/gacha.js new file mode 100644 index 0000000..b6e8d65 --- /dev/null +++ b/Origin/static/gacha.js @@ -0,0 +1,64 @@ +var pool = [ + [1071, 1061, 1070, 1804, 1012, 1043, 1057, 1028, 1029, 1011, 1030, 1018, 1032, 1053, 1049, 1009, 1047, 1010, 1063, 1036, 1044, 1037, 1056, 1014, 1092, 1094, 1095, 1096, 1107, 1108, 1113, 1114, 1065, 1117, 1122, 1109, 1110, 1075, 1077, 1078, 1079, 1081, 1083, 1084, 1086, 1087, 1088, 1091, 1097, 1099, 1100, 1103, 1104, 1106, 1111, 1115, 1119, 1120, 1124, 1125, 1127, 1128], + [1045, 1048, 1008, 1006, 1046, 1020, 1033, 1031, 1017, 1042, 1051, 1027, 1007, 1038, 1016, 1026, 1023, 1015, 1054, 1005, 1013], + [1003, 1034, 1040, 1022, 1004, 1052, 1025, 1050, 1001, 1021, 1055], +]; +var experience = { + "star3": 0, + "star2": 0, + "star1": 0, + "diamond": 0, +}; +var progress = false; +(function () { + var h = localStorage['gacha_experience']; + if (h) { + [experience.star3, experience.star2, experience.star1, experience.diamond] = h.split(',').map(x => +x); + } +})(); +function randarr(arr) { + return String(arr[Math.floor(Math.random() * arr.length)]); +} +function pick(i) { + var x = Math.random(); + if (x < 0.025) { + experience.star3 += 1; + return randarr(pool[0]) + '31'; + } else if (x < 0.205) { + experience.star2 += 1; + return randarr(pool[1]) + '11'; + } else if (i == 9) { + experience.star2 += 1; + return randarr(pool[1]) + '11'; + } + experience.star1 += 1; + return randarr(pool[2]) + '11'; +} +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} +async function reload() { + var container = document.getElementById('container'); + container.innerHTML = ''; + for (i of Array(10).keys()) { + await sleep(200); + let chara = String(pick(i)); + let result = document.createElement('img'); + result.src = sourcebase + chara + '.jpg'; + container.appendChild(result); + if (i === 4) { + container.appendChild(document.createElement('br')); + } + } + experience.diamond += 1500; +} +async function gacha() { + if (progress) { + return; + } + progress = true; + await reload(); + document.getElementById('result').innerHTML = `★3: ${experience.star3}
★2: ${experience.star2}
★1: ${experience.star1}
总耗钻: ${experience.diamond}`; + localStorage['gacha_experience'] = [experience.star3, experience.star2, experience.star1, experience.diamond].join(','); + progress = false; +} \ No newline at end of file diff --git a/Origin/static/gongan.png b/Origin/static/gongan.png new file mode 100644 index 0000000000000000000000000000000000000000..a341341631d632156cada5fee7bfc2004cac389c GIT binary patch literal 3830 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 literal 0 HcmV?d00001 diff --git a/Origin/static/marionette.js b/Origin/static/marionette.js new file mode 100644 index 0000000..2fbfa85 --- /dev/null +++ b/Origin/static/marionette.js @@ -0,0 +1,48 @@ +var vm = new Vue({ + el: '#sending', + data: { + message_type: 'group', + user_id: 0, + group_id: 0, + message: '', + }, + mounted() { + if (localStorage.message_type) { + this.message_type = localStorage.message_type; + this.user_id = localStorage.user_id; + this.group_id = localStorage.group_id; + this.message = localStorage.message; + } + }, + watch: { + message_type: function (newmessage_type) { + localStorage.message_type = newmessage_type; + }, + user_id: function (newuser_id) { + localStorage.user_id = newuser_id; + }, + group_id: function (newgroup_id) { + localStorage.group_id = newgroup_id; + }, + message: function (newmessage) { + localStorage.message = newmessage; + }, + }, + methods: { + send_msg: function (event) { + axios.post( + api_path, + this.$data, + ).then(function (res) { + if (res.data.code == 0) { + alert('已发送'); + } else { + alert('发送失败:' + res.data.message); + } + }).catch(function (error) { + alert(error); + }); + }, + }, + delimiters: ['[[', ']]'], +}) \ No newline at end of file diff --git a/Origin/static/password.js b/Origin/static/password.js new file mode 100644 index 0000000..96f13a3 --- /dev/null +++ b/Origin/static/password.js @@ -0,0 +1,344 @@ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://anmar.eu.org/projects/jssha2/ + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); } +function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); } +function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); } +function hex_hmac_sha256(k, d) + { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } +function b64_hmac_sha256(k, d) + { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } +function any_hmac_sha256(k, d, e) + { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha256_vm_test() +{ + return hex_sha256("abc").toLowerCase() == + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; +} + +/* + * Calculate the sha256 of a raw string + */ +function rstr_sha256(s) +{ + return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8)); +} + +/* + * Calculate the HMAC-sha256 of a key and some data (raw strings) + */ +function rstr_hmac_sha256(key, data) +{ + var bkey = rstr2binb(key); + if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256)); +} + +/* + * Convert a raw string to a hex string + */ +function rstr2hex(input) +{ + try { hexcase } catch(e) { hexcase=0; } + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var output = ""; + var x; + for(var i = 0; i < input.length; i++) + { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt( x & 0x0F); + } + return output; +} + +/* + * Convert a raw string to a base-64 string + */ +function rstr2b64(input) +{ + try { b64pad } catch(e) { b64pad=''; } + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var output = ""; + var len = input.length; + for(var i = 0; i < len; i += 3) + { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i+2) : 0); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > input.length * 8) output += b64pad; + else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); + } + } + return output; +} + +/* + * Convert a raw string to an arbitrary string encoding + */ +function rstr2any(input, encoding) +{ + var divisor = encoding.length; + var remainders = Array(); + var i, q, x, quotient; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + var dividend = Array(Math.ceil(input.length / 2)); + for(i = 0; i < dividend.length; i++) + { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /* + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zero. + * All remainders are stored for later use. + */ + while(dividend.length > 0) + { + quotient = Array(); + x = 0; + for(i = 0; i < dividend.length; i++) + { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if(quotient.length > 0 || q > 0) + quotient[quotient.length] = q; + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + var output = ""; + for(i = remainders.length - 1; i >= 0; i--) + output += encoding.charAt(remainders[i]); + + /* Append leading zero equivalents */ + var full_length = Math.ceil(input.length * 8 / + (Math.log(encoding.length) / Math.log(2))) + for(i = output.length; i < full_length; i++) + output = encoding[0] + output; + + return output; +} + +/* + * Encode a string as utf-8. + * For efficiency, this assumes the input is valid utf-16. + */ +function str2rstr_utf8(input) +{ + var output = ""; + var i = -1; + var x, y; + + while(++i < input.length) + { + /* Decode utf-16 surrogate pairs */ + x = input.charCodeAt(i); + y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; + if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) + { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i++; + } + + /* Encode output as utf-8 */ + if(x <= 0x7F) + output += String.fromCharCode(x); + else if(x <= 0x7FF) + output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), + 0x80 | ( x & 0x3F)); + else if(x <= 0xFFFF) + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + else if(x <= 0x1FFFFF) + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + } + return output; +} + +/* + * Encode a string as utf-16 + */ +function str2rstr_utf16le(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode( input.charCodeAt(i) & 0xFF, + (input.charCodeAt(i) >>> 8) & 0xFF); + return output; +} + +function str2rstr_utf16be(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, + input.charCodeAt(i) & 0xFF); + return output; +} + +/* + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ +function rstr2binb(input) +{ + var output = Array(input.length >> 2); + for(var i = 0; i < output.length; i++) + output[i] = 0; + for(var i = 0; i < input.length * 8; i += 8) + output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + return output; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2rstr(input) +{ + var output = ""; + for(var i = 0; i < input.length * 32; i += 8) + output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); + return output; +} + +/* + * Main sha256 function, with its support functions + */ +function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));} +function sha256_R (X, n) {return ( X >>> n );} +function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));} +function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));} +function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));} +function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));} +function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));} +function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));} +function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));} +function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));} +function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));} +function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));} + +var sha256_K = new Array +( + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, + -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, + 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, + 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, + -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, + 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, + 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, + -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, + 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, + 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, + -1866530822, -1538233109, -1090935817, -965641998 +); + +function binb_sha256(m, l) +{ + var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534, + 1359893119, -1694144372, 528734635, 1541459225); + var W = new Array(64); + var a, b, c, d, e, f, g, h; + var i, j, T1, T2; + + /* append padding */ + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + + for(i = 0; i < m.length; i += 16) + { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for(j = 0; j < 64; j++) + { + if (j < 16) W[j] = m[j + i]; + else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), + sha256_Gamma0256(W[j - 15])), W[j - 16]); + + T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), + sha256_K[j]), W[j]); + T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; +} + +function safe_add (x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + + +let salt = "14b492a3-a40a-42fc-a236-e9a9307b47d2"; + +var getHashWithSalt = function (pwd) { + return hex_sha256(pwd + salt) +}; diff --git a/Origin/static/small.ico b/Origin/static/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..8b894f041192b78a4669066823de8788793291f9 GIT binary patch literal 16958 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 { + animation: move-forever 25s cubic-bezier(.55, .5, .45, .5) infinite; + } + + .parallax>use:nth-child(1) { + animation-delay: -2s; + animation-duration: 7s; + } + + .parallax>use:nth-child(2) { + animation-delay: -3s; + animation-duration: 10s; + } + + .parallax>use:nth-child(3) { + animation-delay: -4s; + animation-duration: 13s; + } + + .parallax>use:nth-child(4) { + animation-delay: -5s; + animation-duration: 20s; + } + + @keyframes move-forever { + 0% { + transform: translate3d(-90px, 0, 0); + } + + 100% { + transform: translate3d(85px, 0, 0); + } + } + + /*Shrinking for mobile*/ + @media (max-width: 768px) { + .waves { + height: 40px; + min-height: 40px; + } + + .content { + height: 30vh; + } + + h1 { + font-size: 24px; + } + } + +#bottomToolbar { + width: 100%; + height: 22px; + line-height: 22px; + background: #409EFF; + position: fixed; + bottom: 0; + left: 0; + _position: absolute; + _top: expression(documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight); + z-index: 999; + font-size: 13px; + color: #FFF; +} + +#bottomToolbar a { + color: #FFF; +} + +.el-icon-star-on { + font-size: 20px; +} + +.finishedRow td span { + color: #909399 !important; +} + +.finishedRow, +.finishedRow td { + background-color: #F5F7FA !important; + color: #909399; +} + +.finishedRow .el-table__expand-icon>.el-icon { + background-color: #F5F7FA !important; + color: #909399; +} + +.finishedRow .el-table th { + background-color: #F5F7FA; +} + +.el-table--enable-row-hover .el-table__body tr:hover>td { + background-color: #EBEEF5; +} + +.el-table .cell { + padding-right: 0px; +} + +.el-table td { + border-bottom: none; + border-right: none; +} + +.el-table th.is-leaf { + border-bottom: none; +} + +.el-table thead { + font-weight: 500; +} + +.el-table .sort-caret.ascending { + top: 5px; +} + +.el-table .sort-caret.descending { + bottom: 7px; +} + +.el-table__expand-icon { + position: relative; + cursor: pointer; + -webkit-transition: -webkit-transform .2s ease-in-out; + transition: -webkit-transform .2s ease-in-out; + transition: transform .2s ease-in-out; + transition: transform .2s ease-in-out, -webkit-transform .2s ease-in-out; + height: 20px; +} + +.el-table--border, +.el-table--group { + border: none; +} + +.el-table::before { + content: ''; + position: absolute; + background-color: transparent; + z-index: 1; +} + +.el-table--border::after, +.el-table--group::after, +.el-table::before { + content: ''; + position: absolute; + background-color: transparent; + z-index: 1; +} + +.el-table__header { + table-layout: auto; + border-collapse: separate; +} + +.el-table .cell { + -webkit-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + word-break: break-all; + line-height: 23px; +} + +.el-table .cell, .el-table--border td:first-child .cell, .el-table--border th:first-child .cell { + padding-left: 0px; +} + +.el-table__body, .el-table__footer, .el-table__header { + table-layout: auto; + border-collapse: separate; +} + +.el-table th>.cell { + padding-left: 0px; + padding-right: 0px; +} \ No newline at end of file diff --git a/Origin/static/yocool/js/yocool.1622013138001.js b/Origin/static/yocool/js/yocool.1622013138001.js new file mode 100644 index 0000000..fe6e237 --- /dev/null +++ b/Origin/static/yocool/js/yocool.1622013138001.js @@ -0,0 +1 @@ +document.writeln("
Powered by Yobot | Themes by YoCool
"); \ No newline at end of file diff --git a/Origin/template/404.html b/Origin/template/404.html new file mode 100644 index 0000000..7a15762 --- /dev/null +++ b/Origin/template/404.html @@ -0,0 +1,14 @@ + + + + + 404 + + + +

404: not found

+

这个{{ item }}不存在

+

返回

+ + + \ No newline at end of file diff --git a/Origin/template/about.html b/Origin/template/about.html new file mode 100644 index 0000000..bc94d4a --- /dev/null +++ b/Origin/template/about.html @@ -0,0 +1,76 @@ + + + + 关于 + + + + +

+ 返回 +

+
+

+ 关于yobot +

+

+ 版本:
+ {{ verinfo | replace("\n", "
") }} +

+

+ 主页:
+ https://yobot.win/ +

+

+ 源码:
+ yobot +

+

+ 联系邮箱:
+ yobot@pcrbot.com +

+

+ 交流群:
1群:770947581
2群:1044314369
4群:1067699252
5群:774394459 +

+

+ 其他 +

+

+ 本项目没有开启赞助、打赏的渠道,所有付款行为与本项目无关。
+ 如果你付费获取了本工具,可能是第三方收取的服务器费用和托管费用。 +

+
+
+

+ 关于YoCool +

+

+ :版本
+ YoCool-v1.1.8-Origin +

+

+ :源码
+ YoCool +

+

+ :交流群
1143518690 +

+

+ :更新日志
点我查看 +

+

+ :了解更多
YoCool WIKI +

+

+ 赞助名单(排名不分先后) +

+

+ @var-mixer +

+

+ YoCool静态资源加速由PcrLink提供 +

+ +
+ diff --git a/Origin/template/admin/groups.html b/Origin/template/admin/groups.html new file mode 100644 index 0000000..3f1fb2e --- /dev/null +++ b/Origin/template/admin/groups.html @@ -0,0 +1,38 @@ + + + + yobot公会管理 + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/Origin/template/admin/pool-setting.html b/Origin/template/admin/pool-setting.html new file mode 100644 index 0000000..7c0304c --- /dev/null +++ b/Origin/template/admin/pool-setting.html @@ -0,0 +1,43 @@ + + + + + 自定义奖池 + + + + + + +

返回

+

所有概率都是相对值,即:抽取率 = 当前奖池概率 ÷ 所有奖池总概率

+
+
+

奖池:[[pname]]

+
+ 名称:
+ 前缀:
+ 单抽概率:
+ 保底抽概率:
+ 内容:
+ + +
+

+ +


+
+ 每次抽卡数:
+ 每日抽卡次数:
+ 保底抽位置不固定 +
+ +
+ + + + + \ No newline at end of file diff --git a/Origin/template/admin/setting.html b/Origin/template/admin/setting.html new file mode 100644 index 0000000..6fa420f --- /dev/null +++ b/Origin/template/admin/setting.html @@ -0,0 +1,254 @@ + + + + yobot设置 + + + + + + + + + +

yobot设置

+
+ + + + + + + 填入当前地址 + + + + + + + + + + + + + + + + + + + + + 开启 gzip 压缩能很大程度节省流量
+ 1级压缩大约节省 70%,9级压缩大约节省 80%
+ 如果你的反向代理软件(nginx 等)开启了 gzip_proxy,那么应该将此处设置为 0
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 添加 + + 删除 + + + + + + 添加 + + 删除 + + + + + + + + + + + 添加 + + 删除 + + + + + + 添加 + + 删除 + + + 仅主人 + 群主以上 + 管理员以上 + 所有人 + + + + + + + + + + + + + 使用(聊天+网站) + + 关闭 + + + 允许群聊抽卡 + 允许私聊抽卡 + + + + + + + + + + + + + + 日服官网 + 日服推特 + 台服官网 + 国服官网 + 国服Bilibili动态 + + + + + + + + + + + + + + 添加 + + 删除 + + + + + + 添加 + + 删除 + + + + + + + + + + + + + +
+

+ + +

+
+

[[ {jp: "日服", tw: "台服", cn: "国服"}[area] ]]

+ + + + + + + + + + + +
起始周目数[[k]]号boss
[[i+1]]阶段 + + + +
+ + +
+
备注:
当前日服公会战阶段情况如下:
1阶段:1~3周目
2阶段:4~10周目
3阶段:11~34周目
4阶段:35~44周目
5阶段:45以上
+
+ + +

+

+ 前往卡池设置 +

+

+ 确定 +

+
+ + + + + \ No newline at end of file diff --git a/Origin/template/admin/users.html b/Origin/template/admin/users.html new file mode 100644 index 0000000..150a2d0 --- /dev/null +++ b/Origin/template/admin/users.html @@ -0,0 +1,79 @@ + + + + yobot用户管理 + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + 搜索 + + + + + + + + + + + + + + + + + + + + + 加载更多 + 已加载全部 + +
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/panel.html b/Origin/template/clan/panel.html new file mode 100644 index 0000000..f1c9030 --- /dev/null +++ b/Origin/template/clan/panel.html @@ -0,0 +1,221 @@ + + + + 公会战 + + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + + + Boss状态 + + + [[ bossData.cycle ]]周目 + [[ bossData.num ]]号boss + + + [[ bossData.health.toLocaleString() ]]/[[ bossData.full_health.toLocaleString() ]] + + + + + + {% if is_member -%} + + 上报伤害 + + + + + + + + + + + + + + 上报尾刀 + + + + + + + + + 代理上报 + + + + + + + + + + + + + + + + + + + + + + + + + 撤销上报 + + + 申请出刀 + [[ (bossData.challenger)&&(bossData.challenger!=self_id)?'强制解锁':'解锁' ]] + 锁定boss + + + + + + + + + [[ today_sl?'取消SL':'SL']] + + + 挂树 + + + + + + + + + 取消挂树 + 预约boss + + + + + + + + + + + + 取消预约 + + + + + + + + + + + + + 修改状态 + 设置 + + + + + + + + + + + + + + + + + {% else -%} +

非公会战成员只允许查看

+ {% endif -%} +
+ +
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/progress.html b/Origin/template/clan/progress.html new file mode 100644 index 0000000..cc5bfd0 --- /dev/null +++ b/Origin/template/clan/progress.html @@ -0,0 +1,339 @@ + + + + 出刀记录 + + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + +

出刀记录

+ + 选中未完成 + 提醒出刀 + +

您确定要向[[ multipleSelection.length ]]名成员发送提醒吗

+ + + + + + + + + 取消 + 确定 + +
+ +
+
+ 删除公会成员 + 在Excel中查看 + +

您确定要删除这[[ multipleSelection.length ]]名成员吗

+ + 取消 + + 确定 + + +
+ +
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/setting.html b/Origin/template/clan/setting.html new file mode 100644 index 0000000..80a11c4 --- /dev/null +++ b/Origin/template/clan/setting.html @@ -0,0 +1,91 @@ + + + + 公会战设置 + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + +

设置

+ + + + + + + + + + + 出刀表无需登录 + 允许api获取数据 + + + 伤害上报 + 撤销上报 + 申请出刀 + 取消申请 + 预约boss + 取消预约 + 挂树 + 取消挂树 + 修改状态 + 使用SL + + + 确定 + 返回 + + + 现在档案编号:[[ battle_id ]]
+ 导出数据 + {#- 新建档案 -#} + 切换档案 + + +
    +
  • + [[ item.battle_id ]]号存档:[[ item.record_count ]]条记录 +
  • +
+ + + + + + + 取消 + 切换 + +
+ 删除数据 + +

此操作会删除 [[ battle_id ]] 号存档中所有数据

+ + 取消 + 确定 + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/statistics.html b/Origin/template/clan/statistics.html new file mode 100644 index 0000000..5934884 --- /dev/null +++ b/Origin/template/clan/statistics.html @@ -0,0 +1,126 @@ + + + + 公会战 - 数据分析 + + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + +

选择查看方式


+ +

出刀顺序
+

数据图表
+ +

均值偏差
+
+ +

多维分析
+
+
+

原始数据

+ + + + +


+
+ {% if allow_api -%} + + + {% else -%} + api访问已禁用,如需开启请前往 + 公会设置 + + {% endif -%} +
+
+ +

+ +

+ + + + + + + diff --git a/Origin/template/clan/statistics/statistics1.html b/Origin/template/clan/statistics/statistics1.html new file mode 100644 index 0000000..51901c5 --- /dev/null +++ b/Origin/template/clan/statistics/statistics1.html @@ -0,0 +1,94 @@ + + + + 总统计 + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/statistics/statistics2.html b/Origin/template/clan/statistics/statistics2.html new file mode 100644 index 0000000..a80da18 --- /dev/null +++ b/Origin/template/clan/statistics/statistics2.html @@ -0,0 +1,177 @@ + + + + 公会战 - 数据分析 + + + + + + + + + +
+ +

数据分析

+ + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/Origin/template/clan/subscribers.html b/Origin/template/clan/subscribers.html new file mode 100644 index 0000000..238f046 --- /dev/null +++ b/Origin/template/clan/subscribers.html @@ -0,0 +1,54 @@ + + + + 公会战预约 + + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + +

预约名单

+ + + + [[ bosstag[bn-1] ]] + +

+ [[ find_name(m.qqid) ]]([[ m.qqid ]]) + + +

+

+ 没有记录 +

+
+
+
+ + + + + \ No newline at end of file diff --git a/Origin/template/clan/unauthorized.html b/Origin/template/clan/unauthorized.html new file mode 100644 index 0000000..7684a88 --- /dev/null +++ b/Origin/template/clan/unauthorized.html @@ -0,0 +1,14 @@ + + + + + 权限不足 + + + +

权限不足

+

这个公会的信息是私密的,只有其成员可以查看

+

返回

+ + + \ No newline at end of file diff --git a/Origin/template/clan/user.html b/Origin/template/clan/user.html new file mode 100644 index 0000000..37e151c --- /dev/null +++ b/Origin/template/clan/user.html @@ -0,0 +1,98 @@ + + + + 出刀记录 + + + + + + + + + + + +
+ + + 面板 + 预约 + 查刀 + 统计 + 我的 + +

[[ nickname ]]的出刀记录

+ + +
+ 在Excel中查看 + 查看用户:[[ nickname ]]
+
+ + + + + \ No newline at end of file diff --git a/Origin/template/help.html b/Origin/template/help.html new file mode 100644 index 0000000..9dddc2f --- /dev/null +++ b/Origin/template/help.html @@ -0,0 +1,239 @@ + + + + 功能表 + + + + + + + +

功能列表

+

此页指令不需要at机器人

+

(权)标记表示功能需要权限

+

(自动)标记表示无需触发词,机器人主动推送

+

方括号表示参数可以省略

+

系统类

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
关键词说明
登录登录进入Web模式
重置密码随机生成一个新密码(不发链接)
更新(权)更新机器人
重启(权)重新启动机器人
退出此群(权:管理员)命令机器人退出当前群聊1
version查看机器人版本
帮助查看帮助
+

+ 1当管理员希望机器人离开群聊时,应该使用此条命令而不是直接踢出群聊,避免增加封号风险 +

+

公会战类

+

注:本类功能仅限群聊

+

公会战功能使用方法请查看手册

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
关键词说明
手册查看公会战使用手册
面板进入公会战面板
创建日服公会日/韩/台/国,创建后可在后台修改
加入公会 [@某人]加入到公会名单,如果有at则为加入他人
加入全部成员
报刀2000000 [@某人] [昨日] [:留言] + 对boss造成伤害但未击败时用,记录伤害,可以使用 200w/200万/2000k 等(一般公会精确到万即可)
+ 如果有at则为代报,有冒号则为留言
+ 如果有“昨日”则将记录添加到前一天1 +
尾刀 [@某人] [昨日] [:留言] + 对boss造成伤害并击败时用,记录伤害
+ 如果有at则为代报,有冒号则为留言
+ 如果有“昨日”则将记录添加到前一天1 +
进度查询今日出刀进度
SL [@某人] [?]挑战boss强制取消后用,记录本日SL2,用“?”查询今日是否已 SL,如果有at则为代报/代查
撤销撤销上一次报刀(非管理员只能撤销自己的记录)
状态显示boss状态
预约1 [:留言]预约boss,当boss出现时通知,有冒号则为留言
挂树 [:留言]挂树,当boss被击败时通知
查1 / 查树查询预约boss的成员,查询挂树的成员
预约表查询所有预约boss的成员
取消预约1 / 取消1取消预约
申请出刀锁定boss,提醒后面申请出刀的人有人正在挑战boss
锁定:留言锁定boss,提醒后面申请出刀的人,冒号后为留言
解锁解锁boss,其他人可以继续申请3
+

+ 1此功能是在日期变更后,将出刀记录添加到前一天。例如日服中03:59完成出刀,在04:01时向机器人报刀则需要加上[昨日]
+ 2在公会战面板的“查刀”页中,可以查看所有人今日是否已使用SL
+ 3此功能既可以用于主动结束锁定,也可以用户强制取消他人的解锁。本人或管理员可以随意解锁,3分钟后“出刀”可以被任何人解锁,“锁定”没有时间限制 +

+

查询类

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
关键词说明
jjc查询 +5个角色名空格分隔查找jjc解法,指定区服可改用“jjc国服/jjc台服/jjc日服”
(自动:新闻推送)推送最新的新闻
[日服/台服/国服]日程(今日/明日/x月x日)(可自动)查看活动日程
日程表查看一周日程
挖矿计算 +当前名次计算剩余可获得的奖励钻石
+

娱乐类

+ + + + + + + + + + + + + + + + + + + + + + + + + +
关键词说明
十连
仓库[@某人[@某人[…]]]查看抽到过的所有角色查看他人抽到过的角色
在线十连在线抽卡,不扰民
人偶(权:主人)人偶功能
+ + + \ No newline at end of file diff --git a/Origin/template/homepage.html b/Origin/template/homepage.html new file mode 100644 index 0000000..4f5291f --- /dev/null +++ b/Origin/template/homepage.html @@ -0,0 +1,86 @@ + + + + + YoCool Link Start + + + + + + + + + + +
+
+

Hi!YoCool!

+
+ + + + + + + + + + + +

+

—yobot is running—

+ + + {% if show_icp -%} + {{ icp_info }} +   + {% if gongan_info -%} + + + {{ gongan_info }} + +   + {% endif -%} + {% endif -%} + + + + + diff --git a/Origin/template/login-code.html b/Origin/template/login-code.html new file mode 100644 index 0000000..97cea8f --- /dev/null +++ b/Origin/template/login-code.html @@ -0,0 +1,18 @@ + + + + yobot登录 + + + +

正在登录中……

+ + + \ No newline at end of file diff --git a/Origin/template/login.html b/Origin/template/login.html new file mode 100644 index 0000000..53e30f1 --- /dev/null +++ b/Origin/template/login.html @@ -0,0 +1,140 @@ + + + + + + 会战系统登录 + + + + + + + + + + +
+
+

会战系统登录

+
+ + + + + + + + + + + +
+
+
+ {% if reason -%} + + + {% endif -%} +
+ + + + + + + + + + 登录 + + +
+
+ + + + \ No newline at end of file diff --git a/Origin/template/manual.html b/Origin/template/manual.html new file mode 100644 index 0000000..7668756 --- /dev/null +++ b/Origin/template/manual.html @@ -0,0 +1,81 @@ + + + + 使用手册 + + + + + + + +

公会战功能使用手册

+ +

使用 Bot 管理公会战,需要所有成员遵守使用规则
Bot 只是辅助作用,与成员多沟通才能提高分数

+ +

具体指令请以查看帮助页面

+ +

开始前

+ +
    +
  1. 机器人管理员进入后台设置,确认设置中的 boss 生命值符合当期公会战
  2. +
  3. 在群聊中发送创建日服公会(日、韩、台、国)
  4. +
  5. 所有公会战成员在群聊中发送加入公会,或者由群管理员发送加入全部成员
  6. +
  7. 成员向 bot 私聊发送登录重置密码,进入后台确认,同时修改登录密码
  8. +
  9. 成员进入公会战面板,并将网页地址保存到桌面快捷方式(手机、电脑均可),以便使用网页报刀和查看数据
  10. +
  11. 管理员在公会设置中,新建一个空白档案用来存放公会战数据
  12. +
+ +

进行中:成员

+ +
    +
  • 成员准备挑战 boss 时,需要在群聊中发送申请出刀,当 bot 允许后开始挑战 boss
  • +
  • 如果挑战 boss 完毕,需要向 bot 上报挑战结果
  • +
  • 如果挑战 boss 不成功,需要向 bot 上报挂树情况或 SL 使用情况
  • +
  • 如果意外掉刀,需要上报一次 0 点伤害的挑战
  • +
  • 成员可以使用预约功能,在 boss 出现时获得 bot 的 at 提醒
  • +
  • (可选择执行)如果希望进行合刀筛刀等多人出刀的操作,可以在群聊中发送锁定:留言,然后等待其他成员共同挑战 boss。等到所有挑战完毕后,按结算顺序向 bot 依次上报
  • +
  • (可选择执行)上报伤害和预约 boss 时,通过留言功能帮助排刀人员制定计划
  • +
+ +

进行中:管理员

+ +
    +
  • 在“查刀”页面中,管理员可以选中当日未完成出刀的成员,一键发送提醒
  • +
  • 在“查刀”页面中,排刀人员可以一览所有成员的 SL 使用情况
  • +
  • 在“查刀”页面中,排刀人员可以一览所有成员未完成的尾刀
  • +
+ +

特殊情况

+ +
    +
  • 如果有人挑战了 boss 却没有上报,可以由他人代理上报
  • +
  • 如果前一个上报数据出错,可以由上报者或管理员发送撤销来撤销
  • +
  • 如果有人申请了挑战,但没有报伤害也没有报挂树或 SL,其他成员可以在 3 分钟后在群聊中发送解锁来强制解锁
  • +
  • 如果出刀时间在日期变更附近导致未及时上报,需要将伤害上报到前一天的记录中
  • +
+ +

查看数据

+ +

公会战面板“查刀”页面中能查看记录的所有数据,并进行快速的筛选、过滤。如果需要原始数据,可以从“统计”页面导出。

+ + + \ No newline at end of file diff --git a/Origin/template/marionette.html b/Origin/template/marionette.html new file mode 100644 index 0000000..c4fa672 --- /dev/null +++ b/Origin/template/marionette.html @@ -0,0 +1,31 @@ + + + + + yobot + + + + + +
+

Marionette

+ 发送类型: + +
+ QQ号: +
+
+ 群号: +
+ 消息: + +
+ + + + + \ No newline at end of file diff --git a/Origin/template/password.html b/Origin/template/password.html new file mode 100644 index 0000000..7554518 --- /dev/null +++ b/Origin/template/password.html @@ -0,0 +1,157 @@ + + + + + 修改密码 + + + + + + + + + + +
+ +
+ {% if error -%} + + + {% endif -%} + {% if success -%} + + + {% endif -%} + + +
+

修改密码

+ + + + + + + + + 修改 + + +
+
+ + + + diff --git a/Origin/template/unauthorized.html b/Origin/template/unauthorized.html new file mode 100644 index 0000000..03b37ca --- /dev/null +++ b/Origin/template/unauthorized.html @@ -0,0 +1,16 @@ + + + + + 权限不足 + + + +

权限不足

+

浏览这个页面需要权限:{{ limit }}

+

你的权限:{{ uath }}

+

+ 返回 + + + \ No newline at end of file diff --git a/Origin/template/user-info.html b/Origin/template/user-info.html new file mode 100644 index 0000000..6e972cd --- /dev/null +++ b/Origin/template/user-info.html @@ -0,0 +1,155 @@ + + + + + 用户信息 + + + + + + + + + +
+ + + +
+ + + + \ No newline at end of file diff --git a/Origin/template/user.html b/Origin/template/user.html new file mode 100644 index 0000000..e385e73 --- /dev/null +++ b/Origin/template/user.html @@ -0,0 +1,140 @@ + + + + + 公主连结公会战面板 + + + + + + + + + + +
+ +
+

会战管理面板

+
+ + + + + + + + + + + +

+
+ +

欢迎,{{ user.nickname }}

+ {% if user.authority_group < 10 -%} + + + 设置项 + + + 用户管理 + + + 群管理 + + + {%- endif %} + + {% if not clan_groups -%} + +
你还没有加入公会
请在你的公会群内发送“加入公会”来加入一个公会
+ 无公会 +
+ {%- else -%} + {% for group in clan_groups -%} + + 公会:{{ group['group_name'] }} + +
+ {% endfor -%} + {%- endif %} +
+
+ + + + \ No newline at end of file diff --git a/PrincessAdventure/template/about.html b/PrincessAdventure/template/about.html index 22339ba..b2c6db8 100644 --- a/PrincessAdventure/template/about.html +++ b/PrincessAdventure/template/about.html @@ -46,7 +46,7 @@

:版本
- YoCool-v1.1.7-PrincessAdventure + YoCool-v1.1.8-PrincessAdventure

:源码
diff --git a/README.md b/README.md index 9238177..50c7180 100644 --- a/README.md +++ b/README.md @@ -74,14 +74,10 @@ YoCool控制台,实现YoCool的一键安装、切换主题、升级、卸载 ### 使用 -无需重启,即装即用 +无需重启,初次安装或更新版本时,PC端需要``Ctrl+F5``强制刷新缓存,移动端需要清除浏览器缓存 ## 最近更新 - - 调整了查刀页面的布局和样式 - - 修复了删除成员按钮的弹出层层级错误的问题 - - 修复了查刀页面报刀后,单元格缺失的问题 - - progress.js改为网络加载 - - 查刀页面的报刀记录中增加了代报人(by [@sdyxxjj123](https://github.com/sdyxxjj123)) + - 新增主题:Origin源生
[了解历史更新内容请点击这里](https://github.com/A-kirami/YoCool/wiki/update) ## 了解更多 @@ -89,7 +85,7 @@ YoCool控制台,实现YoCool的一键安装、切换主题、升级、卸载 ## 代码贡献 感谢以下大佬在本项目中提供的支援和帮助
-[@kaiseixd](https://github.com/kaiseixd) @白白小童鞋 [@pwinner](https://github.com/pwinner) [@sdyxxjj123](https://github.com/sdyxxjj123) +[@kaiseixd](https://github.com/kaiseixd) @白白小童鞋 [@pwinner](https://github.com/pwinner) ## 联系我们 Yobot后台美化组(Q群):1143518690