“如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》
“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》
“维持现状意味着空耗你的努力和生命。”——纪伯伦
第六节 托盘、请求完善
一. 简介
在上面的章节我们完成了 窗口和请求 功能的实现,本章节我们将对系统现有的代码进行修改,以实现完整的功能。
二. 托盘完善
打开项目中 “tary.rs”文件,我们在之前介绍了如何创建和定义托盘菜单,但在实现部分并没有实现它,下面我们来看看它的具体功能和如何实现它。
1. 点击事件
点击托盘图标时,我们希望展示应用界面到桌面最前面,它的逻辑在:on_tray_icon_event 实现处理,它接收2各参数,
-
TrayIcon
id: TrayIconId,inner: tray_icon::TrayIcon,app_handle: AppHandle<R>,
-
TrayIconEvent
实现思路:点击托盘图标,获取Tauri的主窗口,并显示它。
实现代码如下:
let main_win=tray.app_handle().get_webview_window("main").unwrap();main_win.show().unwrap();main_win.unminimize().unwrap();main_win.set_focus().unwrap();
2. 显示事件
显示事件和点击事件的实现思路一致, 这里提供另外一种代码:
...."show" => {for (key, value) in app.webview_windows() {if key == "main" {value.show().unwrap();}}
}
....
3. 退出事件
"quit" => {app.exit(0);
}
调用app.exit api 就可以
4. 完整代码如下:
use tauri::{menu::{Menu, MenuItem, Submenu},tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},Manager, Runtime,
};pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {let quit_i = MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?;let set_i = MenuItem::with_id(app, "set", "设置", true, None::<&str>)?;let show_i = MenuItem::with_id(app, "show", "显示窗口", true, None::<&str>)?;// 分割线let menu = Menu::with_items(app, &[&show_i, &set_i, &quit_i])?;let _ = TrayIconBuilder::with_id("tray").icon(app.default_window_icon().unwrap().clone()).menu(&menu).on_menu_event(move |app, event| match event.id.as_ref() {"show" => {for (key, value) in app.webview_windows() {if key == "main" {value.show().unwrap();}}}"set" => {println!("set");}"quit" => {app.exit(0);}// Add more events here_ => {}}).on_tray_icon_event(|tray, event: TrayIconEvent| {if let TrayIconEvent::Click {button: MouseButton::Left,button_state: MouseButtonState::Up,..} = event{let main_win=tray.app_handle().get_webview_window("main").unwrap();main_win.show().unwrap();main_win.unminimize().unwrap();main_win.set_focus().unwrap();}}).build(app);Ok(())
}
三 . 页面HTTP接口改造
1. 修改 Api hook 增加请求前缀
const res = await fetch(“http://localhost:8080” + url, options);
“http://localhost:8080” 为你的实际服务地址
这里要注意先修改权限配置如下:
{"identifier": "http:default","allow": [{"url": "http://**"},{"url": "https://**"},{"url": "http://*:*"},{"url": "https://*:*"}],"deny": [{"url": "https://private.tauri.app"}]},
2. 页面代码完善后如下
<template><el-container><el-header><el-col :span="8"><el-input v-model="queryInput" placeholder="请输入姓名搜索" /></el-col><div><el-button type="primary" @click="handleAdd">增加</el-button><el-buttontype="danger"@click="handleListDel"v-if="multipleSelection.length > 0">删除</el-button></div></el-header><el-main><el-table:data="tableData"style="width: 100%; height: 100%"borderali@selection-change="handleSelectionChange"ref="multipleTableRef"><el-table-column align="center" type="index" label="Xh" width="55" /><el-table-columnalign="center"prop="type"label="紧急情况":formatter="(row, column, cellValue, index) => {if (cellValue === 1) {return '急';} else if (cellValue === 2) {return '紧急';}return '一般';}"width="90"/><el-table-columnalign="left"header-align="center"prop="title"label="标题"width="200"/><el-table-columnalign="center"prop="name"label="联系人"width="100"/><el-table-columnalign="center"prop="time"label="截止时间"width="180"/><el-table-columnalign="center"prop="state":formatter="(row, column, cellValue, index) => {if (cellValue === 1) {return '未完成';}return '已完成';}"label="状态"width="120"/><el-table-column align="center" fixed="right" label="操作" width="120"><template #default="scope"><!-- <el-buttonlinktype="danger"size="small"@click="handleRowDel(scope.row.id)">删除</el-button> --><el-buttonlinktype="primary"size="small"@click="handleEdit(scope.row)">编辑</el-button></template></el-table-column></el-table><!--dialog 弹窗--><el-dialogv-model="dialogFormVisible":title="dialogType === 'add' ? '新增' : '编辑'"><el-form :model="tableForm" label-width="auto"><el-form-item label="紧急情况"><el-selectv-model="tableForm.type":disabled="dialogType !== 'add'"placeholder="紧急情况"><el-option label="一般" :value="0" /><el-option label="急" :value="1" /><el-option label="紧急" :value="2" /></el-select></el-form-item><el-form-item label="标题"><el-inputv-model="tableForm.title":disabled="dialogType !== 'add'"autocomplete="off"/></el-form-item><el-form-item label="联系人"><el-inputv-model="tableForm.name":disabled="dialogType !== 'add'"autocomplete="off"/></el-form-item><el-form-item label="截止时间"><el-date-pickerv-model="tableForm.time":disabled="dialogType !== 'add'"type="datetime"placeholder="截止时间"/></el-form-item><el-form-item label="状态"><el-selectv-model="tableForm.state"autocomplete="off"placeholder="状态"><el-option label="未完成" :value="0" /><el-option label="已完成" :value="1" /></el-select></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button type="primary" @click="dialogConfirm">确认</el-button></span></template></el-dialog></el-main></el-container>
</template><script setup>
import { ref, watch, onMounted, computed } from "vue";
import useApi from "../../tauri/hooks/api";import {isPermissionGranted,requestPermission,sendNotification,
} from "@tauri-apps/plugin-notification";const api = useApi();
//数据
const queryInput = ref("");
const tableData = ref([]);
let tableDataCopy = computed(() => tableData.value);
const multipleSelection = ref([]); //多选
const dialogFormVisible = ref(false); //是否打开
const formLabelWidth = "80px"; //弹出框 标题长度
const tableForm = ref({});
const dialogType = ref("add");
//监控数据
watch(queryInput, (val) => {if (val.length > 0) {tableData.value = tableData.value.filter((item) =>item.title.toLowerCase().match(val.toLowerCase()));} else {loadPageData();}
});
//选择事件
const handleSelectionChange = (val) => {multipleSelection.value = [];val.forEach((item) => {multipleSelection.value.push(item.id);});
};
//添加按钮
const handleAdd = (val) => {tableForm.value = {};dialogType.value = "add";dialogFormVisible.value = true;
};
//编辑按钮
const handleEdit = (val) => {tableForm.value = val;dialogType.value = "edit";dialogFormVisible.value = true;
};//删除一条按钮
const handleRowDel = (id) => {console.log(id);let index = tableData.value.findIndex((item) => item.id === id);tableData.value.splice(index, 1);
};//删除多条
const handleListDel = () => {multipleSelection.value.forEach((id) => {handleRowDel(id);});multipleSelection.value = [];
};//确认按钮
const dialogConfirm = () => {if (dialogType.value === "add") {api.send("/task/addTask", "POST", tableForm.value).then((res) => {if (res) {loadPageData();}});// tableData.value.push({// id: tableData.value.length + 1,// ...tableForm.value,// });} else {api.send("/task/updateTask", "PATCH", tableForm.value).then((res) => {if (res) {loadPageData();}});// let index = tableData.value.findIndex((item) => item.id === tableForm.id);// tableData[index] = tableForm;}dialogFormVisible.value = false;
};const loadPageData = (not = false) => {api.send("/task/queryTask", "GET").then(async (res) => {tableData.value = res;});
};onMounted(() => {loadPageData(true);
});
</script><style lang="scss" scoped>
.el-container {width: 100%;height: 100%;padding: 10px;background-color: #f0f2f5;.el-header {background-color: #b3c0d1;color: #333;line-height: 60px;display: flex;justify-content: space-between;margin-bottom: 10px;}.el-main {background-color: #b3c0d1;color: #333;text-align: center;padding: 10px;}
}
</style>
四 代码仓库
项目仓库:https://gitee.com/Elcker/tv_task.git