|
|
@@ -0,0 +1,149 @@
|
|
|
+<template>
|
|
|
+ <div class="ota-upgrade">
|
|
|
+ <h1>OTA 固件升级</h1>
|
|
|
+
|
|
|
+ <!-- 设备列表 -->
|
|
|
+ <div class="device-list">
|
|
|
+ <table>
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <th><input type="checkbox" v-model="selectAll" @change="toggleSelectAll" /></th>
|
|
|
+ <th>设备ID</th>
|
|
|
+ <th>当前固件版本</th>
|
|
|
+ <th>最新版本</th>
|
|
|
+ <th>状态</th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <tr v-for="device in devices" :key="device.device_id">
|
|
|
+ <td>
|
|
|
+ <input type="checkbox" v-model="selectedDevices" :value="device.device_id" />
|
|
|
+ </td>
|
|
|
+ <td>{{ device.name }}</td>
|
|
|
+ <td>{{ device.current_firmware_version || '未知' }}</td>
|
|
|
+ <td>{{ device.firmware_version || '未知' }}</td>
|
|
|
+ <td>{{ device.status }}</td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <div class="actions">
|
|
|
+ <button @click="checkUpdates">检查更新</button>
|
|
|
+ <button @click="startUpgrade" :disabled="selectedDevices.length === 0">开始升级</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 升级日志 -->
|
|
|
+ <div class="upgrade-log">
|
|
|
+ <h3>升级日志</h3>
|
|
|
+ <pre>{{ upgradeLog }}</pre>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ devices: [],
|
|
|
+ selectedDevices: [],
|
|
|
+ selectAll: false,
|
|
|
+ upgradeLog: ''
|
|
|
+ };
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ await this.fetchDevices();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async fetchDevices() {
|
|
|
+ try {
|
|
|
+ const response = await fetch('/api/devices');
|
|
|
+ if (response.ok) {
|
|
|
+ this.devices = await response.json();
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取设备列表失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ toggleSelectAll() {
|
|
|
+ if (this.selectAll) {
|
|
|
+ this.selectedDevices = this.devices.map(device => device.device_id);
|
|
|
+ } else {
|
|
|
+ this.selectedDevices = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async checkUpdates() {
|
|
|
+ try {
|
|
|
+ const response = await fetch('/api/ota/check-update', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ },
|
|
|
+ body: JSON.stringify({ devices: this.selectedDevices })
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ const data = await response.json();
|
|
|
+ this.upgradeLog = `检查更新结果:\n${JSON.stringify(data, null, 2)}`;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('检查更新失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async startUpgrade() {
|
|
|
+ try {
|
|
|
+ const response = await fetch('/api/ota/firmware', {
|
|
|
+ method: 'GET',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ this.upgradeLog = '升级任务已启动...';
|
|
|
+ // 可以添加轮询状态更新的逻辑
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('启动升级失败:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.ota-upgrade {
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.device-list {
|
|
|
+ margin: 20px 0;
|
|
|
+}
|
|
|
+
|
|
|
+table {
|
|
|
+ width: 100%;
|
|
|
+ border-collapse: collapse;
|
|
|
+}
|
|
|
+
|
|
|
+th, td {
|
|
|
+ padding: 8px;
|
|
|
+ border: 1px solid #ddd;
|
|
|
+}
|
|
|
+
|
|
|
+.actions {
|
|
|
+ margin: 20px 0;
|
|
|
+}
|
|
|
+
|
|
|
+button {
|
|
|
+ margin-right: 10px;
|
|
|
+ padding: 8px 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.upgrade-log {
|
|
|
+ margin-top: 20px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border: 1px solid #ddd;
|
|
|
+}
|
|
|
+</style>
|