Skip to content

Commit d08f9ab

Browse files
committed
machine-setup: fetch info from system
1 parent ff2c2a8 commit d08f9ab

File tree

3 files changed

+142
-17
lines changed

3 files changed

+142
-17
lines changed
Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,72 @@
11
<template>
2-
<n-card bordered shadow="always" title="@Hydro/XCPC-TOOLS Setup Tool">
3-
<n-statistic title="座位号" value="未配置" style="text-align: center; font-size: 8em;" />
4-
</n-card>
5-
<n-card bordered shadow="always">
6-
<n-input placeholder="请输入座位号" type="text" size="large" style="width: 100%; margin-bottom: .5em;" />
7-
<n-space style="width: 100%;">
8-
<n-button type="primary" style="width: 100%;">保存</n-button>
9-
<n-button type="info" style="width: 100%;">放大显示</n-button>
10-
</n-space>
11-
</n-card>
2+
<n-grid x-gap="6" :cols="2">
3+
<n-gi>
4+
<n-card bordered shadow="always" style="margin-bottom: .25em;" class="text-center">
5+
<h2 style="margin: .5em 0;">@Hydro/XCPC-TOOLS</h2>
6+
<h2 style="margin: .5em 0;">Setup Tool</h2>
7+
</n-card>
8+
<n-card bordered shadow="always">
9+
<n-input placeholder="请输入座位号" v-model:value="editSeat" type="text" size="large" style="width: 100%; margin-bottom: .5em;" />
10+
<n-grid x-gap="12" :cols="2" style="width: 100%;">
11+
<n-gi>
12+
<n-button type="primary" @click="saveSeat" style="width: 100%;">保存</n-button>
13+
</n-gi>
14+
<n-gi>
15+
<n-button type="info" @click="showSeat" style="width: 100%;">放大显示</n-button>
16+
</n-gi>
17+
</n-grid>
18+
</n-card>
19+
</n-gi>
20+
<n-gi>
21+
<n-card bordered shadow="always" class="text-center">
22+
<h1 style="margin: 0;">座位号</h1>
23+
<h1 style="font-size: 8em; margin: 0;">{{ nowSeat || '未配置' }}</h1>
24+
</n-card>
25+
</n-gi>
26+
</n-grid>
1227
</template>
1328

1429
<script setup lang="ts">
15-
import { NCard, NButton, NInput } from 'naive-ui';
30+
import { filesystem, os } from '@neutralinojs/lib';
31+
import { NCard, NGrid, NGi, NButton, NInput } from 'naive-ui';
32+
import { onMounted, ref } from 'vue';
33+
34+
const nowSeat = ref('');
35+
const editSeat = ref('');
36+
37+
const saveSeat = async () => {
38+
try {
39+
console.log('save seat', editSeat.value);
40+
await filesystem.writeFile('/var/lib/icpc/config.json', JSON.stringify({ seat: editSeat.value }));
41+
const read = await filesystem.readFile('/var/lib/icpc/config.json');
42+
console.log('read seat', read);
43+
const res = await os.execCommand(`hostnamectl set-hostname ${editSeat.value}`);
44+
console.log('run hostnamectl', res);
45+
nowSeat.value = editSeat.value;
46+
} catch (error) {
47+
console.error(error);
48+
window.$notification.error({ title: '保存座位号失败', content: (error as any).message });
49+
}
50+
};
51+
52+
const showSeat = async () => {
53+
try {
54+
console.log('show seat', nowSeat.value);
55+
const res = await os.execCommand(`zenity --info --text "<span font='256'>${nowSeat.value}</span>"`);
56+
if (res.stdErr) throw new Error(res.stdErr);
57+
} catch (error) {
58+
console.error(error);
59+
window.$notification.error({ title: '放大显示座位号失败', content: (error as any).message });
60+
}
61+
};
62+
63+
64+
onMounted(async () => {
65+
try {
66+
const res = await filesystem.readFile('/var/lib/icpc/config.json');
67+
nowSeat.value = JSON.parse(res || '{}').seat || '';
68+
} catch (error) {
69+
console.error(error);
70+
}
71+
});
1672
</script>

packages/machine-setup/frontend/src/components/HeartbeatInfo.vue

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
<n-input placeholder="请输入心跳上报URL" v-model:value="heartbeaturl" size="large" style="width: 100%; margin-bottom: .5em;" />
1010
<n-grid x-gap="12" :cols="2" style="width: 100%;">
1111
<n-gi>
12-
<n-button style="width: 100%;">保存</n-button>
12+
<n-button type="primary" @click="saveHeartbeat" style="width: 100%;">保存</n-button>
1313
</n-gi>
1414
<n-gi>
15-
<n-button type="info" style="width: 100%;">测试</n-button>
15+
<n-button type="info" @click="runHeartbeat" style="width: 100%;">测试</n-button>
1616
</n-gi>
1717
</n-grid>
1818
</n-gi>
@@ -21,9 +21,55 @@
2121
</template>
2222

2323
<script setup lang="ts">
24+
import { filesystem, os } from '@neutralinojs/lib';
2425
import { NCard, NGrid, NGi, NButton, NInput } from 'naive-ui';
25-
import { ref } from 'vue';
26+
import { onMounted, ref } from 'vue';
2627
2728
const heartbeaturl = ref<string>('');
2829
const onHeartbeat = ref<boolean>(false);
30+
31+
const saveHeartbeat = async () => {
32+
try {
33+
console.log('save heartbeat', heartbeaturl.value);
34+
const res = await os.execCommand(`HEARTBEATURL=${heartbeaturl.value} /usr/sbin/icpc-heartbeat`);
35+
if (res.stdErr || res.exitCode) throw new Error(res.stdErr);
36+
console.log('run heartbeat on save', res);
37+
await filesystem.writeFile('/etc/default/icpc-heartbeat', `HEARTBEATURL=${heartbeaturl.value}`);
38+
const res2 = await os.execCommand('systemctl enable heartbeat.timer');
39+
console.log('run enable heartbeat on save', res2);
40+
} catch (error) {
41+
console.error(`save heartbeat error: ${error}`);
42+
window.$notification.error({ title: '保存心跳上报URL失败', content: (error as any).message });
43+
}
44+
};
45+
46+
const runHeartbeat = async () => {
47+
try {
48+
const res = await os.execCommand(`HEARTBEATURL=${heartbeaturl.value} /usr/sbin/icpc-heartbeat`);
49+
if (res.stdErr || res.exitCode) throw new Error(res.stdErr);
50+
console.log('run heartbeat on test', res);
51+
} catch (error) {
52+
console.error(`run heartbeat error: ${error}`);
53+
window.$notification.error({ title: '测试心跳上报URL失败', content: (error as any).message });
54+
}
55+
};
56+
57+
onMounted(async () => {
58+
try {
59+
const res = await filesystem.readFile('/etc/default/icpc-heartbeat');
60+
console.log('icpc-heartbeat', res);
61+
heartbeaturl.value = res.split('=')[1].trim();
62+
if (!heartbeaturl.value) {
63+
const res = await os.execCommand('systemctl disable heartbeat.timer');
64+
console.log('disable heartbeat.timer', res);
65+
onHeartbeat.value = false;
66+
} else {
67+
const res = await os.execCommand('systemctl status heartbeat | grep Active');
68+
console.log('systemctl status heartbeat status', res);
69+
if (!res.stdOut.includes('dead')) onHeartbeat.value = true;
70+
}
71+
} catch (error) {
72+
console.error('mount heartbeat error:', error);
73+
}
74+
});
2975
</script>
Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
11
<template>
22
<n-card bordered title="网络信息" shadow="always">
33
<n-grid x-gap="12" :cols="2">
4-
<n-gi v-for="info in netInfo" :key="info.ip">
4+
<n-gi v-for="info in netInfo" :key="info.dev">
55
<p>{{ info.dev }}/{{ info.mac }}</p>
6-
<p>IP: {{ info.ip }}</p>
6+
<p>IPV4: {{ info.v4 }}</p>
7+
<p>IPV6: {{ info.v6 }}</p>
78
</n-gi>
89
</n-grid>
910
<p v-if="netInfo.length === 0">No network information found.</p>
1011
</n-card>
1112
</template>
1213

1314
<script setup lang="ts">
14-
import { ref } from 'vue';
15+
import { os } from '@neutralinojs/lib';
16+
import { onMounted, ref } from 'vue';
1517
1618
const netInfo = ref<any[]>([]);
19+
20+
onMounted(async () => {
21+
try {
22+
const res = await os.execCommand('ip --json address');
23+
const info = JSON.parse(res.stdOut);
24+
console.log(info);
25+
const ips = info.filter((i: any) => {
26+
const local = i.addr_info?.filter((a: any) => a.family === 'inet')[0]?.local;
27+
return local && (local.startsWith('10') || local.startsWith('192.168') || local.startsWith('172.16'));
28+
}).map((i: any) => ({
29+
v4: i.addr_info.filter((a: any) => a.family === 'inet').map((a: any) => a.local).join(', '),
30+
v6: i.addr_info.filter((a: any) => a.family === 'inet6').map((a: any) => a.local).join(', '),
31+
dev: i.ifname,
32+
mac: i.address
33+
}));
34+
netInfo.value = ips;
35+
} catch (error) {
36+
console.error(error);
37+
38+
}
39+
});
1740
</script>

0 commit comments

Comments
 (0)