Replies: 19 comments 4 replies
-
关于启动器的想法,主要是整理一些常用的资源,提供对应的下载和访问链接,并且兼具启动软件的功能 |
Beta Was this translation helpful? Give feedback.
-
一个不错的GPT的c++提问模板:
|
Beta Was this translation helpful? Give feedback.
-
后端应该弃用Carbon(Chaiscript),目前没有能力维护如此复杂的脚本,而且运行效率和编译速度太糟糕了。改为使用pocketpy和atomscript |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
-
对基于FFI的DLL封装的简化,即使封装到ModuleLoader中 #include <iostream>
#include <string>
#include <stdexcept>
#include <functional>
#include <memory>
// Determine the platform
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM_WINDOWS
#include <windows.h>
#elif defined(__linux__)
#define PLATFORM_LINUX
#include <dlfcn.h>
#elif defined(__APPLE__)
#define PLATFORM_MACOS
#include <dlfcn.h>
#endif
class DynamicLibrary {
public:
explicit DynamicLibrary(const std::string& dllName) {
#ifdef PLATFORM_WINDOWS
hModule = LoadLibraryA(dllName.c_str());
if (!hModule) {
std::cerr << "Failed to load the DLL: " << dllName << std::endl;
throw std::runtime_error("Failed to load the DLL");
}
#else
hModule = dlopen(dllName.c_str(), RTLD_LAZY);
if (!hModule) {
std::cerr << "Failed to load the shared library: " << dllName << std::endl;
throw std::runtime_error("Failed to load the shared library");
}
#endif
std::cout << "Library loaded successfully: " << dllName << std::endl;
}
~DynamicLibrary() {
#ifdef PLATFORM_WINDOWS
if (hModule) {
FreeLibrary(static_cast<HMODULE>(hModule));
std::cout << "DLL unloaded successfully." << std::endl;
}
#else
if (hModule) {
dlclose(hModule);
std::cout << "Shared library unloaded successfully." << std::endl;
}
#endif
}
// Function to get a function pointer of any type using template and variadic arguments
template <typename Func>
std::function<Func> getFunction(const std::string& funcName) {
#ifdef PLATFORM_WINDOWS
FARPROC proc = GetProcAddress(static_cast<HMODULE>(hModule), funcName.c_str());
#else
void* proc = dlsym(hModule, funcName.c_str());
#endif
if (!proc) {
std::cerr << "Failed to get the function address: " << funcName << std::endl;
throw std::runtime_error("Failed to get the function address");
}
std::cout << "Function loaded successfully: " << funcName << std::endl;
// We use std::function to wrap the raw function pointer.
return std::function<Func>(reinterpret_cast<Func*>(proc));
}
private:
#ifdef PLATFORM_WINDOWS
HMODULE hModule = nullptr;
#else
void* hModule = nullptr;
#endif
};
// Example usage
int main() {
try {
// Adjust the library name based on the platform
#ifdef PLATFORM_WINDOWS
DynamicLibrary lib("example.dll");
#elif defined(PLATFORM_LINUX)
DynamicLibrary lib("./libexample.so");
#elif defined(PLATFORM_MACOS)
DynamicLibrary lib("./libexample.dylib");
#endif
// Define the function signature using auto and std::function
auto add = lib.getFunction<int(int, int)>("add");
auto subtract = lib.getFunction<int(int, int)>("subtract");
// Call the functions
std::cout << "add(5, 3): " << add(5, 3) << std::endl;
std::cout << "subtract(5, 3): " << subtract(5, 3) << std::endl;
} catch (const std::exception& e) {
std::cerr << "An error occurred: " << e.what() << std::endl;
return 1;
}
return 0;
} |
Beta Was this translation helpful? Give feedback.
-
很多时候,还没想好就干的效率是很低的 |
Beta Was this translation helpful? Give feedback.
-
PHD2和TCP2WS的python实现 import asyncio
import json
import subprocess
import signal
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Depends
from loguru import logger
from typing import List, Optional
import uvicorn
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.responses import FileResponse
# 初始化FastAPI应用
app = FastAPI()
security = HTTPBasic()
# 配置loguru日志记录
logger.add("server.log", rotation="1 MB")
# 全局变量存储PHD2进程
phd2_process: Optional[asyncio.subprocess.Process] = None
# 模拟用户验证(实际应用中应使用数据库或其他方式)
def verify_credentials(credentials: HTTPBasicCredentials):
if credentials.username == "admin" and credentials.password == "secret":
return True
else:
raise HTTPException(status_code=401, detail="Unauthorized")
# 连接管理器类,管理多个WebSocket客户端
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
logger.info(f"Client connected: {websocket.client}")
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
logger.info(f"Client disconnected: {websocket.client}")
async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_text(message)
manager = ConnectionManager()
async def tcp_client_handler(tcp_reader, tcp_writer, websocket: WebSocket):
try:
while True:
data = await tcp_reader.read(100)
if not data:
break
await websocket.send_bytes(data)
except Exception as e:
logger.error(f"TCP client handler exception: {e}")
finally:
tcp_writer.close()
await tcp_writer.wait_closed()
async def handle_phd2_messages(message: dict):
# 在这里处理PHD2特定的消息
if message.get('Event') == 'GuideStep':
logger.info(f"PHD2 GuideStep event: {message}")
elif message.get('Event') == 'StartGuiding':
logger.info("PHD2 StartGuiding event")
elif message.get('Event') == 'StopGuiding':
logger.info("PHD2 StopGuiding event")
async def handle_websocket(websocket: WebSocket):
await manager.connect(websocket)
while True:
try:
tcp_reader, tcp_writer = await asyncio.wait_for(
asyncio.open_connection('localhost', 4400), timeout=5.0)
break
except (asyncio.TimeoutError, ConnectionRefusedError) as e:
logger.error(f"Failed to connect to TCP server: {e}")
await asyncio.sleep(5) # Wait before retrying
try:
asyncio.create_task(tcp_client_handler(tcp_reader, tcp_writer, websocket))
while True:
data = await asyncio.wait_for(websocket.receive_text(), timeout=30.0)
message = json.loads(data)
logger.info(f"Received message from {websocket.client}: {message}")
await handle_phd2_messages(message)
tcp_writer.write(json.dumps(message).encode('utf-8'))
await tcp_writer.drain()
except asyncio.TimeoutError:
logger.warning(f"WebSocket connection timed out: {websocket.client}")
except WebSocketDisconnect:
logger.info(f"WebSocket disconnected: {websocket.client}")
except Exception as e:
logger.error(f"WebSocket exception: {e}")
finally:
manager.disconnect(websocket)
tcp_writer.close()
await tcp_writer.wait_closed()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await handle_websocket(websocket)
async def start_phd2():
logger.info("Starting PHD2 process...")
process = await asyncio.create_subprocess_exec(
'phd2', '--server', 'localhost:4400',
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
logger.info(f"PHD2 started with PID: {process.pid}")
return process
async def monitor_phd2(process):
try:
while True:
return_code = await process.wait()
if return_code is not None:
logger.error(f"PHD2 process exited with code {return_code}. Restarting...")
process = await start_phd2()
await asyncio.sleep(5)
except asyncio.CancelledError:
process.terminate()
await process.wait()
logger.info("PHD2 process terminated.")
@app.on_event("startup")
async def startup_event():
global phd2_process
phd2_process = await start_phd2()
asyncio.ensure_future(monitor_phd2(phd2_process))
@app.on_event("shutdown")
async def shutdown_event():
global phd2_process
phd2_process.terminate()
await phd2_process.wait()
logger.info("PHD2 process terminated on shutdown.")
@app.get("/phd2/status")
async def get_phd2_status(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
global phd2_process
if phd2_process is None or phd2_process.returncode is not None:
raise HTTPException(status_code=503, detail="PHD2 is not running")
# 这里可以添加更多PHD2内部状态的获取逻辑
return {"status": "running", "pid": phd2_process.pid}
@app.post("/phd2/start")
async def start_phd2_endpoint(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
global phd2_process
if phd2_process is not None and phd2_process.returncode is None:
raise HTTPException(status_code=400, detail="PHD2 is already running")
phd2_process = await start_phd2()
asyncio.ensure_future(monitor_phd2(phd2_process))
return {"status": "started", "pid": phd2_process.pid}
@app.post("/phd2/stop")
async def stop_phd2_endpoint(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
global phd2_process
if phd2_process is None or phd2_process.returncode is not None:
raise HTTPException(status_code=400, detail="PHD2 is not running")
phd2_process.terminate()
await phd2_process.wait()
return {"status": "stopped"}
@app.post("/phd2/restart")
async def restart_phd2_endpoint(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
global phd2_process
if phd2_process is not None and phd2_process.returncode is None:
phd2_process.terminate()
await phd2_process.wait()
phd2_process = await start_phd2()
asyncio.ensure_future(monitor_phd2(phd2_process))
return {"status": "restarted", "pid": phd2_process.pid}
@app.get("/logs")
async def get_logs(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
return FileResponse("server.log")
@app.post("/phd2/config")
async def set_phd2_config(config: dict, credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
with open("phd2_config.json", "w") as f:
json.dump(config, f)
return {"status": "config updated"}
@app.get("/phd2/config")
async def get_phd2_config(credentials: HTTPBasicCredentials = Depends(security)):
verify_credentials(credentials)
try:
with open("phd2_config.json", "r") as f:
config = json.load(f)
return config
except FileNotFoundError:
raise HTTPException(status_code=404, detail="Config file not found")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000) |
Beta Was this translation helpful? Give feedback.
-
ini与json的相互转化 import configparser
import json
from typing import Dict, Any
def ini_to_dict(ini_file: str) -> Dict[str, Any]:
config = configparser.ConfigParser()
config.read(ini_file)
return {section: dict(config.items(section)) for section in config.sections()}
def dict_to_ini(data: Dict[str, Any], ini_file: str):
config = configparser.ConfigParser()
for section, params in data.items():
config[section] = params
with open(ini_file, 'w') as file:
config.write(file)
def json_to_dict(json_file: str) -> Dict[str, Any]:
with open(json_file, 'r') as file:
return json.load(file)
def dict_to_json(data: Dict[str, Any], json_file: str):
with open(json_file, 'w') as file:
json.dump(data, file, indent=4)
def ini_to_json(ini_file: str, json_file: str):
data = ini_to_dict(ini_file)
dict_to_json(data, json_file)
def json_to_ini(json_file: str, ini_file: str):
data = json_to_dict(json_file)
dict_to_ini(data, ini_file)
# 示例用法
ini_to_json('example.ini', 'example_converted.json')
json_to_ini('example.json', 'example_converted.ini') |
Beta Was this translation helpful? Give feedback.
-
components/SearchBar.vue <template>
<n-input v-model:value="searchQuery" placeholder="Search..." clearable @clear="onClear" @input="onInput" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'SearchBar',
props: {
searchQuery: {
type: String,
required: true
}
},
emits: ['update:searchQuery'],
methods: {
onClear() {
this.$emit('update:searchQuery', '');
},
onInput(value: string) {
this.$emit('update:searchQuery', value);
}
}
});
</script> components/GroupMenu.vue <template>
<n-menu :options="groupOptions" @update:value="onSelectGroup" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { MenuOption } from 'naive-ui';
export default defineComponent({
name: 'GroupMenu',
props: {
groupOptions: {
type: Array as () => MenuOption[],
required: true
},
selectedGroup: {
type: String,
default: null
}
},
emits: ['update:selectedGroup'],
methods: {
onSelectGroup(key: string) {
this.$emit('update:selectedGroup', key);
}
}
});
</script> components/ConfigTable.vue
components/ConfigModal.vue <template>
<n-modal v-model:show="visible" title="Detail" size="large">
<n-form :model="config" ref="formRef">
<n-form-item label="Key">
<n-input v-model:value="config.key" :readonly="isReadOnly" />
</n-form-item>
<n-form-item label="Value">
<n-input v-model:value="config.value" />
</n-form-item>
<n-form-item label="Description">
<n-input v-model:value="config.description" type="textarea" />
</n-form-item>
</n-form>
<template #footer>
<n-button @click="$emit('update:visible', false)">Close</n-button>
<n-button type="primary" @click="onSave">Save</n-button>
</template>
</n-modal>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
interface ConfigItem {
group: string;
key: string;
value: string;
description: string;
}
export default defineComponent({
name: 'ConfigModal',
props: {
visible: {
type: Boolean,
required: true
},
config: {
type: Object as PropType<ConfigItem>,
required: true
},
isReadOnly: {
type: Boolean,
default: true
}
},
emits: ['update:visible', 'save'],
methods: {
onSave() {
this.$emit('save', { ...this.config });
}
}
});
</script> App.vue <template>
<n-layout>
<n-layout-header>
<search-bar v-model:searchQuery="searchQuery" />
</n-layout-header>
<n-layout>
<n-layout-sider>
<group-menu :groupOptions="groupOptions" v-model:selectedGroup="selectedGroup" />
</n-layout-sider>
<n-layout-content>
<n-card>
<n-button type="success" @click="addNewConfig">Add New</n-button>
<n-button type="warning" @click="exportConfig">Export</n-button>
<n-upload :on-change="importConfig" accept=".json">
<n-button type="info">Import</n-button>
</n-upload>
<config-table :data="filteredData" @row-click="showDetailModal" @delete="deleteConfig">
<template #action="{ row }">
<n-button type="error" @click.stop="deleteConfig(row)">Delete</n-button>
</template>
</config-table>
<config-modal v-model:visible="detailModalVisible" :config="selectedConfig" :isReadOnly="isReadOnly" @save="saveConfig" />
</n-card>
</n-layout-content>
</n-layout>
</n-layout>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, computed } from 'vue';
import { useMessage } from 'naive-ui';
import SearchBar from './components/SearchBar.vue';
import GroupMenu from './components/GroupMenu.vue';
import ConfigTable from './components/ConfigTable.vue';
import ConfigModal from './components/ConfigModal.vue';
interface ConfigItem {
group: string;
key: string;
value: string;
description: string;
}
export default defineComponent({
name: 'App',
components: { SearchBar, GroupMenu, ConfigTable, ConfigModal },
setup() {
const message = useMessage();
// Sample data
const configData = reactive<ConfigItem[]>([
{ group: 'Group 1', key: 'Key1', value: 'Value1', description: 'Description for Key1' },
{ group: 'Group 1', key: 'Key2', value: 'Value2', description: 'Description for Key2' },
{ group: 'Group 2', key: 'Key3', value: 'Value3', description: 'Description for Key3' },
{ group: 'Group 2', key: 'Key4', value: 'Value4', description: 'Description for Key4' }
]);
const searchQuery = ref('');
const selectedGroup = ref<string | null>(null);
const detailModalVisible = ref(false);
const selectedConfig = reactive<Partial<ConfigItem>>({});
const isReadOnly = ref(true);
const groupOptions = computed(() => {
const groups = [...new Set(configData.map(item => item.group))];
return groups.map(group => ({ label: group, key: group }));
});
const filteredData = computed(() => {
return configData.filter(item => {
const matchesGroup = selectedGroup.value ? item.group === selectedGroup.value : true;
const matchesQuery = item.key.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
item.value.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
item.description.toLowerCase().includes(searchQuery.value.toLowerCase());
return matchesGroup && matchesQuery;
});
});
const fetchConfigData = () => {
// Fetch and update configData here based on searchQuery and selectedGroup
};
const selectGroup = (key: string) => {
selectedGroup.value = key;
fetchConfigData();
};
const showDetailModal = (row: ConfigItem) => {
Object.assign(selectedConfig, row);
detailModalVisible.value = true;
isReadOnly.value = true;
};
const addNewConfig = () => {
Object.assign(selectedConfig, { group: selectedGroup.value, key: '', value: '', description: '' });
detailModalVisible.value = true;
isReadOnly.value = false;
};
const saveConfig = (config: ConfigItem) => {
const index = configData.findIndex(item => item.key === config.key);
if (index !== -1) {
Object.assign(configData[index], config);
} else {
configData.push(config);
}
message.success('Configuration saved successfully');
detailModalVisible.value = false;
};
const deleteConfig = (row: ConfigItem) => {
const index = configData.findIndex(item => item.key === row.key);
if (index !== -1) {
configData.splice(index, 1);
message.success('Configuration deleted successfully');
}
};
const exportConfig = () => {
const dataStr = JSON.stringify(configData, null, 2);
const blob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'config.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
const importConfig = (file: File) => {
const reader = new FileReader();
reader.onload = (event: ProgressEvent<FileReader>) => {
if (event.target && event.target.result) {
const data = JSON.parse(event.target.result as string);
data.forEach((item: ConfigItem) => {
const index = configData.findIndex(existingItem => existingItem.key === item.key);
if (index !== -1) {
Object.assign(configData[index], item);
} else {
configData.push(item);
}
});
message.success('Configuration imported successfully');
}
};
reader.readAsText(file);
};
return {
searchQuery,
groupOptions,
selectedGroup,
columns,
filteredData,
detailModalVisible,
selectedConfig,
isReadOnly,
fetchConfigData,
selectGroup,
showDetailModal,
addNewConfig,
saveConfig,
deleteConfig,
exportConfig,
importConfig
};
}
});
</script>
<style>
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
</style> |
Beta Was this translation helpful? Give feedback.
-
INDIWebClone <template>
<n-layout-header class="header">
<n-space align="center" justify="space-between" style="width: 100%">
<n-space align="center">
<n-avatar size="medium" src="https://via.placeholder.com/40" />
<n-h1>INDIWeb Clone</n-h1>
</n-space>
<n-space>
<n-button type="primary">Login</n-button>
</n-space>
</n-space>
</n-layout-header>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Header'
});
</script>
<style scoped>
.header {
background-color: #3eaf7c;
color: white;
padding: 0 20px;
}
</style> components/Sidebar.vue <template>
<n-layout-sider bordered class="sidebar">
<n-menu :options="menuOptions" @update:value="onSelect" />
</n-layout-sider>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Sidebar',
emits: ['select'],
data() {
return {
menuOptions: [
{ label: 'All Devices', key: 'all' },
{ label: 'Category 1', key: 'category1', children: [
{ label: 'Device 1', key: 'device1' },
{ label: 'Device 2', key: 'device2' }
]
},
{ label: 'Category 2', key: 'category2', children: [
{ label: 'Device 3', key: 'device3' },
{ label: 'Device 4', key: 'device4' }
]
}
]
};
},
methods: {
onSelect(key: string) {
this.$emit('select', key);
}
}
});
</script>
<style scoped>
.sidebar {
background-color: #f0f0f0;
padding: 20px;
}
</style> components/DeviceList.vue <template>
<n-card title="Device List" class="device-list">
<n-list :bordered="false">
<n-list-item v-for="device in devices" :key="device.id" @click="onSelect(device)">
<n-avatar :src="device.icon" size="small" />
<span>{{ device.name }}</span>
</n-list-item>
</n-list>
</n-card>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'DeviceList',
props: {
devices: {
type: Array,
required: true
}
},
emits: ['select'],
methods: {
onSelect(device: any) {
this.$emit('select', device);
}
}
});
</script>
<style scoped>
.device-list {
margin: 20px;
}
</style> components/DeviceControl.vue <template>
<n-card v-if="device" title="Device Control" class="device-control">
<n-form :model="deviceData" ref="formRef">
<n-form-item label="Property 1">
<n-input v-model:value="deviceData.property1" />
</n-form-item>
<n-form-item label="Property 2">
<n-input v-model:value="deviceData.property2" />
</n-form-item>
<n-form-item label="Property 3">
<n-input v-model:value="deviceData.property3" />
</n-form-item>
<n-form-item>
<n-button type="primary" @click="saveDevice">Save</n-button>
</n-form-item>
</n-form>
</n-card>
<div v-else class="no-device">
<n-empty description="No device selected." />
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, watch } from 'vue';
export default defineComponent({
name: 'DeviceControl',
props: {
device: {
type: Object,
default: null
}
},
setup(props) {
const deviceData = reactive({
property1: '',
property2: '',
property3: ''
});
watch(() => props.device, (newDevice) => {
if (newDevice) {
deviceData.property1 = newDevice.property1;
deviceData.property2 = newDevice.property2;
deviceData.property3 = newDevice.property3;
}
}, { immediate: true });
const saveDevice = () => {
console.log('Device data saved:', deviceData);
// Here you can save the device data to the backend or perform any other action
};
return {
deviceData,
saveDevice
};
}
});
</script>
<style scoped>
.device-control {
margin: 20px;
}
.no-device {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
</style> components/AddDeviceModal.vue <template>
<n-modal v-model:show="visible" title="Add Device" size="large">
<n-form :model="deviceData" ref="formRef">
<n-form-item label="Name">
<n-input v-model:value="deviceData.name" />
</n-form-item>
<n-form-item label="Category">
<n-select v-model:value="deviceData.category" :options="categoryOptions" />
</n-form-item>
<n-form-item label="Property 1">
<n-input v-model:value="deviceData.property1" />
</n-form-item>
<n-form-item label="Property 2">
<n-input v-model:value="deviceData.property2" />
</n-form-item>
<n-form-item label="Property 3">
<n-input v-model:value="deviceData.property3" />
</n-form-item>
<n-form-item>
<n-button type="primary" @click="addDevice">Add</n-button>
</n-form-item>
</n-form>
</n-modal>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
export default defineComponent({
name: 'AddDeviceModal',
props: {
visible: {
type: Boolean,
required: true
},
categories: {
type: Array,
required: true
}
},
emits: ['update:visible', 'add'],
setup(props) {
const deviceData = reactive({
name: '',
category: '',
property1: '',
property2: '',
property3: ''
});
const addDevice = () => {
if (!deviceData.name || !deviceData.category) {
alert('Please fill out all required fields.');
return;
}
console.log('Adding device:', deviceData);
props.$emit('add', { ...deviceData });
props.$emit('update:visible', false);
};
const categoryOptions = props.categories.map(category => ({ label: category, value: category }));
return {
deviceData,
addDevice,
categoryOptions
};
}
});
</script> App.vue <template>
<n-layout>
<Header />
<n-layout has-sider>
<Sidebar @select="selectDevice" />
<n-layout-content>
<n-card title="Devices">
<n-button type="success" @click="showAddDeviceModal">Add Device</n-button>
<DeviceList :devices="filteredDevices" @select="selectDevice" />
</n-card>
<DeviceControl :device="selectedDevice" />
<AddDeviceModal v-model:visible="addDeviceModalVisible" :categories="categories" @add="addDevice" />
</n-layout-content>
</n-layout>
</n-layout>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import Header from './components/Header.vue';
import Sidebar from './components/Sidebar.vue';
import DeviceList from './components/DeviceList.vue';
import DeviceControl from './components/DeviceControl.vue';
import AddDeviceModal from './components/AddDeviceModal.vue';
interface Device {
id: string;
name: string;
icon: string;
category: string;
property1: string;
property2: string;
property3: string;
}
export default defineComponent({
name: 'App',
components: { Header, Sidebar, DeviceList, DeviceControl, AddDeviceModal },
setup() {
const devices = ref<Device[]>([
{ id: '1', name: 'Device 1', icon: 'https://via.placeholder.com/40', category: 'Category 1', property1: 'value1', property2: 'value2', property3: 'value3' },
{ id: '2', name: 'Device 2', icon: 'https://via.placeholder.com/40', category: 'Category 1', property1: 'value1', property2: 'value2', property3: 'value3' },
{ id: '3', name: 'Device 3', icon: 'https://via.placeholder.com/40', category: 'Category 2', property1: 'value1', property2: 'value2', property3: 'value3' },
{ id: '4', name: 'Device 4', icon: 'https://via.placeholder.com/40', category: 'Category 2', property1: 'value1', property2: 'value2', property3: 'value3' }
]);
const selectedDevice = ref<Device | null>(null);
const selectedCategory = ref<string>('all');
const addDeviceModalVisible = ref(false);
const categories = ref<string[]>(['Category 1', 'Category 2']);
const filteredDevices = computed(() => {
if (selectedCategory.value === 'all') {
return devices.value;
}
return devices.value.filter(device => device.category === selectedCategory.value);
});
const selectDevice = (device: Device) => {
selectedDevice.value = device;
};
const showAddDeviceModal = () => {
addDeviceModalVisible.value = true;
};
const addDevice = (device: Device) => {
device.id = String(devices.value.length + 1);
devices.value.push(device);
if (!categories.value.includes(device.category)) {
categories.value.push(device.category);
}
};
return {
devices,
selectedDevice,
selectedCategory,
addDeviceModalVisible,
categories,
filteredDevices,
selectDevice,
showAddDeviceModal,
addDevice
};
}
});
</script>
<style>
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
</style> |
Beta Was this translation helpful? Give feedback.
-
LogPanel components/Header.vue <template>
<n-layout-header class="header">
<n-space align="center" justify="space-between" style="width: 100%">
<n-space align="center">
<n-h1>Log Dashboard</n-h1>
</n-space>
<n-space>
<n-select v-model:value="selectedLevel" :options="levelOptions" placeholder="Select Level" clearable />
<n-input v-model:value="filterText" placeholder="Filter logs..." clearable @clear="onClear" @input="onInput" />
</n-space>
</n-space>
</n-layout-header>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Header',
props: {
filterText: {
type: String,
required: true
},
selectedLevel: {
type: String,
required: true
}
},
emits: ['update:filterText', 'update:selectedLevel'],
data() {
return {
levelOptions: [
{ label: 'INFO', value: 'INFO' },
{ label: 'WARN', value: 'WARN' },
{ label: 'ERROR', value: 'ERROR' }
]
};
},
methods: {
onClear() {
this.$emit('update:filterText', '');
},
onInput(value: string) {
this.$emit('update:filterText', value);
}
}
});
</script>
<style scoped>
.header {
background-color: #3eaf7c;
color: white;
padding: 0 20px;
}
</style> components/LogTable.vue <template>
<n-card title="Logs" class="log-table">
<n-data-table :columns="columns" :data="filteredLogs" />
</n-card>
</template>
<script lang="ts">
import { defineComponent, computed, h, TransitionGroup } from 'vue';
import { DataTableColumn } from 'naive-ui';
import { LogEntry } from '@/types';
export default defineComponent({
name: 'LogTable',
props: {
logs: {
type: Array as () => LogEntry[],
required: true
},
filterText: {
type: String,
required: true
},
selectedLevel: {
type: String,
required: true
}
},
emits: ['copy-log'],
setup(props, { emit }) {
const columns = computed<DataTableColumn[]>(() => [
{
title: 'Timestamp',
key: 'timestamp',
align: 'center'
},
{
title: 'Level',
key: 'level',
align: 'center'
},
{
title: 'Message',
key: 'message',
align: 'left',
render(rowData) {
const highlightText = (text: string, highlight: string) => {
if (!highlight) return text;
const regex = new RegExp(`(${highlight})`, 'gi');
return text.replace(regex, '<mark>$1</mark>');
};
return h('div', { innerHTML: highlightText(rowData.message, props.filterText) });
}
},
{
title: 'Action',
key: 'action',
align: 'center',
render(rowData) {
return h(
'div',
[
h('n-button', {
text: true,
onClick: () => {
navigator.clipboard.writeText(rowData.message);
emit('copy-log', rowData.message);
}
}, 'Copy')
]
);
}
}
]);
const filteredLogs = computed(() => {
return props.logs.filter(log => {
const matchesLevel = props.selectedLevel ? log.level === props.selectedLevel : true;
const matchesText = props.filterText ? log.message.toLowerCase().includes(props.filterText.toLowerCase()) : true;
return matchesLevel && matchesText;
});
});
return {
columns,
filteredLogs
};
}
});
</script>
<style scoped>
.log-table {
margin: 20px;
}
</style> App.vue <template>
<n-layout>
<Header v-model:filterText="filterText" v-model:selectedLevel="selectedLevel" />
<n-layout-content>
<LogTable :logs="logs" :filterText="filterText" :selectedLevel="selectedLevel" @copy-log="onCopyLog" />
</n-layout-content>
</n-layout>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
import Header from './components/Header.vue';
import LogTable from './components/LogTable.vue';
import { LogEntry } from '@/types';
export default defineComponent({
name: 'App',
components: { Header, LogTable },
setup() {
const filterText = ref<string>('');
const selectedLevel = ref<string>('');
const logs = ref<LogEntry[]>([
{ timestamp: '2023-06-01 12:00:00', level: 'INFO', message: 'System started successfully' },
{ timestamp: '2023-06-01 12:05:00', level: 'WARN', message: 'Low disk space' },
{ timestamp: '2023-06-01 12:10:00', level: 'ERROR', message: 'Failed to connect to database' },
// ... more logs
]);
const fetchLogs = () => {
// Fetch logs from server and update `logs` state
// This is a placeholder implementation
logs.value.push({ timestamp: new Date().toISOString(), level: 'INFO', message: 'New log entry' });
};
const onCopyLog = (message: string) => {
console.log(`Log copied: ${message}`);
};
let intervalId: number;
onMounted(() => {
intervalId = setInterval(fetchLogs, 5000); // Auto-refresh every 5 seconds
});
onUnmounted(() => {
clearInterval(intervalId);
});
return {
filterText,
selectedLevel,
logs,
onCopyLog
};
}
});
</script>
<style>
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
</style> |
Beta Was this translation helpful? Give feedback.
-
#include enum class ScopeGuardStrategy { template <typename Func, ScopeGuardStrategy Strategy = ScopeGuardStrategy::Always> public:
private: template template template template |
Beta Was this translation helpful? Give feedback.
-
#include class FocusStrategy { class HillClimbingStrategy : public FocusStrategy {
}; class BinarySearchStrategy : public FocusStrategy {
}; class AutoFocus { public:
}; // 模拟从相机获取对焦评分 int main() {
} |
Beta Was this translation helpful? Give feedback.
-
这里是一些开发时的想法或者代码片段,仅仅作为心路历程的记录
Beta Was this translation helpful? Give feedback.
All reactions