0) {
18 | blurLeft.style.opacity = 1; // 显示左侧模糊提示
19 | } else {
20 | blurLeft.style.opacity = 0; // 隐藏左侧模糊提示
21 | }
22 |
23 | // 检查右侧是否有可滑动元素
24 | if (headContainer.scrollLeft < headContainer.scrollWidth - headContainer.clientWidth) {
25 | blurRight.style.opacity = 1; // 显示右侧模糊提示
26 | } else {
27 | blurRight.style.opacity = 0; // 隐藏右侧模糊提示
28 | }
29 | }
30 |
31 | // ----------------------------------------------------------------------------------------------------
32 | // 获取当前页面的 URL
33 | const currentUrl = new URL(window.location.href);
34 | // 获取 URL 中的 key 参数
35 | const key = currentUrl.searchParams.get('key');
36 | // 如果 key 参数存在,则修改相关跳转
37 | if (key) {
38 | var form = document.getElementById('restart');
39 | form.action = `/restart?key=${key}`;
40 | document.getElementById('logs').href = `/logs?key=${key}`;
41 | document.getElementById('go_wol').href = `/wol?key=${key}`;
42 | document.getElementById('go_shutdown').href = `/shutdown?key=${key}`;
43 | document.getElementById('go_ping').href = `/ping?key=${key}`;
44 | document.getElementById('go_push').href = `/testpush?key=${key}`;
45 | }
46 | // 监听表单提交事件
47 | document.getElementById('restart').addEventListener('submit', function (event) {
48 | event.preventDefault(); // 防止表单默认提交
49 |
50 | // 使用 Fetch API 发送 POST 请求(不关心响应)
51 | fetch(form.action, {
52 | method: 'POST',
53 | })
54 | // 初始化倒计时
55 | let countdown = 5;
56 |
57 | // 添加 "即将刷新" 消息
58 | const flashMessages = document.getElementById('flash-messages');
59 | const messageElement = document.createElement('ul');
60 | const messageItem = document.createElement('li');
61 | messageItem.innerHTML = `即将刷新 ${countdown}`;
62 | messageElement.appendChild(messageItem);
63 | flashMessages.appendChild(messageElement);
64 |
65 | // 设置定时器每秒更新一次消息
66 | const intervalId = setInterval(function () {
67 | countdown--;
68 | messageItem.innerHTML = `即将刷新 ${countdown}`; // 更新提示消息
69 |
70 | // 倒计时结束后刷新页面
71 | if (countdown < 1) {
72 | clearInterval(intervalId); // 清除定时器
73 | location.reload(); // 刷新页面
74 | }
75 | }, 1000); // 每隔1秒更新一次
76 | });
77 |
78 | // ----------------------------------------------------------------------------------------------------
79 | function go_func_show() {
80 | const items = [
81 | 'bemfa', 'wol', 'shutdown', 'ping', 'push',
82 | 'serverchanturbo', 'serverchan3', 'qmsg', 'wechat_webhook'
83 | ];
84 |
85 | items.forEach(item => {
86 | const enabled_id = `${item}_enabled`;
87 | const go_id = `go_${item}`;
88 |
89 | const goElement = document.getElementById(go_id);
90 |
91 | // 根据 enabled 元素的 checked 属性值,添加或移除 visible 类
92 | if (document.getElementById(enabled_id).checked) {
93 | goElement.classList.remove('hidden');
94 | goElement.classList.add('visible');
95 | } else {
96 | goElement.classList.remove('visible');
97 | goElement.classList.add('hidden');
98 | }
99 | });
100 | }
101 |
102 |
103 | // 根据复选框状态更新对应内容的显示或隐藏
104 | function ifshow(event) {
105 | const checkbox = event.target; // 当前触发事件的复选框
106 | const targetId = checkbox.dataset.target; // 获取对应的内容 ID
107 | const targetElement = document.getElementById(targetId); // 获取目标内容元素
108 |
109 | if (checkbox.checked) {
110 | targetElement.classList.remove('hidden');
111 | targetElement.classList.add('visible');
112 | } else {
113 | targetElement.classList.remove('visible');
114 | targetElement.classList.add('hidden');
115 | }
116 | go_func_show();
117 | }
118 |
119 | // 页面加载完成后为所有复选框添加事件监听
120 | document.addEventListener('DOMContentLoaded', () => {
121 | const checkboxes = document.querySelectorAll('.checkbox-label:not(#bemfa_reconnect_enabled)');
122 |
123 | checkboxes.forEach(checkbox => {
124 | // 初始化显示状态
125 | const targetId = checkbox.dataset.target;
126 | const targetElement = document.getElementById(targetId);
127 |
128 | if (checkbox.checked) {
129 | targetElement.classList.remove('hidden');
130 | } else {
131 | targetElement.classList.add('hidden');
132 | }
133 | go_func_show()
134 | // 添加监听事件
135 | checkbox.addEventListener('change', ifshow);
136 | });
137 | });
138 |
139 | // ----------------------------------------------------------------------------------------------------
140 | // 获取复选框和目标内容元素
141 | const netrpcCheckbox = document.getElementById('netrpc');
142 | const udpCheckbox = document.getElementById('udp');
143 | const shellCheckbox = document.getElementById('shell');
144 | const netrpcConfig = document.getElementById('netrpcconfig');
145 | const dl_pcshutdown = document.getElementById('dl_pcshutdown');
146 | const shell_script = document.getElementById('shell_script');
147 | const shutdown_delay_time = document.getElementById('shutdown_delay_time');
148 |
149 | // 更新netrpcconfig的显示状态
150 | function ifshow_method_shutdown() {
151 | function showElement(element) {
152 | element.classList.remove('hidden');
153 | element.classList.add('visible');
154 | }
155 |
156 | function hideElement(element) {
157 | element.classList.remove('visible');
158 | element.classList.add('hidden');
159 | }
160 |
161 | hideElement(netrpcConfig);
162 | hideElement(dl_pcshutdown);
163 | hideElement(shell_script);
164 | hideElement(shutdown_delay_time);
165 |
166 | if (netrpcCheckbox.checked) {
167 | showElement(netrpcConfig);
168 | showElement(shutdown_delay_time);
169 | } else if (udpCheckbox.checked) {
170 | showElement(dl_pcshutdown);
171 | showElement(shutdown_delay_time);
172 | } else if (shellCheckbox.checked) {
173 | showElement(shell_script);
174 | }
175 | }
176 |
177 | // 勾选一个复选框时,取消另一个复选框的勾选
178 | function only_one_check(checkedCheckbox) {
179 | const checkboxes = [netrpcCheckbox, udpCheckbox, shellCheckbox];
180 | checkboxes.forEach(checkbox => {
181 | // 如果当前复选框被勾选的复选框,则勾选
182 | if (checkbox !== checkedCheckbox) {
183 | checkbox.checked = false;
184 | }
185 | });
186 | ifshow_method_shutdown();
187 | }
188 |
189 | // 监听
190 | function handleCheckboxChange(checkbox) {
191 | if (checkbox.checked) {
192 | only_one_check(checkbox);
193 | } else {
194 | checkbox.checked = true; // 禁止取消勾选
195 | }
196 | }
197 |
198 | document.addEventListener('DOMContentLoaded', () => {
199 | ifshow_method_shutdown();
200 |
201 | // 添加change事件监听
202 | netrpcCheckbox.addEventListener('change', () => handleCheckboxChange(netrpcCheckbox));
203 | udpCheckbox.addEventListener('change', () => handleCheckboxChange(udpCheckbox));
204 | shellCheckbox.addEventListener('change', () => handleCheckboxChange(shellCheckbox));
205 | });
206 |
207 | // ----------------------------------------------------------------------------------------------------
208 | function submit_pcconfig() {
209 | document.getElementById("pcconfig").submit();
210 | }
211 |
212 | // ----------------------------------------------------------------------------------------------------
213 | // 动态调整输入框宽度
214 | document.addEventListener("DOMContentLoaded", function () {
215 | document.querySelectorAll(".input-label").forEach((input) => {
216 | // 默认宽度
217 | const defaultWidth = window.getComputedStyle(input).width;
218 |
219 | function adjustWidth() {
220 | // 创建一个临时span元素来计算文本长度
221 | let tempSpan = document.createElement("span");
222 | tempSpan.style.visibility = "hidden";
223 | tempSpan.style.position = "absolute"; // 避免影响布局
224 | tempSpan.style.whiteSpace = "nowrap"; // 确保单行计算宽度
225 | tempSpan.style.fontSize = window.getComputedStyle(input).fontSize;
226 | tempSpan.style.fontFamily = window.getComputedStyle(input).fontFamily;
227 | tempSpan.innerText = input.value || input.placeholder || "输入文本";
228 | document.body.appendChild(tempSpan);
229 |
230 | // 计算并设置input宽度
231 | input.style.width = `${tempSpan.offsetWidth + 10}px`;
232 |
233 | document.body.removeChild(tempSpan);
234 | }
235 |
236 | // 监听用户输入或粘贴
237 | input.addEventListener("input", adjustWidth);
238 | // 监听焦点事件来调整宽度
239 | input.addEventListener("focus", adjustWidth);
240 | // 失去焦点时恢复默认宽度
241 | input.addEventListener("blur", function () {
242 | input.style.width = defaultWidth;;
243 | });
244 | });
245 | });
246 |
247 | // ----------------------------------------------------------------------------------------------------
248 | // 下载确认
249 | function confirmDownload() {
250 | var result = confirm("确认下载");
251 | return result;
252 | }
253 |
254 | // ----------------------------------------------------------------------------------------------------
255 | // 实时更新wol目标地址
256 | function update_wol_dest() {
257 | const ipInput = document.getElementById('device_ip').value;
258 | const broadcastIpDirect = document.getElementById('broadcast_ip_direct');
259 | const broadcastDeviceIp = document.getElementById('broadcast_device_ip');
260 |
261 | // 更新定向广播选项
262 | const broadcastIp = ipInput.slice(0, ipInput.lastIndexOf('.') + 1) + '255';
263 | broadcastIpDirect.textContent = '定向广播(' + broadcastIp + ')';
264 |
265 | // 更新设备IP选项
266 | broadcastDeviceIp.textContent = '设备ip(' + ipInput + ')';
267 | }
268 |
269 | // 页面加载时更新
270 | window.onload = update_wol_dest;
--------------------------------------------------------------------------------
/app/static/js/index.js:
--------------------------------------------------------------------------------
1 | // index.html
2 |
3 | // ----------------------------------------------------------------------------------------------------
4 | // 顶部模糊效果
5 | window.addEventListener('DOMContentLoaded', checkBlur);
6 | window.addEventListener('resize', checkBlur);
7 | document.querySelector('.head-container').addEventListener('scroll', checkBlur);
8 |
9 | function checkBlur() {
10 | const headContainer = document.querySelector('.head-container');
11 | const blurLeft = document.querySelector('.blur-left');
12 | const blurRight = document.querySelector('.blur-right');
13 |
14 | if (!headContainer || !blurLeft || !blurRight) return;
15 |
16 | // 检查左侧是否有可滑动元素
17 | if (headContainer.scrollLeft > 0) {
18 | blurLeft.style.opacity = 1; // 显示左侧模糊提示
19 | } else {
20 | blurLeft.style.opacity = 0; // 隐藏左侧模糊提示
21 | }
22 |
23 | // 检查右侧是否有可滑动元素
24 | if (headContainer.scrollLeft < headContainer.scrollWidth - headContainer.clientWidth) {
25 | blurRight.style.opacity = 1; // 显示右侧模糊提示
26 | } else {
27 | blurRight.style.opacity = 0; // 隐藏右侧模糊提示
28 | }
29 | }
30 |
31 | // ----------------------------------------------------------------------------------------------------
32 | // 跳转按钮
33 | document.addEventListener("DOMContentLoaded", function () {
34 | let input = document.getElementById("webkey");
35 | let button = document.getElementById("keybtn");
36 | let message = document.getElementById("message");
37 |
38 | function sendKey() {
39 | let key = input.value
40 | fetch("/", {
41 | method: "POST",
42 | headers: {
43 | "Content-Type": "application/json"
44 | },
45 | body: JSON.stringify({ key: key })
46 | })
47 | .then(response => response.json())
48 | .then(data => {
49 | if (data.success) {
50 | window.location.href = `/config?key=${key}`;
51 | } else {
52 | message.textContent = data.message; // 显示错误信息
53 | message.classList.remove("hidden");
54 | message.classList.add("visible");
55 | setTimeout(() => {
56 | message.classList.remove("visible");
57 | message.classList.add("hidden");
58 | }, 3000); // 3 秒后清空
59 | }
60 | })
61 | .catch(error => console.error("Error:", error));
62 | }
63 |
64 | // 监听按钮点击
65 | button.addEventListener("click", sendKey);
66 |
67 | // 监听输入框按键
68 | input.addEventListener("keydown", function (event) {
69 | if (event.key === "Enter") {
70 | event.preventDefault(); // 防止刷新页面
71 | sendKey();
72 | }
73 | });
74 | });
75 | // ----------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------
/app/static/js/logs.js:
--------------------------------------------------------------------------------
1 | // logs.html
2 |
3 | // 加载文件内容
4 | function loadFileContent(filename, listItem) {
5 | // 取消其他文件的选中状态
6 | const allItems = document.querySelectorAll('.file-list li');
7 | allItems.forEach(item => item.classList.remove('selected'));
8 |
9 | // 高亮当前选择的文件
10 | listItem.classList.add('selected');
11 |
12 | // 更新文件名
13 | document.getElementById('fileName').textContent = filename;
14 |
15 | // 获取当前页面的 URL
16 | const currentUrl = new URL(window.location.href);
17 | // 获取 URL 中的 key 参数
18 | const key = currentUrl.searchParams.get('key');
19 | // 构造 fetch 请求的 URL,带上 key 参数
20 | const fetchUrl = `/logs/${filename}?key=${key}`;
21 |
22 | // 请求文件内容
23 | fetch(fetchUrl)
24 | .then(response => response.json())
25 | .then(data => {
26 | // 获取日志内容
27 | let logContent = data.log_content;
28 |
29 | // 将日志内容按行分割
30 | const lines = logContent.split('\n');
31 |
32 | // 遍历每一行,检查是否包含 '[Error]',如果是,则添加红色样式
33 | const formattedLines = lines.map(line => {
34 | if (line.includes('[Error]')) {
35 | return `${line}`;
36 | }
37 | return line;
38 | });
39 |
40 | // 将处理后的日志内容插入到页面
41 | document.getElementById('fileContent').innerHTML = formattedLines.join('
');
42 |
43 | // 使用 DOM 的 scrollTop 属性将内容区域滚动到顶部
44 | const contentArea = document.getElementById('contentArea');
45 | contentArea.scrollTop = 0; // 直接将 scrollTop 设置为 0
46 | })
47 | .catch(error => alert('无法加载文件内容: ' + error));
48 |
49 | // 点击文件后自动隐藏文件列表(仅移动端)
50 | if (window.innerWidth <= 768) {
51 | toggleSidebar();
52 | }
53 | }
54 |
55 | // 切换文件列表的显示与隐藏
56 | function toggleSidebar() {
57 | const sidebar = document.getElementById('sidebar');
58 | const button = document.getElementById('toggleButton');
59 |
60 | // 判断文件列表是否显示
61 | if (sidebar.classList.contains('open')) {
62 | sidebar.classList.remove('open');
63 | button.textContent = '>'; // 显示右箭头
64 | } else {
65 | sidebar.classList.add('open');
66 | button.textContent = '<'; // 显示左箭头
67 | }
68 | }
69 |
70 | // 页面加载时显示切换按钮(移动端)
71 | window.addEventListener('resize', function () {
72 | const button = document.getElementById('toggleButton');
73 | const sidebar = document.getElementById('sidebar');
74 | if (window.innerWidth > 768) {
75 | button.style.display = 'none'; // 隐藏切换按钮
76 | sidebar.classList.add('open'); // 始终显示文件列表
77 | } else {
78 | button.style.display = 'block'; // 显示切换按钮
79 | sidebar.classList.remove('open'); // 隐藏文件列表
80 | }
81 | });
82 |
83 | // 初始加载时处理屏幕尺寸并确保文件列表弹出(手机端)
84 | window.addEventListener('load', function () {
85 | if (window.innerWidth <= 768) {
86 | const sidebar = document.getElementById('sidebar');
87 | sidebar.classList.add('open'); // 移动端首次加载时自动显示文件列表
88 | document.getElementById('toggleButton').textContent = '<'; // 设置按钮为左箭头
89 | }
90 | });
91 |
92 | // 点击非列表区域时收起文件列表
93 | document.addEventListener('click', function (event) {
94 | const sidebar = document.getElementById('sidebar');
95 | const button = document.getElementById('toggleButton');
96 | const sidebarArea = sidebar.contains(event.target);
97 | const buttonArea = button.contains(event.target);
98 |
99 | if (!sidebarArea && !buttonArea && window.innerWidth <= 768) {
100 | sidebar.classList.remove('open');
101 | button.textContent = '>'; // 恢复右箭头
102 | }
103 | });
104 |
105 | // 初始加载时处理屏幕尺寸
106 | window.dispatchEvent(new Event('resize'));
--------------------------------------------------------------------------------
/app/static/js/theme.js:
--------------------------------------------------------------------------------
1 | // 深色模式
2 | // 手动切换主题的功能
3 | function toggleTheme() {
4 | document.body.style.transition = "background-color 0.5s, color 0.5s";
5 | document.body.classList.toggle('dark-mode');
6 | // 保存用户选择的主题到 localStorage,确保页面刷新后保持设置
7 | const theme = document.body.classList.contains('dark-mode') ? 'dark' : 'light';
8 | localStorage.setItem('theme', theme);
9 | }
10 |
11 | // 检测并设置当前的主题
12 | function detectAndApplyTheme() {
13 | const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
14 | if (isDarkMode) {
15 | document.body.classList.add('dark-mode');
16 | } else {
17 | document.body.classList.remove('dark-mode');
18 | }
19 | }
20 |
21 | // 页面加载时应用用户上次选择的主题
22 | document.addEventListener('DOMContentLoaded', () => {
23 | const savedTheme = localStorage.getItem('theme');
24 | if (savedTheme) {
25 | if (savedTheme === 'dark') {
26 | document.body.classList.add('dark-mode');
27 | } else {
28 | document.body.classList.remove('dark-mode');
29 | }
30 | } else {
31 | detectAndApplyTheme(); // 如果没有保存,自动检测系统主题
32 | }
33 |
34 | // 给图片添加点击事件,点击图片切换主题
35 | const themeToggleButton = document.getElementById('theme-toggle');
36 | themeToggleButton.addEventListener('click', toggleTheme);
37 | });
--------------------------------------------------------------------------------
/app/templates/changelog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 更新日志
11 |
12 |
13 |
14 |
15 |
更新日志
16 |
 }})
17 |
18 | {% if log_content %}
19 |
{{ log_content }}
20 | {% else %}
21 |
无法加载更新日志,文件未找到。
22 | {% endif %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/templates/code.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 代码块
15 |
16 |
17 |
18 |
代码
19 |
 }})
21 |
22 | {% raw %}
23 |
24 | 1、docker-cli:
25 |
26 |
27 |
28 | docker run -d -v /your/path:/app/data -e WEB_PORT=7678 -e WEB_KEY=yourkey --network host --restart unless-stopped --name powercontrol viklion/powercontrol:latest
29 | # 默认root用户运行
30 |
31 |
32 |
33 |
34 |
35 | docker run -d -u 1000:100 -v /your/path:/app/data -e WEB_PORT=7678 -e WEB_KEY=yourkey --network host --restart unless-stopped --name powercontrol viklion/powercontrol:latest
36 | # 设置指定user运行(-u uid:gid)
37 |
38 |
39 |
40 |
41 | 2、docker-compose(注意检查缩进)
42 |
43 |
44 |
45 | services:
46 | powercontrol:
47 | image: viklion/powercontrol:latest
48 | container_name: powercontrol
49 | volumes:
50 | - /your/path:/app/data
51 | environment:
52 | - WEB_PORT=7678
53 | - WEB_KEY=yourkey
54 | # 默认root用户运行,去掉下行的#,设置指定user运行(uid:gid)
55 | #user: 1000:100
56 | restart: unless-stopped
57 | network_mode: host
58 |
59 |
60 |
61 |
62 | 3、homeassistant configuration.yaml(注意检查缩进)
63 |
64 |
65 |
66 | shell_command:
67 | ha_wol_pc: "curl http://192.168.2.75:1856/wol?key=1111"
68 | ha_shutdown_pc: "curl http://192.168.2.75:1856/shutdown?key=1111"
69 |
70 | input_text:
71 | powercontrol_state:
72 | name: powercontrol_state
73 | initial: "off"
74 |
75 | sensor:
76 | - platform: rest
77 | name: "powercontrol_pc_state"
78 | resource: "http://192.168.2.75:1856/ping?key=1111"
79 | method: GET
80 | scan_interval: 60
81 | value_template: "{{ value_json.device_status }}"
82 |
83 | switch:
84 | - platform: template
85 | switches:
86 | my_pc:
87 | friendly_name: "电脑"
88 | unique_id: "my_pc_001"
89 | icon_template: mdi:desktop-tower-monitor
90 | value_template: "{{ states('input_text.powercontrol_state') == 'on' }}"
91 | turn_on:
92 | - service: shell_command.ha_wol_pc
93 | - service: input_text.set_value
94 | target:
95 | entity_id: input_text.powercontrol_state
96 | data:
97 | value: "on"
98 | turn_off:
99 | - service: shell_command.ha_shutdown_pc
100 | - service: input_text.set_value
101 | target:
102 | entity_id: input_text.powercontrol_state
103 | data:
104 | value: "off"
105 |
106 |
107 |
108 |
109 | 4、homeassistant automations.yaml(注意检查缩进)
110 |
111 |
112 |
113 | - id: '20250108'
114 | alias: 更新电脑在线状态
115 | trigger:
116 | - platform: time_pattern
117 | minutes: "/1"
118 | condition:
119 | - condition: template
120 | value_template: "{{ states('sensor.powercontrol_pc_state') != states('input_text.powercontrol_state') }}"
121 | action:
122 | - service: input_text.set_value
123 | target:
124 | entity_id: input_text.powercontrol_state
125 | data:
126 | value: "{{ states('sensor.powercontrol_pc_state') }}"
127 |
128 |
129 | {% endraw %}
130 |
131 |
--------------------------------------------------------------------------------
/app/templates/config.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | PowerControl配置页
11 |
12 |
13 |
14 |
15 |
16 |
17 |
28 |
29 |
30 |
31 |
32 |
PowerControl配置 {{ config.version }}
33 |
by viklion
34 |
{{ run_time }}
35 |
36 |
37 | {% with messages = get_flashed_messages() %}
38 | {% if messages %}
39 |
40 | {% for message in messages %}
41 | - {{ message | replace('\n', '
')| safe }}
42 | {% endfor %}
43 |
44 | {% endif %}
45 | {% endwith %}
46 |
47 |
48 |
50 |
53 |
54 |
179 |
180 |
181 |
--------------------------------------------------------------------------------
/app/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | PowerControl
12 |
13 |
14 |
15 |
16 |
17 |
18 |
30 |
31 |
32 |
33 |
34 |
PowerControl {{ config.version }}
35 |
by viklion
36 |
{{ run_time }}
37 |
38 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/templates/logs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 操作日志
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
28 |
29 |
30 |
31 |
32 |
左侧选择日志文件
33 |
 }})
35 |
36 |
点击日志文件查看内容。
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/doc/PowerControl教程.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/doc/PowerControl教程.pdf
--------------------------------------------------------------------------------
/iStoreOS.md:
--------------------------------------------------------------------------------
1 | # iStoreOS添加容器详细指引
2 | 1. docker-镜像,输入`viklion/powercontrol:latest`,点击`拉取`
3 |
4 | 
5 |
6 | 1. docker-容器,点击`新增`
7 |
8 | 
9 |
10 | 1. 容器名称:`powercontrol`(可自由更改)
11 |
12 | Docker镜像,选择`viklion/powercontrol:latest`
13 |
14 | 勾选`总是先拉取镜像`
15 |
16 | 重启策略:选择`Unless stopped`
17 |
18 | 网络:选择`host`
19 |
20 | 环境变量(别忘了点击'+'号):`WEB_PORT=你想设置的端口号,默认:7678` , `WEB_KEY=你想设置的密钥,默认:admin`
21 |
22 | 绑定挂载(别忘了点击'+'号):`/dockerdata/powercontrol:/app/data`或者`你自定义的存放配置文件和日志文件的文件夹:/app/data`
23 |
24 | 
25 |
26 | 1. 勾选容器,点击`启动`
27 |
28 | 
29 |
30 | 1. 容器启动后访问`ip:端口`进入首页,顶部跳转教程,输入KEY跳转配置
31 |
--------------------------------------------------------------------------------
/icon/powercontrol-圆角.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/icon/powercontrol-圆角.png
--------------------------------------------------------------------------------
/icon/powercontrol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/icon/powercontrol.png
--------------------------------------------------------------------------------
/icon/powercontrol宽图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/icon/powercontrol宽图.png
--------------------------------------------------------------------------------
/icon/powercontrol宽图透明.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/icon/powercontrol宽图透明.png
--------------------------------------------------------------------------------
/icon/powercontrol透明背景.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/icon/powercontrol透明背景.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | APScheduler==3.11.0
2 | blinker==1.9.0
3 | certifi==2024.12.14
4 | charset-normalizer==3.4.0
5 | click==8.1.8
6 | colorama==0.4.6
7 | Flask==3.1.0
8 | Flask-Cors==5.0.0
9 | idna==3.10
10 | itsdangerous==2.2.0
11 | Jinja2==3.1.5
12 | MarkupSafe==3.0.2
13 | pythonping==1.1.4
14 | PyYAML==6.0.2
15 | requests==2.32.3
16 | serverchan-sdk==1.0.6
17 | setuptools==75.1.0
18 | tzdata==2024.2
19 | tzlocal==5.2
20 | urllib3==2.3.0
21 | wakeonlan==3.1.0
22 | Werkzeug==3.1.3
23 | wheel==0.44.0
24 |
--------------------------------------------------------------------------------
/software/PCshutdown.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/software/PCshutdown.exe
--------------------------------------------------------------------------------
/software/WakeOnLanMonitor.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viklion/PowerControl/b5f6c390652e7c1156dac98209acce40e2f337a5/software/WakeOnLanMonitor.exe
--------------------------------------------------------------------------------