feat(device): 新增开发者模式指令及下拉菜单样式优化
新增推送开发者模式指令到设备的 API。 优化设备页面表格工具栏更多按钮的下拉菜单: - 点击触发并支持点击菜单项后自动隐藏 - 移除触发按钮 hover 时的背景色 - 调整下拉菜单项的布局、间距与圆角样式
This commit is contained in:
340
src/views/devices/developer/index.vue
Normal file
340
src/views/devices/developer/index.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<el-card class="page-search" shadow="never">
|
||||
<el-form ref="queryFormRef" :model="params" :inline="true">
|
||||
<el-form-item label="设备序列号" prop="keywords">
|
||||
<el-input
|
||||
v-model="params.keywords"
|
||||
placeholder="请输入设备序列号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开关状态" prop="developerOptions">
|
||||
<el-select
|
||||
v-model="params.developerOptions"
|
||||
placeholder="全部"
|
||||
clearable
|
||||
style="width: 140px"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option label="已开启" :value="1" />
|
||||
<el-option label="已关闭" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="handleResetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card ref="tableWrapperRef" class="page-content" shadow="never">
|
||||
<div class="page-toolbar">
|
||||
<div class="page-toolbar__left">
|
||||
<el-button v-hasPerm="['device:developer:create']" type="primary" @click="openDialog()">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPerm="['device:developer:delete']"
|
||||
type="danger"
|
||||
:disabled="selectIds.length === 0"
|
||||
@click="handleDelete()"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="page-toolbar__right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button class="page-icon-btn" @click="handleQuery">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="全屏" placement="top">
|
||||
<el-button class="page-icon-btn" @click="toggleFullscreen">
|
||||
<el-icon><FullScreen /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-table-wrapper">
|
||||
<el-table
|
||||
ref="dataTableRef"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
class="page-table"
|
||||
height="100%"
|
||||
highlight-current-row
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column key="sn" label="设备序列号" prop="sn" min-width="180" />
|
||||
<el-table-column key="developerOptions" label="开发者选项" width="140" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
:model-value="scope.row.developerOptions === 1"
|
||||
:loading="switchLoadingSn === scope.row.sn"
|
||||
:disabled="!hasSwitchPerm"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
@change="
|
||||
(val: string | number | boolean) =>
|
||||
handleSwitchChange(scope.row as DeveloperItem, Boolean(val))
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column key="createTime" label="创建时间" prop="createTime" min-width="160" />
|
||||
<el-table-column key="updateTime" label="更新时间" prop="updateTime" min-width="160" />
|
||||
<el-table-column fixed="right" label="操作" width="240">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-hasPerm="['device:developer:push']"
|
||||
type="success"
|
||||
size="small"
|
||||
link
|
||||
@click="handlePush(scope.row.sn)"
|
||||
>
|
||||
推送设备
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPerm="['device:developer:update']"
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="openDialog(scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPerm="['device:developer:delete']"
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="handleDelete(scope.row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<pagination
|
||||
v-if="total > 0"
|
||||
v-model:total="total"
|
||||
v-model:page="params.pageNum"
|
||||
v-model:limit="params.pageSize"
|
||||
@pagination="fetchData"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogState.visible"
|
||||
:title="dialogState.title"
|
||||
width="500px"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<el-form
|
||||
ref="dataFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-suffix=":"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="设备序列号" prop="sn">
|
||||
<el-input
|
||||
v-model="formData.sn"
|
||||
placeholder="请输入设备序列号"
|
||||
:maxlength="64"
|
||||
:disabled="!!formData.id"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发者选项" prop="developerOptions">
|
||||
<el-radio-group v-model="formData.developerOptions">
|
||||
<el-radio :value="1">开启</el-radio>
|
||||
<el-radio :value="0">关闭</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from "element-plus";
|
||||
import { Refresh, FullScreen } from "@element-plus/icons-vue";
|
||||
|
||||
import DeveloperAPI from "@/api/system/developer";
|
||||
import type { DeveloperItem, DeveloperForm, DeveloperQueryParams } from "@/api/system/developer";
|
||||
import { usePageTable } from "@/composables";
|
||||
import { hasPerm } from "@/utils/auth";
|
||||
|
||||
defineOptions({
|
||||
name: "Developer",
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const tableWrapperRef = ref<HTMLElement | null>(null);
|
||||
const { toggle: toggleFullscreen } = useFullscreen(tableWrapperRef);
|
||||
|
||||
const queryFormRef = ref<FormInstance>();
|
||||
const dataFormRef = ref<FormInstance>();
|
||||
|
||||
/** 分页表格数据管理 */
|
||||
const { loading, list, total, params, fetchData, handleQuery, handleResetQuery } = usePageTable<
|
||||
DeveloperItem,
|
||||
DeveloperQueryParams
|
||||
>({
|
||||
initialParams: { pageNum: 1, pageSize: 10, keywords: "", developerOptions: undefined },
|
||||
request: DeveloperAPI.getPage,
|
||||
onBeforeReset: () => queryFormRef.value?.resetFields(),
|
||||
});
|
||||
|
||||
const selectIds = ref<string[]>([]);
|
||||
const switchLoadingSn = ref<string>("");
|
||||
|
||||
/** 是否拥有开关快捷切换权限 */
|
||||
const hasSwitchPerm = computed(() => hasPerm("device:developer:update"));
|
||||
|
||||
const dialogState = reactive({ title: "", visible: false });
|
||||
|
||||
const formData = reactive<DeveloperForm>({
|
||||
id: undefined,
|
||||
sn: "",
|
||||
developerOptions: 0,
|
||||
});
|
||||
|
||||
const rules: FormRules = {
|
||||
sn: [{ required: true, message: "请输入设备序列号", trigger: "blur" }],
|
||||
developerOptions: [{ required: true, message: "请选择开发者选项开关", trigger: "change" }],
|
||||
};
|
||||
|
||||
function handleSelectionChange(selection: DeveloperItem[]): void {
|
||||
selectIds.value = selection.map((item) => item.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开新增/编辑开发者选项弹窗
|
||||
*/
|
||||
async function openDialog(id?: string): Promise<void> {
|
||||
dialogState.visible = true;
|
||||
if (id) {
|
||||
dialogState.title = "修改开发者选项";
|
||||
const data = await DeveloperAPI.getFormData(id);
|
||||
Object.assign(formData, data);
|
||||
} else {
|
||||
dialogState.title = "新增开发者选项";
|
||||
formData.id = undefined;
|
||||
formData.sn = "";
|
||||
formData.developerOptions = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格内快捷切换开发者选项开关
|
||||
*/
|
||||
async function handleSwitchChange(row: DeveloperItem, checked: boolean): Promise<void> {
|
||||
switchLoadingSn.value = row.sn;
|
||||
try {
|
||||
await DeveloperAPI.saveOrUpdateBySn(row.sn, checked ? 1 : 0);
|
||||
row.developerOptions = checked ? 1 : 0;
|
||||
ElMessage.success(checked ? "已开启开发者选项" : "已关闭开发者选项");
|
||||
} finally {
|
||||
switchLoadingSn.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送开发者模式指令到设备
|
||||
*/
|
||||
async function handlePush(sn: string): Promise<void> {
|
||||
await ElMessageBox.confirm(`确认向设备【${sn}】推送开发者模式指令?`, "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
});
|
||||
loading.value = true;
|
||||
try {
|
||||
await DeveloperAPI.pushBySn(sn);
|
||||
ElMessage.success("推送成功");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并提交开发者选项表单
|
||||
*/
|
||||
async function handleSubmit(): Promise<void> {
|
||||
const valid = await dataFormRef.value?.validate().catch(() => false);
|
||||
if (!valid) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const id = formData.id;
|
||||
if (id) {
|
||||
await DeveloperAPI.update(id, formData);
|
||||
ElMessage.success("修改成功");
|
||||
} else {
|
||||
await DeveloperAPI.create(formData);
|
||||
ElMessage.success("新增成功");
|
||||
}
|
||||
closeDialog();
|
||||
handleResetQuery();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭弹窗并重置表单
|
||||
*/
|
||||
function closeDialog(): void {
|
||||
dialogState.visible = false;
|
||||
dataFormRef.value?.resetFields();
|
||||
dataFormRef.value?.clearValidate();
|
||||
formData.id = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除开发者选项配置
|
||||
*/
|
||||
async function handleDelete(id?: string): Promise<void> {
|
||||
const ids = id ? [id] : selectIds.value;
|
||||
if (ids.length === 0) {
|
||||
ElMessage.warning("请勾选要删除的数据");
|
||||
return;
|
||||
}
|
||||
await ElMessageBox.confirm("确认删除选中的开发者选项配置?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
});
|
||||
loading.value = true;
|
||||
try {
|
||||
await DeveloperAPI.deleteByIds(ids.join(","));
|
||||
ElMessage.success("删除成功");
|
||||
selectIds.value = [];
|
||||
handleResetQuery();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
handleQuery();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user