feat: implement Windows service for parental control application
This commit is contained in:
+27
-10
@@ -5,6 +5,11 @@ async function api(path, body) {
|
||||
? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }
|
||||
: {};
|
||||
const res = await fetch(path, init);
|
||||
// сессия истекла — иначе открытая вкладка молча перестала бы обновляться
|
||||
if (res.status === 401) {
|
||||
location.href = '/login';
|
||||
throw new Error('нужен вход');
|
||||
}
|
||||
if (!res.ok) throw new Error(`${path}: ${res.status}`);
|
||||
return res.json();
|
||||
}
|
||||
@@ -89,25 +94,32 @@ const UpdateBar = {
|
||||
props: { info: { type: Object, required: true } },
|
||||
emits: ['check'],
|
||||
setup(props) {
|
||||
const busy = computed(() => ['checking', 'downloading', 'installing'].includes(props.info.phase));
|
||||
const status = computed(() => {
|
||||
const i = props.info;
|
||||
const phases = { checking: 'проверка…', downloading: 'загрузка…', installing: 'установка…' };
|
||||
if (phases[i.phase]) return phases[i.phase];
|
||||
if (i.error) return 'не удалось проверить обновления';
|
||||
if (i.available && i.latest && i.latest !== i.current) return 'доступна версия ' + i.latest;
|
||||
if (i.phase === 'checking') return 'проверка…';
|
||||
if (i.phase === 'installing') return `устанавливается ${i.latest}, панель перезапустится`;
|
||||
if (i.error) return i.error;
|
||||
if (i.available) return `доступна версия ${i.latest}`;
|
||||
return 'установлена последняя версия';
|
||||
});
|
||||
return { busy, status };
|
||||
return {
|
||||
status,
|
||||
checking: computed(() => props.info.phase === 'checking'),
|
||||
bad: computed(() => Boolean(props.info.error)),
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<section class="card">
|
||||
<div class="row" style="justify-content:space-between">
|
||||
<div>
|
||||
<h2 style="margin:0">Версия {{ info.current || '—' }}</h2>
|
||||
<span :class="info.error ? 'warn' : 'muted'">{{ status }}</span>
|
||||
<span :class="bad ? 'warn' : 'muted'">{{ status }}</span>
|
||||
</div>
|
||||
<button :disabled="busy" @click="$emit('check')">Проверить обновления</button>
|
||||
<button :disabled="checking" @click="$emit('check')">Проверить обновления</button>
|
||||
</div>
|
||||
<div v-if="info.installer" class="muted" style="margin-top:8px">
|
||||
Установщик, {{ info.installer.time }}:
|
||||
<span :class="{ warn: !info.installer.ok }">{{ info.installer.message }}</span>
|
||||
</div>
|
||||
</section>`,
|
||||
};
|
||||
@@ -243,7 +255,9 @@ const App = {
|
||||
const { info: update, load: loadUpdate, check: checkUpdate } = useUpdate();
|
||||
|
||||
onMounted(loadRules);
|
||||
usePolling(() => { loadProcesses(); loadLog(); loadUpdate(); }, 3000);
|
||||
usePolling(() => { loadProcesses(); loadLog(); }, 3000);
|
||||
// версия меняется раз в сутки в лучшем случае — частить незачем
|
||||
usePolling(loadUpdate, 30000);
|
||||
|
||||
// в whitelist «заблокирован» означает отсутствие в allowed — действия зеркальные
|
||||
const toggle = async (g) => {
|
||||
@@ -265,7 +279,10 @@ const App = {
|
||||
return { rules, groups, lines, update, whitelist, save, remove, toggle, kill, scheduleRandom, checkUpdate };
|
||||
},
|
||||
template: `
|
||||
<h1>Родительский контроль</h1>
|
||||
<div class="row" style="justify-content:space-between">
|
||||
<h1>Родительский контроль</h1>
|
||||
<form method="post" action="/logout"><button>Выйти</button></form>
|
||||
</div>
|
||||
<update-bar :info="update" @check="checkUpdate" />
|
||||
<rules-panel :rules="rules" @update="save" @remove="remove" />
|
||||
<random-kill @schedule="scheduleRandom" />
|
||||
|
||||
Reference in New Issue
Block a user