add 地秤管理界面
This commit is contained in:
parent
310af266f9
commit
c302448bc2
156
src/api/admin/UspscaleApi.ts
Normal file
156
src/api/admin/UspscaleApi.ts
Normal file
@ -0,0 +1,156 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: adademo / https://github.com/adademo/swagger-typescript-api ##
|
||||
* ## SOURCE: https://github.com/adademo/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import {
|
||||
UspscaleAddInput,
|
||||
UspscaleGetOutput,
|
||||
UspscaleUpdateInput,
|
||||
PageInputUspscaleGetPageInput,
|
||||
ResultOutputUspscaleGetOutput,
|
||||
ResultOutputPageOutputUspscaleGetPageOutput,
|
||||
ResultOutputInt64,
|
||||
} from './data-contracts'
|
||||
import { ContentType, HttpClient, RequestParams } from './http-client'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
export class UspscaleApi<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name Get
|
||||
* @summary 查询
|
||||
* @request GET:/api/admin/usp-scale/get
|
||||
* @secure
|
||||
*/
|
||||
get = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<ResultOutputUspscaleGetOutput, any>({
|
||||
path: `/api/admin/usp-scale/get`,
|
||||
method: 'GET',
|
||||
query: query,
|
||||
secure: true,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name GetPage
|
||||
* @summary 查询分页
|
||||
* @request POST:/api/admin/usp-scale/get-page
|
||||
* @secure
|
||||
*/
|
||||
getPage = (data: PageInputUspscaleGetPageInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputPageOutputUspscaleGetPageOutput, any>({
|
||||
path: `/api/admin/usp-scale/get-page`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name Add
|
||||
* @summary 新增
|
||||
* @request POST:/api/admin/usp-scale/add
|
||||
* @secure
|
||||
*/
|
||||
add = (data: UspscaleAddInput, params: RequestParams = {}) =>
|
||||
this.request<ResultOutputInt64, any>({
|
||||
path: `/api/admin/usp-scale/add`,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
format: 'json',
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name Update
|
||||
* @summary 修改
|
||||
* @request PUT:/api/admin/usp-scale/update
|
||||
* @secure
|
||||
*/
|
||||
update = (data: UspscaleUpdateInput, params: RequestParams = {}) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/usp-scale/update`,
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
secure: true,
|
||||
type: ContentType.Json,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name Delete
|
||||
* @summary 彻底删除
|
||||
* @request DELETE:/api/admin/usp-scale/delete
|
||||
* @secure
|
||||
*/
|
||||
delete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/usp-scale/delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
|
||||
/**
|
||||
* No description
|
||||
*
|
||||
* @tags uspscale
|
||||
* @name SoftDelete
|
||||
* @summary 删除
|
||||
* @request DELETE:/api/admin/usp-scale/soft-delete
|
||||
* @secure
|
||||
*/
|
||||
softDelete = (
|
||||
query?: {
|
||||
/** @format int64 */
|
||||
id?: number
|
||||
},
|
||||
params: RequestParams = {}
|
||||
) =>
|
||||
this.request<AxiosResponse, any>({
|
||||
path: `/api/admin/usp-scale/soft-delete`,
|
||||
method: 'DELETE',
|
||||
query: query,
|
||||
secure: true,
|
||||
...params,
|
||||
})
|
||||
}
|
@ -6594,3 +6594,229 @@ export interface WebSocketPreConnectInput {
|
||||
*/
|
||||
websocketId?: number | null
|
||||
}
|
||||
|
||||
/** 秤台设备 */
|
||||
export interface UspscaleGetOutput {
|
||||
/** 设备编号 */
|
||||
deviceNo?: string | null
|
||||
/** 资产编号 */
|
||||
assetNo?: string | null
|
||||
/** 型号 */
|
||||
model?: string | null
|
||||
/** 规格 */
|
||||
specification?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 维护标记 */
|
||||
maintenanceFlag?: boolean
|
||||
/** 是否喂料秤 */
|
||||
isFeedingScale?: boolean
|
||||
/** 启用 */
|
||||
enabled?: boolean
|
||||
/**
|
||||
* 主键Id
|
||||
* @format int64
|
||||
*/
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 结果输出 */
|
||||
export interface ResultOutputUspscaleGetOutput {
|
||||
/** 是否成功标记 */
|
||||
success?: boolean
|
||||
/** 编码 */
|
||||
code?: string | null
|
||||
/** 消息 */
|
||||
msg?: string | null
|
||||
/** 秤台设备 */
|
||||
data?: UspscaleGetOutput
|
||||
}
|
||||
|
||||
/** 添加 */
|
||||
export interface UspscaleAddInput {
|
||||
/** 设备编号 */
|
||||
deviceNo?: string | null
|
||||
/** 资产编号 */
|
||||
assetNo?: string | null
|
||||
/** 型号 */
|
||||
model?: string | null
|
||||
/** 规格 */
|
||||
specification?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 维护标记 */
|
||||
maintenanceFlag?: boolean
|
||||
/** 是否喂料秤 */
|
||||
isFeedingScale?: boolean
|
||||
/** 启用 */
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
/** 修改 */
|
||||
export interface UspscaleUpdateInput {
|
||||
/** 设备编号 */
|
||||
deviceNo?: string | null
|
||||
/** 资产编号 */
|
||||
assetNo?: string | null
|
||||
/** 型号 */
|
||||
model?: string | null
|
||||
/** 规格 */
|
||||
specification?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 设备负责人ID */
|
||||
principalId?: number
|
||||
/** 维护标记 */
|
||||
maintenanceFlag?: boolean
|
||||
/** 报警下限值(g) */
|
||||
warningLowerLimit?: number
|
||||
/** 子系统IP */
|
||||
subSystemIP?: string | null
|
||||
/** 子系统IP端口 */
|
||||
subSystemIPPort?: string | null
|
||||
/** 设备IP */
|
||||
deviceIP?: string | null
|
||||
/** 设备IP端口 */
|
||||
deviceIPPort?: string | null
|
||||
/** 精度(g) */
|
||||
scalePrecision?: number
|
||||
/** 服务名称 */
|
||||
serviceName?: string | null
|
||||
/** 是否喂料秤 */
|
||||
isFeedingScale?: boolean
|
||||
/** 启用 */
|
||||
enabled?: boolean
|
||||
/**
|
||||
* 主键Id
|
||||
* @format int64
|
||||
*/
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 结果输出 */
|
||||
export interface ResultOutputListUspscaleGetListOutput {
|
||||
/** 是否成功标记 */
|
||||
success?: boolean
|
||||
/** 编码 */
|
||||
code?: string | null
|
||||
/** 消息 */
|
||||
msg?: string | null
|
||||
/** 数据 */
|
||||
data?: UspscaleGetListOutput[] | null
|
||||
}
|
||||
|
||||
/** 秤台设备列表 */
|
||||
export interface UspscaleGetListOutput {
|
||||
/**
|
||||
* 主键Id
|
||||
* @format int64
|
||||
*/
|
||||
id?: number
|
||||
/** 设备编号 */
|
||||
deviceNo?: string | null
|
||||
/** 资产编号 */
|
||||
assetNo?: string | null
|
||||
/** 型号 */
|
||||
model?: string | null
|
||||
/** 规格 */
|
||||
specification?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 维护标记 */
|
||||
maintenanceFlag?: boolean
|
||||
/** 是否喂料秤 */
|
||||
isFeedingScale?: boolean
|
||||
/** 启用 */
|
||||
enabled?: boolean
|
||||
/**
|
||||
* 创建时间
|
||||
* @format date-time
|
||||
*/
|
||||
createdTime?: string | null
|
||||
}
|
||||
|
||||
/** 分页信息输入 */
|
||||
export interface PageInputUspscaleGetPageInput {
|
||||
dynamicFilter?: DynamicFilterInfo
|
||||
/** 排序列表 */
|
||||
sortList?: SortInput[] | null
|
||||
/**
|
||||
* 当前页标
|
||||
* @format int32
|
||||
*/
|
||||
currentPage?: number
|
||||
/**
|
||||
* 每页大小
|
||||
* @format int32
|
||||
*/
|
||||
pageSize?: number
|
||||
/** 分页请求 */
|
||||
filter?: UspscaleGetPageInput
|
||||
}
|
||||
|
||||
/** 分页请求 */
|
||||
export interface UspscaleGetPageInput {
|
||||
/** 关键词 */
|
||||
keyWord?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 开始日期 */
|
||||
stDate?: string | null
|
||||
/** 结束日期 */
|
||||
edDate?: string | null
|
||||
}
|
||||
|
||||
/** 结果输出 */
|
||||
export interface ResultOutputPageOutputUspscaleGetPageOutput {
|
||||
/** 是否成功标记 */
|
||||
success?: boolean
|
||||
/** 编码 */
|
||||
code?: string | null
|
||||
/** 消息 */
|
||||
msg?: string | null
|
||||
/** 分页信息输出 */
|
||||
data?: PageOutputUspscaleGetPageOutput
|
||||
}
|
||||
|
||||
/** 分页信息输出 */
|
||||
export interface PageOutputUspscaleGetPageOutput {
|
||||
/**
|
||||
* 数据总数
|
||||
* @format int64
|
||||
*/
|
||||
total?: number
|
||||
/** 数据 */
|
||||
list?: UspscaleGetPageOutput[] | null
|
||||
}
|
||||
|
||||
/** 分页响应 */
|
||||
export interface UspscaleGetPageOutput {
|
||||
/**
|
||||
* 编号
|
||||
* @format int64
|
||||
*/
|
||||
id?: number
|
||||
/** 设备编号 */
|
||||
deviceNo?: string | null
|
||||
/** 资产编号 */
|
||||
assetNo?: string | null
|
||||
/** 型号 */
|
||||
model?: string | null
|
||||
/** 规格 */
|
||||
specification?: string | null
|
||||
/** 房间ID */
|
||||
roomID?: number
|
||||
/** 维护标记 */
|
||||
maintenanceFlag?: boolean
|
||||
/** 是否喂料秤 */
|
||||
isFeedingScale?: boolean
|
||||
/** 启用 */
|
||||
enabled?: boolean
|
||||
/** 创建者 */
|
||||
createdUserName?: string | null
|
||||
/**
|
||||
* 创建时间
|
||||
* @format date-time
|
||||
*/
|
||||
createdTime?: string | null
|
||||
}
|
||||
|
@ -19,9 +19,9 @@
|
||||
</el-menu>
|
||||
|
||||
<!-- 将四个模块合并为一个下拉菜单,类似语言切换 -->
|
||||
<el-dropdown
|
||||
:show-timeout="70"
|
||||
:hide-timeout="50"
|
||||
<el-dropdown
|
||||
:show-timeout="70"
|
||||
:hide-timeout="50"
|
||||
trigger="click"
|
||||
@command="onModuleCommand"
|
||||
class="module-dropdown"
|
||||
@ -35,8 +35,8 @@
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="module in moduleList"
|
||||
<el-dropdown-item
|
||||
v-for="module in moduleList"
|
||||
:key="module.path"
|
||||
:command="module.path"
|
||||
:class="{ 'is-active': isCurrentModule(module.path) }"
|
||||
@ -104,17 +104,17 @@ const moduleList = computed(() => {
|
||||
|
||||
// 当前选中的模块
|
||||
const currentModule = computed(() => {
|
||||
const current = moduleList.value.find(module =>
|
||||
state.currentModulePath === module.path ||
|
||||
const current = moduleList.value.find(module =>
|
||||
state.currentModulePath === module.path ||
|
||||
route.path.startsWith(module.path)
|
||||
)
|
||||
|
||||
console.log('state.currentModulePath', state.currentModulePath)
|
||||
|
||||
return current || moduleList.value[0] || {
|
||||
path: '',
|
||||
title: '选择模块',
|
||||
icon: 'ele-Menu'
|
||||
return current || moduleList.value[0] || {
|
||||
path: '',
|
||||
title: '选择模块',
|
||||
icon: 'ele-Menu'
|
||||
}
|
||||
})
|
||||
// 路由过滤递归函数
|
||||
@ -180,11 +180,11 @@ const setCurrentRouterHighlight = (currentRoute: RouteToFrom) => {
|
||||
const onModuleCommand = (path: string) => {
|
||||
// 更新当前模块路径
|
||||
state.currentModulePath = path
|
||||
|
||||
|
||||
// 查找选中的模块
|
||||
const selectedModule = menuLists.value.find(item => item.path === path)
|
||||
if (!selectedModule) return
|
||||
|
||||
|
||||
// 如果模块有子菜单,跳转到第一个可用的子菜单,并更新左侧菜单为第三级
|
||||
if (selectedModule.children && selectedModule.children.length > 0) {
|
||||
const firstChild = selectedModule.children.find((child: RouteRecordRaw) => !child.meta?.isHide)
|
||||
@ -272,7 +272,7 @@ onBeforeMount(() => {
|
||||
const initCurrentModule = () => {
|
||||
// 根据当前路由确定所属模块
|
||||
const currentPath = route.path
|
||||
const matchedModule = menuLists.value.find(module =>
|
||||
const matchedModule = menuLists.value.find(module =>
|
||||
currentPath.startsWith(module.path) && module.path !== '/'
|
||||
)
|
||||
if (matchedModule) {
|
||||
@ -288,16 +288,16 @@ onBeforeRouteUpdate((to) => {
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
setCurrentRouterHighlight(to)
|
||||
// 更新当前模块
|
||||
const matchedModule = menuLists.value.find(module =>
|
||||
const matchedModule = menuLists.value.find(module =>
|
||||
to.path.startsWith(module.path) && module.path !== '/'
|
||||
)
|
||||
if (matchedModule) {
|
||||
state.currentModulePath = matchedModule.path
|
||||
}
|
||||
|
||||
console.log('onBeforeRouteUpdate', to.path, matchedModule.path)
|
||||
console.log('onBeforeRouteUpdate', to.path, matchedModule.path)
|
||||
mittBus.emit('setSendClassicChildren', setBeforeRouteUpdateClassicChildren(to.path))
|
||||
|
||||
|
||||
|
||||
// // 修复经典布局开启切割菜单时,点击tagsView后左侧导航菜单数据不变的问题
|
||||
// let { layout, isClassicSplitMenu } = themeConfig.value
|
||||
@ -339,6 +339,7 @@ onBeforeRouteUpdate((to) => {
|
||||
font-size: 14px;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: color 0.3s, border-color 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
.submenu-icon {
|
||||
margin-top: 0;
|
||||
@ -378,6 +379,7 @@ onBeforeRouteUpdate((to) => {
|
||||
background: var(--el-bg-color);
|
||||
font-size: 14px;
|
||||
transition: background 0.3s, color 0.3s, border-color 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
.module-title { font-weight: 500; }
|
||||
&:hover {
|
||||
@ -406,6 +408,7 @@ onBeforeRouteUpdate((to) => {
|
||||
margin: 4px 6px;
|
||||
border-radius: 6px;
|
||||
transition: background 0.3s, color 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
.dropdown-icon {
|
||||
margin-right: 10px;
|
||||
|
106
src/views/admin/uspscale/components/communication-form.vue
Normal file
106
src/views/admin/uspscale/components/communication-form.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
title="通讯设置"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" size="default" label-width="120px">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="子系统IP" prop="subSystemIP">
|
||||
<el-input v-model="form.subSystemIP" clearable placeholder="请输入子系统IP地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="子系统端口" prop="subSystemIPPort">
|
||||
<el-input v-model="form.subSystemIPPort" clearable placeholder="请输入子系统端口" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="设备IP" prop="deviceIP">
|
||||
<el-input v-model="form.deviceIP" clearable placeholder="请输入设备IP地址" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="设备端口" prop="deviceIPPort">
|
||||
<el-input v-model="form.deviceIPPort" clearable placeholder="请输入设备端口" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="服务名称" prop="serviceName">
|
||||
<el-input v-model="form.serviceName" clearable placeholder="请输入服务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" size="default">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/Uspscale/communication-form">
|
||||
import { reactive, toRefs, ref } from 'vue'
|
||||
|
||||
interface CommunicationData {
|
||||
subSystemIP?: string | null
|
||||
subSystemIPPort?: string | null
|
||||
deviceIP?: string | null
|
||||
deviceIPPort?: string | null
|
||||
serviceName?: string | null
|
||||
}
|
||||
|
||||
const formRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
form: {
|
||||
subSystemIP: '',
|
||||
subSystemIPPort: '',
|
||||
deviceIP: '',
|
||||
deviceIPPort: '',
|
||||
serviceName: '',
|
||||
} as CommunicationData,
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
const emit = defineEmits(['confirm'])
|
||||
|
||||
// 打开对话框
|
||||
const open = (data: CommunicationData = {}) => {
|
||||
state.form = {
|
||||
subSystemIP: data.subSystemIP || '',
|
||||
subSystemIPPort: data.subSystemIPPort || '',
|
||||
deviceIP: data.deviceIP || '',
|
||||
deviceIPPort: data.deviceIPPort || '',
|
||||
serviceName: data.serviceName || '',
|
||||
}
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
emit('confirm', { ...state.form })
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
364
src/views/admin/uspscale/components/uspscale-form.vue
Normal file
364
src/views/admin/uspscale/components/uspscale-form.vue
Normal file
@ -0,0 +1,364 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="state.showDialog"
|
||||
destroy-on-close
|
||||
:title="title"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
width="900px"
|
||||
>
|
||||
<el-form :model="form" ref="formRef" size="default" label-width="120px">
|
||||
<!-- 基本信息 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">基本信息</div>
|
||||
<el-row :gutter="25">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="设备编号" prop="deviceNo" :rules="[{ required: true, message: '请输入设备编号', trigger: ['blur', 'change'] }]">
|
||||
<el-input v-model="form.deviceNo" clearable placeholder="请输入设备编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="资产编号" prop="assetNo">
|
||||
<el-input v-model="form.assetNo" clearable placeholder="请输入资产编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="型号" prop="model">
|
||||
<el-select v-model="form.model" placeholder="请选择设备型号" clearable style="width: 100%">
|
||||
<el-option
|
||||
v-for="model in state.modelOptions"
|
||||
:key="model.value"
|
||||
:label="model.label"
|
||||
:value="model.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="规格" prop="specification">
|
||||
<el-input v-model="form.specification" clearable placeholder="请输入设备规格" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="房间" prop="roomID" :rules="[{ required: true, message: '请选择房间', trigger: ['blur', 'change'] }]">
|
||||
<el-select v-model="form.roomID" placeholder="请选择设备所在房间" style="width: 100%">
|
||||
<el-option
|
||||
v-for="room in state.roomOptions"
|
||||
:key="room.id"
|
||||
:label="room.roomName"
|
||||
:value="room.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="设备负责人" prop="principalId">
|
||||
<el-select
|
||||
v-model="form.principalId"
|
||||
placeholder="请输入姓名搜索设备负责人"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="user in state.userOptions"
|
||||
:key="user.id"
|
||||
:label="`${user.name} (${user.userName})`"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 技术参数 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">技术参数</div>
|
||||
<el-row :gutter="25">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="精度(g)" prop="scalePrecision">
|
||||
<el-input-number v-model="form.scalePrecision" :min="0" :precision="1" style="width: 100%" placeholder="请输入设备精度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="报警下限值(g)" prop="warningLowerLimit">
|
||||
<el-input-number v-model="form.warningLowerLimit" :min="0" :precision="2" style="width: 100%" placeholder="请输入报警下限值" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 设备配置 -->
|
||||
<div class="form-section">
|
||||
<div class="section-title">设备配置</div>
|
||||
<el-row :gutter="25">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="维护标记">
|
||||
<el-switch
|
||||
v-model="form.maintenanceFlag"
|
||||
active-text="维护中"
|
||||
inactive-text="正常"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="是否补料地秤">
|
||||
<el-switch
|
||||
v-model="form.isFeedingScale"
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="启用状态">
|
||||
<el-switch
|
||||
v-model="form.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<el-form-item label="通讯设置">
|
||||
<el-button type="primary" @click="openCommunicationForm" icon="ele-Setting">
|
||||
配置通讯参数
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||
<el-button type="primary" @click="onSure" size="default" :loading="state.sureLoading">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 通讯设置表单 -->
|
||||
<communication-form ref="communicationFormRef" @confirm="onCommunicationConfirm" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/Uspscale/form">
|
||||
import { reactive, toRefs, ref, getCurrentInstance, onMounted, defineAsyncComponent } from 'vue'
|
||||
import { UspscaleUpdateInput, RoomGetPageOutput, PageInputRoomGetPageInput, UserGetPageOutput, PageInputUserGetPageInput } from '/@/api/admin/data-contracts'
|
||||
import { UspscaleApi } from '/@/api/admin/UspscaleApi'
|
||||
import { RoomApi } from '/@/api/admin/Room'
|
||||
import { UserApi } from '/@/api/admin/User'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
|
||||
// 引入通讯设置表单组件
|
||||
const CommunicationForm = defineAsyncComponent(() => import('./communication-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const communicationFormRef = ref()
|
||||
const state = reactive({
|
||||
showDialog: false,
|
||||
sureLoading: false,
|
||||
form: {
|
||||
enabled: true,
|
||||
maintenanceFlag: false,
|
||||
isFeedingScale: false,
|
||||
roomID: 0,
|
||||
} as UspscaleUpdateInput,
|
||||
roomOptions: [] as Array<RoomGetPageOutput>,
|
||||
userOptions: [] as Array<UserGetPageOutput>,
|
||||
modelOptions: [
|
||||
{ label: 'CAIS2-U 1500kg', value: '001' },
|
||||
{ label: 'METTLER', value: '3' },
|
||||
{ label: 'OHAUS', value: '5' }
|
||||
],
|
||||
data: [],
|
||||
})
|
||||
|
||||
const { form } = toRefs(state)
|
||||
|
||||
onMounted(() => {
|
||||
getRoomOptions()
|
||||
getUserOptions()
|
||||
})
|
||||
|
||||
const getRoomOptions = async () => {
|
||||
try {
|
||||
const roomPageInput = {
|
||||
currentPage: 1,
|
||||
pageSize: 1000, // 获取足够多的数据
|
||||
filter: {
|
||||
keyWord: '',
|
||||
}
|
||||
} as PageInputRoomGetPageInput
|
||||
|
||||
const res = await new RoomApi().getPage(roomPageInput)
|
||||
if (res?.success) {
|
||||
state.roomOptions = res.data?.list ?? []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取房间列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getUserOptions = async () => {
|
||||
try {
|
||||
const userPageInput = {
|
||||
currentPage: 1,
|
||||
pageSize: 1000, // 获取足够多的数据
|
||||
filter: {
|
||||
orgId: null,
|
||||
}
|
||||
} as PageInputUserGetPageInput
|
||||
|
||||
const res = await new UserApi().getPage(userPageInput)
|
||||
if (res?.success) {
|
||||
state.userOptions = res.data?.list ?? []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开对话框
|
||||
const open = async (row: any = {}) => {
|
||||
proxy.$modal.loading()
|
||||
|
||||
if (row.id > 0) {
|
||||
const res = await new UspscaleApi().get({ id: row.id }, { loading: true })
|
||||
if (res?.success) {
|
||||
let formData = res.data as UspscaleUpdateInput
|
||||
state.form = formData
|
||||
}
|
||||
} else {
|
||||
state.form = {
|
||||
enabled: true,
|
||||
maintenanceFlag: false,
|
||||
isFeedingScale: false,
|
||||
roomID: undefined,
|
||||
principalId: undefined,
|
||||
warningLowerLimit: 0,
|
||||
scalePrecision: 0,
|
||||
deviceNo: '',
|
||||
assetNo: '',
|
||||
model: '',
|
||||
specification: '',
|
||||
subSystemIP: '',
|
||||
subSystemIPPort: '',
|
||||
deviceIP: '',
|
||||
deviceIPPort: '',
|
||||
serviceName: '',
|
||||
} as UspscaleUpdateInput
|
||||
}
|
||||
|
||||
proxy.$modal.closeLoading()
|
||||
state.showDialog = true
|
||||
}
|
||||
|
||||
// 打开通讯设置表单
|
||||
const openCommunicationForm = () => {
|
||||
const communicationData = {
|
||||
subSystemIP: state.form.subSystemIP,
|
||||
subSystemIPPort: state.form.subSystemIPPort,
|
||||
deviceIP: state.form.deviceIP,
|
||||
deviceIPPort: state.form.deviceIPPort,
|
||||
serviceName: state.form.serviceName,
|
||||
}
|
||||
communicationFormRef.value.open(communicationData)
|
||||
}
|
||||
|
||||
// 通讯设置确认回调
|
||||
const onCommunicationConfirm = (data: any) => {
|
||||
state.form.subSystemIP = data.subSystemIP
|
||||
state.form.subSystemIPPort = data.subSystemIPPort
|
||||
state.form.deviceIP = data.deviceIP
|
||||
state.form.deviceIPPort = data.deviceIPPort
|
||||
state.form.serviceName = data.serviceName
|
||||
}
|
||||
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
state.showDialog = false
|
||||
}
|
||||
|
||||
// 确定
|
||||
const onSure = () => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
|
||||
state.sureLoading = true
|
||||
let res = {} as any
|
||||
if (state.form.id != undefined && state.form.id > 0) {
|
||||
res = await new UspscaleApi().update(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
} else {
|
||||
res = await new UspscaleApi().add(state.form, { showSuccessMessage: true }).catch(() => {
|
||||
state.sureLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
state.sureLoading = false
|
||||
|
||||
if (res?.success) {
|
||||
eventBus.emit('refreshRoom')
|
||||
state.showDialog = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-section {
|
||||
margin-bottom: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #f0f0f0;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -2px;
|
||||
width: 40px;
|
||||
height: 2px;
|
||||
background: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
:deep(.el-switch__label) {
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
300
src/views/admin/uspscale/index.vue
Normal file
300
src/views/admin/uspscale/index.vue
Normal file
@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<MyLayout>
|
||||
<el-card v-show="state.showQuery" class="my-query-box mt8" shadow="never" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :inline="true" label-width="auto" @submit.stop.prevent>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="state.filter.keyWord" placeholder="设备编号、资产编号" @keyup.enter="onQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号">
|
||||
<el-select v-model="state.filter.model" placeholder="请选择设备型号" clearable style="width: 150px">
|
||||
<el-option
|
||||
v-for="model in state.modelOptions"
|
||||
:key="model.value"
|
||||
:label="model.label"
|
||||
:value="model.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="房间">
|
||||
<el-select v-model="state.filter.roomID" placeholder="请选择房间" clearable style="width: 150px">
|
||||
<el-option
|
||||
v-for="room in state.roomOptions"
|
||||
:key="room.id"
|
||||
:label="room.roomName"
|
||||
:value="room.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间">
|
||||
<el-date-picker
|
||||
v-model="state.filter.stDate"
|
||||
type="datetime"
|
||||
placeholder="选择开始时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间">
|
||||
<el-date-picker
|
||||
v-model="state.filter.edDate"
|
||||
type="datetime"
|
||||
placeholder="选择结束时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
|
||||
<el-button v-auth="'api:admin:usp-scale:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="my-fill mt8" shadow="never">
|
||||
<div class="my-tools-box mb8 my-flex my-flex-between">
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="state.showUspscaleList"
|
||||
:data="state.uspscaleListData"
|
||||
style="width: 100%"
|
||||
v-loading="state.loading"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
border
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column prop="deviceNo" label="设备编号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="assetNo" label="资产编号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="model" label="型号" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ getModelName(row.model) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="specification" label="规格" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="roomID" label="房间" width="120" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ getRoomName(row.roomID) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="维护标记" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag type="warning" v-if="row.maintenanceFlag">维护中</el-tag>
|
||||
<el-tag type="success" v-else>正常</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="补料地秤" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" v-if="row.isFeedingScale">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right" header-align="center" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="auth('api:admin:usp-scale:update')"
|
||||
icon="ele-EditPen"
|
||||
size="small"
|
||||
text
|
||||
type="primary"
|
||||
@click="onEdit(row)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="auth('api:admin:usp-scale:soft-delete')"
|
||||
icon="ele-Delete"
|
||||
size="small"
|
||||
text
|
||||
type="danger"
|
||||
@click="onDelete(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="my-flex my-flex-end" style="margin-top: 10px">
|
||||
<el-pagination
|
||||
v-model:currentPage="state.pageInput.currentPage"
|
||||
v-model:page-size="state.pageInput.pageSize"
|
||||
:total="state.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
size="small"
|
||||
background
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<uspscale-form ref="uspscaleFormRef" :title="state.uspscaleFormTitle"></uspscale-form>
|
||||
</MyLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="admin/uspscale">
|
||||
import { ref, reactive, onMounted, getCurrentInstance, onBeforeMount, defineAsyncComponent } from 'vue'
|
||||
import { UspscaleGetListOutput, PageInputUspscaleGetPageInput, UspscaleGetPageOutput, RoomGetPageOutput, PageInputRoomGetPageInput } from '/@/api/admin/data-contracts'
|
||||
import { UspscaleApi } from '/@/api/admin/UspscaleApi'
|
||||
import { RoomApi } from '/@/api/admin/Room'
|
||||
import eventBus from '/@/utils/mitt'
|
||||
import { auth } from '/@/utils/authFunction'
|
||||
|
||||
// 引入组件
|
||||
const UspscaleForm = defineAsyncComponent(() => import('./components/uspscale-form.vue'))
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const uspscaleFormRef = ref()
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
uspscaleFormTitle: '',
|
||||
filter: {
|
||||
keyWord: '',
|
||||
model: '',
|
||||
roomID: undefined as number | undefined,
|
||||
stDate: '',
|
||||
edDate: '',
|
||||
},
|
||||
total: 0,
|
||||
pageInput: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
} as PageInputUspscaleGetPageInput,
|
||||
uspscaleListData: [] as Array<UspscaleGetPageOutput>,
|
||||
roomOptions: [] as Array<RoomGetPageOutput>,
|
||||
modelOptions: [
|
||||
{ label: 'CAIS2-U 1500kg', value: '001' },
|
||||
{ label: 'METTLER', value: '3' },
|
||||
{ label: 'OHAUS', value: '5' }
|
||||
],
|
||||
showQuery: true,
|
||||
showUspscaleList: true,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getRoomOptions()
|
||||
Query()
|
||||
eventBus.off('refreshRoom')
|
||||
eventBus.on('refreshRoom', () => {
|
||||
Query()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
eventBus.off('refreshRoom')
|
||||
})
|
||||
|
||||
const onChangeUspscaleList = () => {
|
||||
state.showUspscaleList = !state.showUspscaleList
|
||||
if (state.showUspscaleList) {
|
||||
Query()
|
||||
}
|
||||
}
|
||||
|
||||
const onQuery = () => {
|
||||
Query()
|
||||
}
|
||||
|
||||
const getRoomOptions = async () => {
|
||||
try {
|
||||
const roomPageInput = {
|
||||
currentPage: 1,
|
||||
pageSize: 1000, // 获取足够多的数据
|
||||
filter: {
|
||||
keyWord: '',
|
||||
}
|
||||
} as PageInputRoomGetPageInput
|
||||
|
||||
const res = await new RoomApi().getPage(roomPageInput)
|
||||
if (res?.success) {
|
||||
state.roomOptions = res.data?.list ?? []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取房间列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getRoomName = (roomID: number) => {
|
||||
const room = state.roomOptions.find(r => r.id === roomID)
|
||||
return room ? room.roomName : `未知房间(${roomID})`
|
||||
}
|
||||
|
||||
const getModelName = (modelValue: string) => {
|
||||
const model = state.modelOptions.find(m => m.value === modelValue)
|
||||
return model ? model.label : modelValue
|
||||
}
|
||||
|
||||
const Query = async () => {
|
||||
state.loading = true
|
||||
state.pageInput.filter = state.filter
|
||||
const res = await new UspscaleApi().getPage(state.pageInput).catch(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
state.uspscaleListData = res?.data?.list ?? []
|
||||
state.total = res?.data?.total ?? 0
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
state.uspscaleFormTitle = '新增地秤'
|
||||
uspscaleFormRef.value.open({
|
||||
id: 0,
|
||||
enabled: true,
|
||||
deviceNo: '',
|
||||
assetNo: '',
|
||||
model: '',
|
||||
specification: '',
|
||||
roomID: undefined,
|
||||
principalId: undefined,
|
||||
maintenanceFlag: false,
|
||||
warningLowerLimit: 0,
|
||||
subSystemIP: '',
|
||||
subSystemIPPort: '',
|
||||
deviceIP: '',
|
||||
deviceIPPort: '',
|
||||
scalePrecision: 0,
|
||||
serviceName: '',
|
||||
isFeedingScale: false
|
||||
})
|
||||
}
|
||||
|
||||
const onEdit = (row: UspscaleGetListOutput) => {
|
||||
state.uspscaleFormTitle = '编辑地秤'
|
||||
uspscaleFormRef.value.open(row)
|
||||
}
|
||||
|
||||
const onDelete = (row: UspscaleGetListOutput) => {
|
||||
proxy.$modal
|
||||
.confirmDelete(`确定要删除设备【${row.deviceNo || row.assetNo || '未知设备'}】?`)
|
||||
.then(async () => {
|
||||
await new UspscaleApi().softDelete({ id: row.id }, { loading: true })
|
||||
Query()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const onSizeChange = (val: number) => {
|
||||
state.pageInput.currentPage = 1
|
||||
state.pageInput.pageSize = val
|
||||
onQuery()
|
||||
}
|
||||
|
||||
const onCurrentChange = (val: number) => {
|
||||
state.pageInput.currentPage = val
|
||||
onQuery()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
570
页面开发数据模板.md
Normal file
570
页面开发数据模板.md
Normal file
@ -0,0 +1,570 @@
|
||||
# 页面开发数据模板
|
||||
|
||||
> 基于 uspscale (秤台设备管理) 页面开发经验总结的完整开发模板
|
||||
|
||||
## 1. 基本信息配置
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 页面基本信息
|
||||
pageInfo: {
|
||||
moduleName: "uspscale", // 模块名称(小写,用于路径)
|
||||
displayName: "秤台设备管理", // 显示名称
|
||||
baseRoute: "admin/uspscale", // 路由路径
|
||||
referenceModule: "admin/room" // 参考的现有模块(用于复制结构)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. API接口定义
|
||||
|
||||
```typescript
|
||||
{
|
||||
// API配置
|
||||
apiConfig: {
|
||||
baseEndpoint: "/api/admin/usp-scale", // API基础路径
|
||||
endpoints: {
|
||||
getPage: "get-page", // 分页查询
|
||||
get: "get", // 单条查询
|
||||
add: "add", // 新增
|
||||
update: "update", // 更新
|
||||
softDelete: "soft-delete" // 软删除(推荐)
|
||||
// delete: "delete" // 硬删除(可选)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 数据字段定义
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 字段定义
|
||||
fields: {
|
||||
// 主键字段
|
||||
primaryKey: {
|
||||
name: "id",
|
||||
type: "number",
|
||||
required: true
|
||||
},
|
||||
|
||||
// 基本字段
|
||||
basicFields: [
|
||||
{
|
||||
name: "deviceNo",
|
||||
type: "string",
|
||||
label: "设备编号",
|
||||
required: true,
|
||||
component: "input",
|
||||
placeholder: "请输入设备编号"
|
||||
},
|
||||
{
|
||||
name: "assetNo",
|
||||
type: "string",
|
||||
label: "资产编号",
|
||||
required: false,
|
||||
component: "input",
|
||||
placeholder: "请输入资产编号"
|
||||
}
|
||||
],
|
||||
|
||||
// 下拉选择字段
|
||||
selectFields: [
|
||||
{
|
||||
name: "roomID",
|
||||
type: "number",
|
||||
label: "房间",
|
||||
required: true,
|
||||
component: "select",
|
||||
dataSource: "room", // 数据来源API
|
||||
displayField: "roomName",
|
||||
valueField: "id",
|
||||
placeholder: "请选择设备所在房间"
|
||||
},
|
||||
{
|
||||
name: "model",
|
||||
type: "string",
|
||||
label: "型号",
|
||||
required: false,
|
||||
component: "select",
|
||||
dataSource: "static", // 静态数据
|
||||
options: [
|
||||
{ label: "CAIS2-U 1500kg", value: "001" },
|
||||
{ label: "METTLER", value: "3" },
|
||||
{ label: "OHAUS", value: "5" }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "principalId",
|
||||
type: "number",
|
||||
label: "设备负责人",
|
||||
required: false,
|
||||
component: "select",
|
||||
dataSource: "user", // 用户数据源
|
||||
displayField: "name (userName)", // 显示格式:姓名(用户名)
|
||||
valueField: "id",
|
||||
filterable: true, // 支持搜索
|
||||
placeholder: "请输入姓名搜索设备负责人"
|
||||
}
|
||||
],
|
||||
|
||||
// 数字字段
|
||||
numberFields: [
|
||||
{
|
||||
name: "scalePrecision",
|
||||
type: "number",
|
||||
label: "精度(g)",
|
||||
required: false,
|
||||
component: "input-number",
|
||||
min: 0,
|
||||
precision: 1,
|
||||
placeholder: "请输入设备精度"
|
||||
},
|
||||
{
|
||||
name: "warningLowerLimit",
|
||||
type: "number",
|
||||
label: "报警下限值(g)",
|
||||
required: false,
|
||||
component: "input-number",
|
||||
min: 0,
|
||||
precision: 2,
|
||||
placeholder: "请输入报警下限值"
|
||||
}
|
||||
],
|
||||
|
||||
// 开关字段
|
||||
switchFields: [
|
||||
{
|
||||
name: "enabled",
|
||||
type: "boolean",
|
||||
label: "启用状态",
|
||||
required: false,
|
||||
component: "switch",
|
||||
activeText: "启用",
|
||||
inactiveText: "禁用"
|
||||
},
|
||||
{
|
||||
name: "maintenanceFlag",
|
||||
type: "boolean",
|
||||
label: "维护标记",
|
||||
required: false,
|
||||
component: "switch",
|
||||
activeText: "维护中",
|
||||
inactiveText: "正常"
|
||||
},
|
||||
{
|
||||
name: "isFeedingScale",
|
||||
type: "boolean",
|
||||
label: "是否补料地秤",
|
||||
required: false,
|
||||
component: "switch",
|
||||
activeText: "是",
|
||||
inactiveText: "否"
|
||||
}
|
||||
],
|
||||
|
||||
// 搜索筛选字段
|
||||
filterFields: [
|
||||
{
|
||||
name: "keyWord",
|
||||
type: "string",
|
||||
label: "关键词",
|
||||
component: "input",
|
||||
placeholder: "设备编号、资产编号"
|
||||
},
|
||||
{
|
||||
name: "model",
|
||||
type: "string",
|
||||
label: "设备型号",
|
||||
component: "select",
|
||||
dataSource: "static",
|
||||
placeholder: "请选择设备型号"
|
||||
},
|
||||
{
|
||||
name: "roomID",
|
||||
type: "number",
|
||||
label: "房间",
|
||||
component: "select",
|
||||
dataSource: "room",
|
||||
placeholder: "请选择房间"
|
||||
},
|
||||
{
|
||||
name: "stDate",
|
||||
type: "string",
|
||||
label: "开始时间",
|
||||
component: "datetime-picker",
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
placeholder: "选择开始时间"
|
||||
},
|
||||
{
|
||||
name: "edDate",
|
||||
type: "string",
|
||||
label: "结束时间",
|
||||
component: "datetime-picker",
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
placeholder: "选择结束时间"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 权限定义
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 权限配置
|
||||
permissions: [
|
||||
"api:admin:usp-scale:get", // 查询单条
|
||||
"api:admin:usp-scale:get-list", // 查询列表
|
||||
"api:admin:usp-scale:get-page", // 分页查询
|
||||
"api:admin:usp-scale:add", // 新增
|
||||
"api:admin:usp-scale:update", // 更新
|
||||
"api:admin:usp-scale:soft-delete" // 软删除
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 表格列配置
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 表格列定义
|
||||
tableColumns: [
|
||||
{
|
||||
prop: "deviceNo",
|
||||
label: "设备编号",
|
||||
minWidth: 120,
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{
|
||||
prop: "assetNo",
|
||||
label: "资产编号",
|
||||
minWidth: 120,
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{
|
||||
prop: "model",
|
||||
label: "型号",
|
||||
minWidth: 120,
|
||||
showOverflowTooltip: true,
|
||||
formatter: "getModelName" // 需要转换显示的字段
|
||||
},
|
||||
{
|
||||
prop: "specification",
|
||||
label: "规格",
|
||||
minWidth: 120,
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{
|
||||
prop: "roomID",
|
||||
label: "房间",
|
||||
width: 120,
|
||||
align: "center",
|
||||
formatter: "getRoomName" // 需要转换显示的字段
|
||||
},
|
||||
{
|
||||
prop: "maintenanceFlag",
|
||||
label: "维护标记",
|
||||
width: 80,
|
||||
align: "center",
|
||||
component: "tag", // 使用标签显示
|
||||
tagConfig: {
|
||||
trueText: "维护中",
|
||||
falseText: "正常",
|
||||
trueType: "warning",
|
||||
falseType: "success"
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: "isFeedingScale",
|
||||
label: "补料地秤",
|
||||
width: 100,
|
||||
align: "center",
|
||||
component: "tag",
|
||||
tagConfig: {
|
||||
trueText: "是",
|
||||
falseText: "否",
|
||||
trueType: "primary",
|
||||
falseType: "info"
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: "enabled",
|
||||
label: "状态",
|
||||
width: 80,
|
||||
align: "center",
|
||||
component: "tag",
|
||||
tagConfig: {
|
||||
trueText: "启用",
|
||||
falseText: "禁用",
|
||||
trueType: "success",
|
||||
falseType: "danger"
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: "actions",
|
||||
label: "操作",
|
||||
width: 200,
|
||||
fixed: "right",
|
||||
headerAlign: "center",
|
||||
align: "center",
|
||||
actions: [
|
||||
{
|
||||
text: "编辑",
|
||||
type: "primary",
|
||||
permission: "api:admin:usp-scale:update",
|
||||
handler: "onEdit"
|
||||
},
|
||||
{
|
||||
text: "删除",
|
||||
type: "danger",
|
||||
permission: "api:admin:usp-scale:soft-delete",
|
||||
handler: "onDelete"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 表单布局配置
|
||||
|
||||
```typescript
|
||||
{
|
||||
// 表单配置
|
||||
formConfig: {
|
||||
dialogWidth: "900px",
|
||||
labelWidth: "120px",
|
||||
|
||||
// 表单分组
|
||||
sections: [
|
||||
{
|
||||
title: "基本信息",
|
||||
fields: [
|
||||
"deviceNo",
|
||||
"assetNo",
|
||||
"model",
|
||||
"specification",
|
||||
"roomID",
|
||||
"principalId"
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "技术参数",
|
||||
fields: [
|
||||
"scalePrecision",
|
||||
"warningLowerLimit"
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "设备配置",
|
||||
fields: [
|
||||
"maintenanceFlag",
|
||||
"isFeedingScale",
|
||||
"enabled",
|
||||
"communicationSettings"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
// 特殊组件(如独立表单)
|
||||
specialComponents: [
|
||||
{
|
||||
name: "communicationSettings",
|
||||
type: "button",
|
||||
label: "通讯设置",
|
||||
buttonText: "配置通讯参数",
|
||||
icon: "ele-Setting",
|
||||
action: "openSubForm",
|
||||
subFormConfig: {
|
||||
title: "通讯设置",
|
||||
width: "600px",
|
||||
fields: [
|
||||
"subSystemIP",
|
||||
"subSystemIPPort",
|
||||
"deviceIP",
|
||||
"deviceIPPort",
|
||||
"serviceName"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 完整示例配置
|
||||
|
||||
### 设备管理页面示例
|
||||
|
||||
```json
|
||||
{
|
||||
"pageInfo": {
|
||||
"moduleName": "device",
|
||||
"displayName": "设备管理",
|
||||
"baseRoute": "admin/device",
|
||||
"referenceModule": "admin/room"
|
||||
},
|
||||
"apiConfig": {
|
||||
"baseEndpoint": "/api/admin/device",
|
||||
"endpoints": {
|
||||
"getPage": "get-page",
|
||||
"get": "get",
|
||||
"add": "add",
|
||||
"update": "update",
|
||||
"softDelete": "soft-delete"
|
||||
}
|
||||
},
|
||||
"permissions": [
|
||||
"api:admin:device:get",
|
||||
"api:admin:device:get-page",
|
||||
"api:admin:device:add",
|
||||
"api:admin:device:update",
|
||||
"api:admin:device:soft-delete"
|
||||
],
|
||||
"fields": {
|
||||
"basicFields": [
|
||||
{
|
||||
"name": "deviceName",
|
||||
"type": "string",
|
||||
"label": "设备名称",
|
||||
"required": true,
|
||||
"component": "input",
|
||||
"placeholder": "请输入设备名称"
|
||||
},
|
||||
{
|
||||
"name": "deviceCode",
|
||||
"type": "string",
|
||||
"label": "设备编码",
|
||||
"required": true,
|
||||
"component": "input",
|
||||
"placeholder": "请输入设备编码"
|
||||
}
|
||||
],
|
||||
"selectFields": [
|
||||
{
|
||||
"name": "categoryId",
|
||||
"type": "number",
|
||||
"label": "设备分类",
|
||||
"required": true,
|
||||
"component": "select",
|
||||
"dataSource": "category"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 开发步骤清单
|
||||
|
||||
### 8.1 准备阶段
|
||||
- [ ] 确定页面基本信息(模块名、显示名等)
|
||||
- [ ] 设计数据结构和字段定义
|
||||
- [ ] 确定API接口规范
|
||||
- [ ] 确定权限控制规则
|
||||
- [ ] 分析数据关联关系(如外键引用)
|
||||
|
||||
### 8.2 后端准备
|
||||
- [ ] 创建数据库表结构
|
||||
- [ ] 实现API接口(CRUD操作)
|
||||
- [ ] 配置权限控制
|
||||
- [ ] 数据验证和业务逻辑
|
||||
- [ ] API文档编写
|
||||
|
||||
### 8.3 前端开发
|
||||
|
||||
#### 8.3.1 基础文件创建
|
||||
- [ ] 创建主页面文件 `src/views/admin/{module}/index.vue`
|
||||
- [ ] 创建表单组件 `src/views/admin/{module}/components/{module}-form.vue`
|
||||
- [ ] 创建API文件 `src/api/admin/{Module}Api.ts`
|
||||
- [ ] 更新类型定义 `src/api/admin/data-contracts.ts`
|
||||
|
||||
#### 8.3.2 功能实现
|
||||
- [ ] 实现分页查询功能
|
||||
- [ ] 实现新增功能
|
||||
- [ ] 实现编辑功能
|
||||
- [ ] 实现删除功能
|
||||
- [ ] 添加权限控制
|
||||
|
||||
#### 8.3.3 用户体验优化
|
||||
- [ ] 添加搜索筛选功能
|
||||
- [ ] 优化表单布局(分组、占位符)
|
||||
- [ ] 添加数据验证
|
||||
- [ ] 优化选择框(搜索、分页)
|
||||
- [ ] 添加操作确认提示
|
||||
|
||||
### 8.4 测试阶段
|
||||
- [ ] 功能测试(CRUD操作)
|
||||
- [ ] 权限测试
|
||||
- [ ] 数据验证测试
|
||||
- [ ] 用户体验测试
|
||||
- [ ] 性能测试
|
||||
|
||||
### 8.5 优化阶段
|
||||
- [ ] 代码优化和重构
|
||||
- [ ] 性能优化(懒加载、虚拟滚动等)
|
||||
- [ ] 错误处理优化
|
||||
- [ ] 用户反馈收集和改进
|
||||
|
||||
## 9. 开发最佳实践
|
||||
|
||||
### 9.1 命名规范
|
||||
- **文件命名**:使用小写字母和连字符,如 `device-form.vue`
|
||||
- **变量命名**:使用驼峰命名法,如 `deviceList`
|
||||
- **常量命名**:使用大写字母和下划线,如 `MAX_PAGE_SIZE`
|
||||
|
||||
### 9.2 代码组织
|
||||
- **组件拆分**:将复杂表单拆分为多个子组件
|
||||
- **逻辑复用**:将通用逻辑提取为组合函数
|
||||
- **类型安全**:全面使用 TypeScript 类型定义
|
||||
|
||||
### 9.3 用户体验
|
||||
- **响应式设计**:适配不同屏幕尺寸
|
||||
- **加载状态**:添加适当的加载提示
|
||||
- **错误处理**:友好的错误提示信息
|
||||
- **操作反馈**:成功/失败的操作提示
|
||||
|
||||
### 9.4 性能优化
|
||||
- **懒加载**:大型组件使用异步加载
|
||||
- **虚拟滚动**:大数据量列表使用虚拟滚动
|
||||
- **防抖节流**:搜索等操作使用防抖
|
||||
- **缓存策略**:合理使用数据缓存
|
||||
|
||||
## 10. 常见问题和解决方案
|
||||
|
||||
### 10.1 下拉选择优化
|
||||
**问题**:数据量大时选择困难
|
||||
**解决方案**:
|
||||
- 添加搜索功能(filterable)
|
||||
- 显示更多信息(姓名+用户名)
|
||||
- 支持远程搜索
|
||||
- 添加分页加载
|
||||
|
||||
### 10.2 表单字段分组
|
||||
**问题**:字段太多导致表单复杂
|
||||
**解决方案**:
|
||||
- 按逻辑分组(基本信息、技术参数、配置)
|
||||
- 使用独立表单处理复杂模块
|
||||
- 添加分步表单
|
||||
- 使用折叠面板
|
||||
|
||||
### 10.3 权限控制
|
||||
**问题**:不同用户需要不同权限
|
||||
**解决方案**:
|
||||
- 细化权限粒度
|
||||
- 使用 v-auth 指令控制按钮显示
|
||||
- 在API层面进行权限验证
|
||||
- 提供权限管理界面
|
||||
|
||||
### 10.4 数据关联
|
||||
**问题**:外键数据显示和选择
|
||||
**解决方案**:
|
||||
- 提供格式化函数转换显示
|
||||
- 在表单中使用下拉选择
|
||||
- 支持级联选择
|
||||
- 缓存关联数据
|
||||
|
||||
---
|
||||
|
||||
**注意**:此模板基于 Vue 3 + TypeScript + Element Plus + Pinia 技术栈,使用时请根据实际项目技术栈进行调整。
|
Loading…
x
Reference in New Issue
Block a user