新需求增加

This commit is contained in:
BianLzhaoMin 2025-12-29 10:14:57 +08:00
parent 693adb8017
commit ad9123258f
17 changed files with 2401 additions and 39 deletions

View File

@ -0,0 +1,64 @@
import request from '@/utils/request'
/**
* 查询App版本列表
* @param {Object} query - 查询参数
* @returns {Promise}
*/
export function listAppVersion(query) {
return request({
url: '/system/appVersion/list',
method: 'get',
params: query,
})
}
/**
* 查询App版本详情
* @param {Number} id - 版本ID
* @returns {Promise}
*/
export function getAppVersion(id) {
return request({
url: '/system/appVersion/' + id,
method: 'get',
})
}
/**
* 新增App版本
* @param {Object} data - 版本数据
* @returns {Promise}
*/
export function addAppVersion(data) {
return request({
url: '/system/appVersion',
method: 'post',
data: data,
})
}
/**
* 修改App版本
* @param {Object} data - 版本数据
* @returns {Promise}
*/
export function updateAppVersion(data) {
return request({
url: '/system/appVersion/edit',
method: 'post',
data: data,
})
}
/**
* 删除App版本
* @param {Number} id - 版本ID
* @returns {Promise}
*/
export function delAppVersion(id) {
return request({
url: '/system/appVersion/delete/' + id,
method: 'post',
})
}

View File

@ -70,7 +70,7 @@
/>
<el-date-picker
type="date"
style="width: 240px"
:style="{ width: item.f_width || '240px' }"
value-format="yyyy-MM-dd"
v-if="item.f_type === 'date'"
v-model="queryParams[item.f_model]"
@ -78,7 +78,7 @@
/>
<el-date-picker
type="daterange"
style="width: 240px"
:style="{ width: item.f_width || '240px' }"
range-separator="至"
value-format="yyyy-MM-dd"
start-placeholder="开始日期"

View File

@ -5,6 +5,13 @@ export const formLabel = [
f_label: '关键词',
f_model: 'keyWord',
},
{
f_label: '创建时间',
f_model: 'createTime',
f_type: 'date',
f_width: '180px',
isShow: false, // 是否展示label
},
]
export const columnsList = [
@ -17,6 +24,7 @@ export const columnsList = [
t_slot: 'count',
},
{ t_slot: 'proStatus', t_label: '状态' },
{ t_props: 'createTime', t_label: '创建时间' },
]
export const dialogConfig = {

View File

@ -110,15 +110,30 @@
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="是否上海项目" prop="isShanghai">
<el-radio-group
size="medium"
:disabled="formType === 2"
<el-form-item label="工程所在地" prop="isShanghai">
<!-- <el-radio-group -->
<!-- size="medium" -->
<!-- :disabled="formType === 2" -->
<!-- v-model="addOrEditForm.isShanghai" -->
<!-- > -->
<!-- <el-radio-button :label="1"></el-radio-button> -->
<!-- <el-radio-button :label="0"></el-radio-button> -->
<!-- </el-radio-group> -->
<!-- 2025-12-29 新需求 修改成下拉选 -->
<el-select
clearable
filterable
style="width: 100%"
placeholder="请选择"
v-model="addOrEditForm.isShanghai"
>
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
<el-option
:key="item.value"
:label="item.label"
:value="item.value"
v-for="item in dict.type.project_action"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
@ -145,7 +160,7 @@
clearable
maxlength="60"
show-word-limit
placeholder="请输入总工程名称"
placeholder="请输入工程地址"
v-model="addOrEditForm.proAddress"
/>
</el-form-item>
@ -163,7 +178,7 @@
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<!-- <el-col :span="12">
<el-form-item label="项目部经度" prop="lon">
<el-input
clearable
@ -171,7 +186,7 @@
v-model="addOrEditForm.lon"
/>
</el-form-item>
</el-col>
</el-col> -->
<el-col :span="12">
<el-form-item label="计划竣工时间" prop="endTime">
<el-date-picker
@ -185,7 +200,7 @@
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<!-- <el-col :span="12">
<el-form-item label="项目部纬度" prop="lat">
<el-input
clearable
@ -193,7 +208,7 @@
v-model="addOrEditForm.lat"
/>
</el-form-item>
</el-col>
</el-col> -->
</el-row>
</el-form>
</div>
@ -209,7 +224,12 @@ import {
} from '@/utils/getCommonData'
export default {
name: 'AddOrEditForm',
dicts: ['project_status', 'project_type', 'voltage_level'],
dicts: [
'project_status',
'project_type',
'voltage_level',
'project_action',
],
components: { Treeselect },
props: {
//
@ -262,9 +282,10 @@ export default {
mainProId: '', // id
startTime: null, //
proAddress: '', //
isShanghai: 0, //
isShanghai: '', //
simpleName: '', //
},
isShanghaiOptions: [],
addOrEditFormRules: {
mainProId: [
{

View File

@ -31,18 +31,25 @@ export const formLabel = [
isShow: false, // 是否展示label
f_type: 'sel',
f_model: 'isShanghai',
f_label: '是否上海外项目',
f_label: '工程所在地',
f_selList: [
{
label: '是',
value: 1,
},
{
label: '否',
value: 0,
},
// {
// label: '是',
// value: 1,
// },
// {
// label: '否',
// value: 0,
// },
],
},
{
f_label: '创建时间',
f_model: 'createTime',
f_type: 'date',
f_width: '180px',
isShow: false, // 是否展示label
},
]
export const columnsList = [
@ -53,6 +60,7 @@ export const columnsList = [
{ t_props: 'volLevel', t_label: '电压等级' },
{ t_props: 'proAddress', t_label: '工程地址' },
{ t_slot: 'proStatus', t_label: '状态' },
{ t_props: 'createTime', t_label: '创建时间' },
]
export const dialogConfig = {

View File

@ -127,7 +127,7 @@ import {
} from '@/utils/getCommonData'
export default {
name: 'Lot-project',
dicts: ['project_type', 'project_status'],
dicts: ['project_type', 'project_status', 'project_action'],
components: {
TableModel,
DialogModel,
@ -343,6 +343,10 @@ export default {
}
})
}
if (item.f_model === 'isShanghai') {
item.f_selList = this.dict.type.project_action
}
})
},
}

View File

@ -69,6 +69,23 @@ export const formLabel = [
},
], // 状态列表
},
{
f_label: '红绿灯状态',
f_model: 'lightStatus',
f_type: 'sel',
f_width: '180px',
isShow: false, // 是否展示label
f_selList: [
{
label: '绿灯',
value: '2',
},
{
label: '黄灯',
value: '1',
},
], // 状态列表
},
]
export const columnsList = [

View File

@ -63,7 +63,7 @@
icon="el-icon-setting"
@click="onHandleShanghaiPersonMultiEngineSetting()"
>
上海人员多工程设置
人员同时入场工程设置
</el-button>
<el-button
@ -467,9 +467,9 @@ export default {
}
},
//
//
onHandleShanghaiPersonMultiEngineSetting() {
this.dialogConfig.outerTitle = '上海人员多工程设置'
this.dialogConfig.outerTitle = '人员同时入场工程设置'
this.dialogConfig.outerWidth = '90%'
this.dialogConfig.minHeight = '90vh'
this.dialogConfig.maxHeight = '90vh'
@ -484,7 +484,7 @@ export default {
})
},
//
//
onHandleOpenShanghaiProSetting(idNumber) {
this.dialogConfig.outerVisible = false
this.onHandleShanghaiPersonMultiEngineSetting()

View File

@ -1,5 +1,5 @@
<template>
<!-- 施工人员 ---- 出入场管理 ---- 上海人员多工程设置 -->
<!-- 施工人员 ---- 出入场管理 ---- 人员同时入场工程设置 -->
<div class="container">
<div class="shanghai-pro-setting-step1" v-if="currentStep === 1">
<el-form
@ -19,7 +19,7 @@
</el-form>
<div class="content">
<span> 上海人员多工程设置 </span>
<span> 人员同时入场工程设置 </span>
<span> 1. 请确保该人员已经入场一个上海工程 </span>
<span>
2.
@ -53,10 +53,10 @@
新增入场工程
</el-button>
<div class="title"> 上海人员多工程设置明细 </div>
<div class="title"> 人员同时入场工程设置明细 </div>
<div class="content-detail">
<span> 上海人员多工程设置 </span>
<span> 人员同时入场工程设置 </span>
<span> 1. 请确保该人员已经入场一个上海工程 </span>
<span>
2.

View File

@ -0,0 +1,250 @@
<template>
<el-card class="tree-card" shadow="hover">
<div class="tree-container">
<div class="head-container">
<el-input
v-model="filterText"
placeholder="请输入关键字"
clearable
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
</div>
<el-tree
:data="treeData"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
>
<span
class="custom-tree-node"
:class="getNodeClass(node.data)"
slot-scope="{ node }"
>
<span class="node-content">
<span
v-if="node.data.level == 2"
class="status-dot"
:class="getStatusDotClass(node.data)"
>
</span>
<el-tooltip
:content="node.label"
placement="top"
:disabled="!isTextOverflow(node.label)"
>
<span
class="node-label"
:class="getNodeLabelClass(node.data)"
>
{{ node.label }}
</span>
</el-tooltip>
</span>
</span>
</el-tree>
</div>
</el-card>
</template>
<script>
import { getProjectAndMacTreeAPI } from '@/api/system/attMacManage.js'
export default {
name: 'LeftTree',
data() {
return {
filterText: '',
treeData: [],
defaultProps: {
children: 'children',
label: 'name',
},
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
},
},
created() {
this.getTreeData()
},
methods: {
//
async getTreeData() {
try {
const res = await getProjectAndMacTreeAPI()
if (res.code === 200) {
this.treeData = res.data || []
}
} catch (error) {
console.error('获取树形数据失败:', error)
}
},
//
filterNode(value, data, node) {
if (!value) return true
// true
if (data.name && data.name.indexOf(value) !== -1) {
return true
}
//
//
let parent = node.parent
while (parent && parent.data) {
if (
parent.data.name &&
parent.data.name.indexOf(value) !== -1
) {
return true
}
parent = parent.parent
}
return false
},
//
handleNodeClick(data) {
this.$emit('node-click', data)
},
//
getNodeClass(data) {
if (data.level === 2 && data.onLine === 1) {
return 'node-online'
}
return ''
},
//
getStatusDotClass(data) {
if (data.level == 2) {
if (data.onLine == 1) {
return 'status-dot-online'
} else {
return 'status-dot-offline'
}
}
return ''
},
getNodeLabelClass(data) {
if (data.level == 2) {
if (data.onLine == 1) {
return 'node-label-online'
} else {
return 'node-label-offline'
}
}
return ''
},
/**
* 判断文本是否溢出
* 业务背景当节点名称过长时需要显示 tooltip 提示完整名称
* 设计决策通过检查文本长度来判断是否需要显示 tooltip避免短文本也显示提示
* @param {string} text - 节点文本内容
* @returns {boolean} 是否溢出
*/
isTextOverflow(text) {
if (!text) return false
// 20
//
return text.length > 20
},
},
}
</script>
<style scoped lang="scss">
.tree-card {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
::v-deep .el-card__body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 20px;
min-height: 0;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
}
.tree-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
.head-container {
margin-bottom: 10px;
flex-shrink: 0;
}
}
::v-deep .el-tree {
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.node-content {
display: flex;
align-items: center;
gap: 6px;
}
.status-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.status-dot-online {
background-color: #67c23a;
box-shadow: 0 0 4px rgba(103, 194, 58, 0.6);
}
.node-label-online {
color: #67c23a;
}
.status-dot-offline {
background-color: #f56c6c;
box-shadow: 0 0 4px rgba(245, 108, 108, 0.6);
}
.node-label {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
max-width: 100%;
}
&.node-online {
.node-label {
color: #67c23a;
font-weight: 500;
}
}
}
}
</style>

View File

@ -0,0 +1,813 @@
<template>
<div style="height: 100%; overflow: hidden">
<el-card class="table-card" shadow="hover">
<div class="table-container">
<TableModel
:formLabel="formLabel"
:columnsList="columnsList"
:request-api="requestApi"
:showOperation="true"
:isSelectShow="true"
:sendParams="sendParams"
:isIndexShow="false"
ref="tableRef"
@selection-change="handleSelectionChange"
>
<template slot="btn">
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
:disabled="selectedData.length === 0"
@click="handleBatchDelete"
>
批量删除
</el-button>
<el-button
size="mini"
type="primary"
icon="el-icon-download"
@click="handleSendDown"
>
下发
</el-button>
<el-button
size="mini"
type="success"
icon="el-icon-refresh"
:disabled="refreshCountdown > 0"
@click="handleRefresh"
>
{{
refreshCountdown > 0
? `刷新(${refreshCountdown}s)`
: '刷新'
}}
</el-button>
</template>
<template slot="handle" slot-scope="{ data }">
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
@click="handleDelete(data)"
>
删除
</el-button>
</template>
<template slot="faceImage" slot-scope="{ data }">
<ImagePreview
:src="data.faceImage"
height="60px"
width="60px"
/>
</template>
<template slot="isOnDataBase" slot-scope="{ data }">
<el-tag
v-if="data.isOnDataBase == 1"
size="mini"
type="success"
>
在库
</el-tag>
<el-tag
v-if="data.isOnDataBase == 0"
size="mini"
type="danger"
>
不在库
</el-tag>
</template>
</TableModel>
</div>
</el-card>
<!-- 下发弹框 -->
<DialogModel
:dialogConfig="sendDownDialogConfig"
@closeDialogOuter="handleCloseSendDownDialog"
>
<template slot="outerContent">
<el-form
ref="sendDownFormRef"
:model="sendDownFormData"
:rules="sendDownFormRules"
label-width="120px"
>
<el-form-item
:label="
sendDownFormData.allSelect ? '取消全选' : '全选'
"
>
<el-checkbox
v-model="allSelect"
@change="handleAllSelectChange"
>
{{ `${allSelect ? '取消全选' : '全选'}` }}
</el-checkbox>
</el-form-item>
<el-form-item label="未下发人员:" prop="unSendPersonIds">
<el-checkbox-group
v-model="sendDownFormData.unSendPersonIds"
@change="handleUnSendPersonChange"
>
<el-checkbox
:key="item.id"
:label="item.id"
v-for="item in unSendPersonList"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="已下发人员:" prop="sentPersonIds">
<el-checkbox-group
v-model="sendDownFormData.sentPersonIds"
@change="handleSentPersonChange"
>
<el-checkbox
:key="item.id"
:label="item.id"
v-for="item in sentPersonList"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
<el-row class="dialog-footer-btn">
<el-button size="medium" @click="handleCloseSendDownDialog">
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="handleSendDownSubmit"
>
确定
</el-button>
</el-row>
</template>
</DialogModel>
<!-- 配置弹框 -->
<DialogModel
:dialogConfig="configDialogConfig"
@closeDialogOuter="handleCloseConfigDialog"
>
<template slot="outerContent">
<el-form
ref="configFormRef"
:model="configFormData"
:rules="configFormRules"
label-width="120px"
>
<el-form-item label="选择人员:" prop="workerIds">
<el-select
v-model="configFormData.workerIds"
multiple
filterable
placeholder="请选择人员"
style="width: 100%"
:loading="personListLoading"
>
<el-option
v-for="item in personList"
:key="item.id"
:label="`${item.name}(${item.idNumber})`"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="配置项:" prop="configItem">
<el-input
v-model="configFormData.configItem"
type="textarea"
:autosize="{ minRows: 4, maxRows: 8 }"
placeholder="请输入配置项"
clearable
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-form>
<el-row class="dialog-footer-btn">
<el-button size="medium" @click="handleCloseConfigDialog">
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="handleConfigSubmit"
>
确定
</el-button>
</el-row>
</template>
</DialogModel>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import DialogModel from '@/components/DialogModel'
import {
getPersonListByMacNoAPI,
getAllPersonListAPI,
deletePersonAPI,
batchDeletePersonAPI,
refreshAPI,
restartAPI,
sendDownAPI,
configAPI,
} from '@/api/system/attMacManage.js'
export default {
name: 'RightTable',
components: {
TableModel,
DialogModel,
},
props: {
macNo: {
type: String,
default: '',
},
proId: {
type: [String, Number],
default: '',
},
subId: {
type: [String, Number],
default: '',
},
teamId: {
type: [String, Number],
default: '',
},
},
data() {
return {
//
formLabel: [
{
f_label: '关键字',
f_model: 'keyWord',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '人员编号',
f_model: 'userId',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '是否在库',
f_model: 'isOnDataBase',
f_type: 'sel',
f_width: '180px',
f_selList: [
{
label: '在库',
value: '1',
},
{
label: '不在库',
value: '0',
},
],
},
],
//
columnsList: [
{
t_label: '人员编号',
t_props: 'userId',
},
{
t_label: '姓名',
t_props: 'userName',
},
{
t_label: '考勤机编号',
t_props: 'devCode',
},
{
t_label: '人脸图片',
t_slot: 'faceImage',
},
{
t_label: '是否在库',
t_slot: 'isOnDataBase',
},
{
t_label: '更新时间',
t_props: 'updateTime',
},
],
//
sendDownDialogConfig: {
outerVisible: false,
outerTitle: '下发',
outerWidth: '50%',
maxHeight: '80vh',
},
//
configDialogConfig: {
outerVisible: false,
outerTitle: '配置',
outerWidth: '50%',
maxHeight: '80vh',
},
//
sendDownFormData: {
workerIds: [],
//
unSendPersonIds: [],
//
sentPersonIds: [],
},
//
configFormData: {
workerIds: [],
configItem: '',
},
//
sendDownFormRules: {
unSendPersonIds: [
{
required: true,
message: '请选择人员',
trigger: 'change',
},
],
},
//
configFormRules: {
unSendPersonList: [
{
required: true,
message: '请选择人员',
trigger: 'change',
},
],
configItem: [
{
required: true,
message: '请输入配置项',
trigger: 'blur',
},
],
},
//
personList: [],
personListLoading: false,
allSelect: false,
selectedData: [],
//
unSendPersonList: [],
//
sentPersonList: [],
//
refreshCountdown: 0,
//
refreshTimer: null,
//
restartCountdown: 0,
//
restartTimer: null,
}
},
computed: {
// 使API
requestApi() {
return this.macNo
? getPersonListByMacNoAPI
: getPersonListByMacNoAPI
},
//
sendParams() {
return {
deviceCode: this.macNo || '',
proId: this.proId || '',
}
},
},
watch: {
macNo: {
handler() {
//
this.$nextTick(() => {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
})
},
immediate: true,
},
},
/**
* 组件销毁前清理定时器
* 业务背景避免组件销毁后定时器仍在运行导致的内存泄漏
* 设计决策在组件销毁前清除所有定时器
*/
beforeDestroy() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
if (this.restartTimer) {
clearInterval(this.restartTimer)
this.restartTimer = null
}
},
methods: {
//
getTableList() {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
},
//
handleDelete(row) {
this.$modal
.confirm('确定要删除该人员吗?')
.then(() => {
deletePersonAPI({
deviceCode: this.macNo,
workerIds: [row.userId],
})
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
//
// this.handleRefresh()
this.getTableList()
}
})
.catch(() => {})
})
.catch(() => {})
},
//
handleBatchDelete() {
if (this.selectedData.length === 0) {
this.$modal.msgWarning('请选择要删除的数据')
return
}
this.$modal
.confirm(
'确定要删除选中的 ' +
this.selectedData.length +
' 条数据吗?',
)
.then(() => {
const ids = this.selectedData.map((item) => item.userId)
deletePersonAPI({
deviceCode: this.macNo,
workerIds: ids,
})
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('批量删除成功')
// this.handleRefresh()
this.getTableList()
}
})
.catch(() => {})
})
.catch(() => {})
},
//
handleSendDown() {
if (!this.macNo) {
this.$modal.msgWarning('请先选择考勤机')
return
}
this.sendDownDialogConfig.outerVisible = true
this.resetSendDownForm()
this.getPersonList()
},
//
handleConfig() {
if (!this.macNo) {
this.$modal.msgWarning('请先选择考勤机')
return
}
this.configDialogConfig.outerVisible = true
this.resetConfigForm()
this.getPersonList()
},
//
async getPersonList() {
this.personListLoading = true
try {
const res = await getAllPersonListAPI({
proId: this.proId,
deviceCode: this.macNo,
subId: this.subId,
teamId: this.teamId,
})
if (res.code === 200) {
// this.unSendPersonList = res?.data.map((item) => ({
// id: item.workerId,
// name: item.workerName,
// isSelected: false,
// }))
this.unSendPersonList = res?.data
.filter((item) => item.isIssue == 0)
.map((item) => ({
id: item.workerId,
name: item.workerName,
isSelected: false,
}))
this.sentPersonList = res?.data
.filter((item) => item.isIssue == 1)
.map((item) => ({
id: item.workerId,
name: item.workerName,
isSelected: false,
}))
}
} catch (error) {
console.error('获取人员列表失败:', error)
} finally {
this.personListLoading = false
}
},
//
handleCloseSendDownDialog() {
this.sendDownDialogConfig.outerVisible = false
this.resetSendDownForm()
},
/**
* 重置下发表单
* 业务背景关闭弹框或重新打开时需要清空表单数据
* 设计决策需要重置所有表单字段包括未下发和已下发人员ID数组避免 undefined 导致的错误
*/
resetSendDownForm() {
this.sendDownFormData = {
workerIds: [],
//
unSendPersonIds: [],
//
sentPersonIds: [],
}
this.allSelect = false
if (this.$refs.sendDownFormRef) {
this.$refs.sendDownFormRef.resetFields()
}
},
/**
* 提交下发表单
* 业务背景将选中的未下发人员下发到考勤机
* 设计决策使用 unSendPersonIds 作为提交参数因为表单绑定的是该字段
*/
handleSendDownSubmit() {
this.$refs.sendDownFormRef.validate((valid) => {
if (valid) {
const params = {
deviceCode: this.macNo,
workerIds: this.sendDownFormData.unSendPersonIds,
}
sendDownAPI(params)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('下发成功')
this.handleCloseSendDownDialog()
// this.handleRefresh()
this.getTableList()
}
})
.catch(() => {})
}
})
},
//
handleCloseConfigDialog() {
this.configDialogConfig.outerVisible = false
this.resetConfigForm()
},
//
resetConfigForm() {
this.configFormData = {
workerIds: [],
configItem: '',
}
if (this.$refs.configFormRef) {
this.$refs.configFormRef.resetFields()
}
},
//
handleConfigSubmit() {
this.$refs.configFormRef.validate((valid) => {
if (valid) {
const params = {
macNo: this.macNo,
workerIds: this.configFormData.workerIds,
configItem: this.configFormData.configItem,
}
configAPI(params)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('配置成功')
this.handleCloseConfigDialog()
this.getTableList()
this.$emit('refresh-tree')
}
})
.catch(() => {})
}
})
},
/**
* 刷新考勤机
* 业务背景刷新考勤机数据获取最新的人员信息
* 设计决策刷新成功后启动10秒倒计时防止频繁刷新对服务器造成压力
*/
handleRefresh() {
if (!this.macNo) {
this.$modal.msgWarning('请先选择考勤机')
return
}
//
if (this.refreshCountdown > 0) {
return
}
refreshAPI(this.macNo)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('刷新成功')
this.getTableList()
//
this.startRefreshCountdown()
}
})
.catch(() => {})
},
/**
* 启动刷新倒计时
* 业务背景刷新成功后需要等待10秒才能再次刷新
* 设计决策使用定时器每秒更新倒计时倒计时结束后清除定时器
*/
startRefreshCountdown() {
//
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
// 10
this.refreshCountdown = 10
// 1
this.refreshTimer = setInterval(() => {
this.refreshCountdown--
if (this.refreshCountdown <= 0) {
//
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
}, 1000)
},
/**
* 重启考勤机
* 业务背景重启考勤机设备恢复设备状态
* 设计决策重启成功后启动10秒倒计时防止频繁重启对设备造成损害
*/
handleRestart() {
if (!this.macNo) {
this.$modal.msgWarning('请先选择考勤机')
return
}
//
if (this.restartCountdown > 0) {
return
}
this.$modal
.confirm('确定要重启该考勤机吗?')
.then(() => {
restartAPI(this.macNo)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('重启成功')
//
this.startRestartCountdown()
}
})
.catch(() => {})
})
.catch(() => {})
},
/**
* 启动重启倒计时
* 业务背景重启成功后需要等待10秒才能再次重启
* 设计决策使用定时器每秒更新倒计时倒计时结束后清除定时器
*/
startRestartCountdown() {
//
if (this.restartTimer) {
clearInterval(this.restartTimer)
this.restartTimer = null
}
// 10
this.restartCountdown = 10
// 1
this.restartTimer = setInterval(() => {
this.restartCountdown--
if (this.restartCountdown <= 0) {
//
clearInterval(this.restartTimer)
this.restartTimer = null
}
}, 1000)
},
//
handleAllSelectChange(val) {
if (val) {
this.sendDownFormData.unSendPersonIds =
this.unSendPersonList.map((item) => item.id)
this.sendDownFormData.sentPersonIds = this.sentPersonList.map(
(item) => item.id,
)
} else {
this.sendDownFormData.unSendPersonIds = []
this.sendDownFormData.sentPersonIds = []
}
},
//
handleUnSendPersonChange(value) {
if (
value.length == this.unSendPersonList.length &&
this.sendDownFormData.sentPersonIds.length ==
this.sentPersonList.length
) {
this.allSelect = true
} else {
this.allSelect = false
}
},
//
handleSentPersonChange(value) {
if (
value.length == this.sentPersonList.length &&
this.sendDownFormData.unSendPersonIds.length ==
this.unSendPersonList.length
) {
this.allSelect = true
} else {
this.allSelect = false
}
},
handleSelectionChange(e) {
this.selectedData = e
},
},
}
</script>
<style scoped lang="scss">
.table-card {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
::v-deep .el-card__body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 20px;
min-height: 0;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
}
.table-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
height: 0; // flex: 1 使
}
.dialog-footer-btn {
text-align: right;
padding-top: 20px;
}
</style>

View File

@ -0,0 +1,274 @@
<template>
<div style="height: 100%; overflow: hidden">
<el-card class="table-card" shadow="hover">
<div class="table-container">
<TableModel
:formLabel="formLabel"
:columnsList="columnsList"
:request-api="requestApi"
:showOperation="false"
:isSelectShow="true"
:sendParams="sendParams"
:isIndexShow="false"
ref="tableRef"
:pageSizes="[100, 200, 500]"
@selection-change="handleSelectionChange"
>
<template slot="btn">
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
:disabled="selectedData.length === 0"
@click="handleBatchDelete"
>
批量删除
</el-button>
</template>
<template slot="transStatus" slot-scope="{ data }">
<el-tag
size="mini"
type="info"
v-if="data.transStatus == 0"
>
待执行
</el-tag>
<el-tag
size="mini"
type="primary"
v-if="data.transStatus == 1"
>
执行中
</el-tag>
<el-tag
size="mini"
type="success"
v-if="data.transStatus == 2"
>
已完成
</el-tag>
<el-tag
size="mini"
type="danger"
v-if="data.transStatus == 3"
>
任务繁忙-人员占用
</el-tag>
<el-tag
size="mini"
type="danger"
v-if="
data.transStatus == 4 || data.transStatus == 5
"
>
失败
</el-tag>
</template>
</TableModel>
</div>
</el-card>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import {
getTaskHistoryListAPI,
batchDeleteTaskAPI,
} from '@/api/system/attMacManage.js'
export default {
name: 'TaskHistoryList',
components: {
TableModel,
},
props: {
macNo: {
type: String,
default: '',
},
proId: {
type: [String, Number],
default: '',
},
},
data() {
return {
//
formLabel: [
{
f_label: '任务编码',
f_model: 'cmdCode',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '任务名称',
f_model: 'cmdName',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '执行状态',
f_model: 'transStatus',
f_type: 'sel',
f_width: '180px',
f_selList: [
{
label: '待执行',
value: '0',
},
{
label: '执行中',
value: '1',
},
{
label: '已完成',
value: '2',
},
{
label: '任务繁忙-人员占用',
value: '3',
},
{
label: '失败',
value: '4',
},
],
},
],
//
columnsList: [
{
t_label: '任务ID',
t_props: 'taskId',
},
{
t_label: '任务编号',
t_props: 'cmdCode',
},
{
t_label: '任务名称',
t_props: 'cmdName',
},
{
t_label: '请求参数',
t_props: 'cmdParam',
},
{
t_label: '执行时间',
t_props: 'exeTime',
},
{
t_label: '创建时间',
t_props: 'createTime',
},
{
t_label: '状态',
t_slot: 'transStatus',
},
{
t_label: '异常内容',
t_props: 'msg',
},
],
selectedData: [],
}
},
computed: {
// API
requestApi() {
return getTaskHistoryListAPI
},
//
sendParams() {
return {
deviceCode: this.macNo || '',
pageSize: 100,
}
},
},
watch: {
macNo: {
handler() {
//
this.$nextTick(() => {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
})
},
immediate: true,
},
},
methods: {
//
getTableList() {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
},
handleSelectionChange(val) {
this.selectedData = val
},
handleBatchDelete() {
if (this.selectedData.length === 0) {
this.$modal.msgWarning('请选择要删除的数据')
return
}
this.$modal
.confirm(
'确定要删除选中的 ' +
this.selectedData.length +
' 条数据吗?',
)
.then(() => {
const ids = this.selectedData.map((item) => item.taskId)
batchDeleteTaskAPI({
taskId: ids.join(','),
})
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('批量删除成功')
this.$refs.tableRef.getTableList()
}
})
.catch(() => {})
})
.catch(() => {})
},
},
}
</script>
<style scoped lang="scss">
.table-card {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
::v-deep .el-card__body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 20px;
min-height: 0;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
}
.table-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
height: 0; // flex: 1 使
}
</style>

View File

@ -0,0 +1,271 @@
<template>
<div style="height: 100%; overflow: hidden">
<el-card class="table-card" shadow="hover">
<div class="table-container">
<TableModel
:formLabel="formLabel"
:columnsList="columnsList"
:request-api="requestApi"
:showOperation="false"
:isSelectShow="true"
:isIndexShow="false"
:sendParams="sendParams"
:pageSizes="[100, 200, 500]"
ref="tableRef"
@selection-change="handleSelectionChange"
>
<template slot="btn">
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
:disabled="selectedData.length === 0"
@click="handleBatchDelete"
>
批量删除
</el-button>
</template>
<template slot="transStatus" slot-scope="{ data }">
<el-tag
size="mini"
type="info"
v-if="data.transStatus == 0"
>
待执行
</el-tag>
<el-tag
size="mini"
type="primary"
v-if="data.transStatus == 1"
>
执行中
</el-tag>
<el-tag
size="mini"
type="success"
v-if="data.transStatus == 2"
>
已完成
</el-tag>
<el-tag
size="mini"
type="danger"
v-if="data.transStatus == 3"
>
任务繁忙-人员占用
</el-tag>
<el-tag
size="mini"
type="danger"
v-if="
data.transStatus == 4 || data.transStatus == 5
"
>
失败
</el-tag>
</template>
</TableModel>
</div>
</el-card>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import { getTaskListAPI, deleteTaskAPI } from '@/api/system/attMacManage.js'
export default {
name: 'TaskHistoryList',
components: {
TableModel,
},
props: {
macNo: {
type: String,
default: '',
},
proId: {
type: [String, Number],
default: '',
},
},
data() {
return {
//
formLabel: [
{
f_label: '任务编码',
f_model: 'cmdCode',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '任务名称',
f_model: 'cmdName',
f_type: 'ipt',
f_width: '180px',
},
{
f_label: '执行状态',
f_model: 'transStatus',
f_type: 'sel',
f_width: '180px',
f_selList: [
{
label: '待执行',
value: '0',
},
{
label: '执行中',
value: '1',
},
{
label: '已完成',
value: '2',
},
{
label: '任务繁忙-人员占用',
value: '3',
},
{
label: '失败',
value: '4',
},
],
},
],
//
columnsList: [
{
t_label: '任务ID',
t_props: 'taskId',
},
{
t_label: '任务编号',
t_props: 'cmdCode',
},
{
t_label: '任务名称',
t_props: 'cmdName',
},
{
t_label: '请求参数',
t_props: 'cmdParam',
},
{
t_label: '执行时间',
t_props: 'exeTime',
},
{
t_label: '创建时间',
t_props: 'createTime',
},
{
t_label: '状态',
t_slot: 'transStatus',
},
{
t_label: '异常内容',
t_props: 'msg',
},
],
selectedData: [],
}
},
computed: {
// API
requestApi() {
return getTaskListAPI
},
//
sendParams() {
return {
deviceCode: this.macNo || '',
pageSize: 100,
}
},
},
watch: {
macNo: {
handler() {
//
this.$nextTick(() => {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
})
},
immediate: true,
},
},
methods: {
//
getTableList() {
if (this.$refs.tableRef) {
this.$refs.tableRef.getTableList()
}
},
handleSelectionChange(val) {
this.selectedData = val
},
handleBatchDelete() {
// console.log(this.selectedData)
if (this.selectedData.length === 0) {
this.$modal.msgWarning('请选择要删除的数据')
return
}
this.$modal
.confirm(
'确定要删除选中的 ' +
this.selectedData.length +
' 条数据吗?',
)
.then(() => {
const ids = this.selectedData.map((item) => item.taskId)
deleteTaskAPI({
taskId: ids.join(','),
})
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('批量删除成功')
this.$refs.tableRef.getTableList()
}
})
.catch(() => {})
})
.catch(() => {})
},
},
}
</script>
<style scoped lang="scss">
.table-card {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
::v-deep .el-card__body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 20px;
min-height: 0;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
}
.table-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
height: 0; // flex: 1 使
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div class="app-container">
<el-row :gutter="10">
<!-- 左侧树形组件 -->
<el-col :span="6" :xs="24">
<leftTree ref="leftTreeRef" @node-click="handleNodeClick" />
</el-col>
<!-- 右侧表格组件 -->
<el-col :span="18" :xs="24">
<div class="right-content">
<!-- 切换按钮 -->
<div class="tab-switch">
<div class="tab-switch-left">
<el-radio-group v-model="activeTab" size="medium">
<el-radio-button label="person">
人员列表
</el-radio-button>
<el-radio-button label="task">
任务列表
</el-radio-button>
<el-radio-button label="taskHistory">
任务历史
</el-radio-button>
</el-radio-group>
</div>
<div class="tab-switch-right">
<div class="selected-node-info">
<i class="el-icon-location-outline"></i>
<span class="label">当前节点</span>
<span class="value">{{
selectedNodeName || '未选择'
}}</span>
</div>
</div>
</div>
<div class="right-content-table">
<component
:is="currentComponent"
ref="currentTableRef"
:mac-no="selectedMacNo"
:pro-id="selectedProId"
:sub-id="selectedSubId"
:team-id="selectedTeamId"
@refresh-tree="handleRefreshTree"
/>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import leftTree from './components/leftTree.vue'
import rightTable from './components/rightTable.vue'
import taskList from './components/taskList.vue'
import taskHistoryList from './components/taskHistoryList.vue'
export default {
name: 'AttMacManage',
components: {
leftTree,
rightTable,
taskList,
taskHistoryList,
},
data() {
return {
selectedMacNo: '', //
selectedProId: '', // id
selectedSubId: '', // id
selectedTeamId: '', // id
selectedNodeName: '', //
activeTab: 'person', //
}
},
computed: {
//
currentComponent() {
const componentMap = {
person: 'rightTable',
task: 'taskList',
taskHistory: 'taskHistoryList',
}
return componentMap[this.activeTab] || 'rightTable'
},
},
methods: {
//
handleNodeClick(data) {
console.log('data选择的节点', data)
this.selectedMacNo = data.id
this.selectedProId = data.proId
this.selectedSubId = data.subId
this.selectedTeamId = data.teamId
this.selectedNodeName = data.name
// if (data.level === 2) {
// //
// this.selectedMacNo = data.id
// } else {
// //
// this.selectedMacNo = ''
// }
//
this.$nextTick(() => {
this.refreshCurrentTable()
})
},
//
refreshCurrentTable() {
const ref = this.$refs.currentTableRef
if (ref && ref.getTableList) {
ref.getTableList()
}
},
//
handleTabChange(val) {
console.log('val', val)
//
// this.$nextTick(() => {
// this.refreshCurrentTable()
// })
},
//
handleRefreshTree() {
if (this.$refs.leftTreeRef) {
this.$refs.leftTreeRef.getTreeData()
}
},
},
}
</script>
<style scoped lang="scss">
.app-container {
// height: calc(100vh - 120px);
display: flex;
flex-direction: column;
}
::v-deep .el-row {
flex: 1;
display: flex;
min-height: 0;
}
::v-deep .el-col {
display: flex;
flex-direction: column;
min-height: 0;
}
.right-content {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.tab-switch {
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
margin-bottom: 10px;
padding: 12px 20px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
}
.tab-switch-left {
flex: 1;
}
.tab-switch-right {
margin-left: 20px;
flex-shrink: 0;
}
.selected-node-info {
display: flex;
align-items: center;
padding: 6px 16px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 20px;
font-size: 14px;
color: #606266;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
i {
font-size: 16px;
color: #409eff;
margin-right: 6px;
}
.label {
color: #909399;
margin-right: 4px;
font-weight: 500;
}
.value {
color: #303133;
font-weight: 600;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.right-content-table {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
::v-deep .el-radio-group {
.el-radio-button__inner {
padding: 10px 20px;
}
}
</style>

View File

@ -0,0 +1,388 @@
<template>
<div class="app-container">
<el-card class="table-card" shadow="hover">
<div slot="header" class="card-header">
<span>App版本管理</span>
</div>
<div class="table-container">
<!-- 操作按钮 -->
<div class="toolbar">
<el-button
type="primary"
icon="el-icon-plus"
size="small"
@click="handleAdd"
>
新增
</el-button>
</div>
<!-- 表格 -->
<el-table
v-loading="loading"
:data="appVersionList"
border
fit
highlight-current-row
style="width: 100%"
:max-height="tableHeight"
>
<el-table-column
label="序号"
align="center"
width="80"
type="index"
>
<template slot-scope="scope">
<span>{{
(queryParams.pageNum - 1) *
queryParams.pageSize +
scope.$index +
1
}}</span>
</template>
</el-table-column>
<el-table-column
label="版本号"
align="center"
prop="version"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
label="更新内容"
align="center"
prop="updateContent"
min-width="300"
:show-overflow-tooltip="true"
/>
<el-table-column
label="更新时间"
align="center"
prop="updateTime"
width="180"
>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
width="180"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>
修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</el-card>
<!-- 新增/编辑对话框 -->
<el-dialog
:title="dialogTitle"
:visible.sync="dialogVisible"
width="600px"
@close="handleDialogClose"
>
<el-form
ref="appVersionForm"
:model="formData"
:rules="formRules"
label-width="100px"
>
<el-form-item label="版本号" prop="version">
<el-input
maxlength="20"
v-model="formData.version"
placeholder="请输入版本号1.0.0"
/>
</el-form-item>
<el-form-item label="更新内容" prop="updateContent">
<el-input
type="textarea"
maxlength="500"
show-word-limit
placeholder="请输入更新内容"
v-model="formData.updateContent"
:autosize="{ minRows: 4, maxRows: 8 }"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listAppVersion,
getAppVersion,
addAppVersion,
updateAppVersion,
delAppVersion,
} from '@/api/system/appManage'
import Pagination from '@/components/Pagination'
/**
* App版本管理组件
* 业务背景用于管理移动端App的版本信息记录每次更新的内容和版本号支持Android和iOS平台的自动更新
* 设计决策采用简单的列表+表单模式不依赖封装的TableModel组件保持代码简洁
*/
export default {
name: 'AppManage',
components: {
Pagination,
},
data() {
return {
//
loading: false,
//
appVersionList: [],
//
total: 0,
//
tableHeight: 600,
//
queryParams: {
pageNum: 1,
pageSize: 10,
},
//
dialogVisible: false,
//
dialogTitle: '新增版本',
//
isAdd: true,
//
formData: {
id: null,
version: '',
platform: '',
updateContent: '',
},
//
formRules: {
version: [
{
required: true,
message: '请输入版本号',
trigger: 'blur',
},
],
platform: [
{
required: true,
message: '请选择平台类型',
trigger: 'change',
},
],
updateContent: [
{
required: true,
message: '请输入更新内容',
trigger: 'blur',
},
],
},
}
},
created() {
this.getList()
},
methods: {
/**
* 获取列表数据
* 业务背景加载App版本列表支持分页查询
*/
getList() {
this.loading = true
listAppVersion(this.queryParams)
.then((res) => {
if (res.code === 200) {
this.appVersionList = res.rows || []
this.total = res.total || 0
}
})
.catch(() => {})
.finally(() => {
this.loading = false
})
},
/**
* 新增版本
* 业务背景打开新增对话框初始化表单数据
*/
handleAdd() {
this.isAdd = true
this.dialogTitle = '新增版本'
this.dialogVisible = true
this.resetForm()
},
/**
* 修改版本
* 业务背景打开编辑对话框加载当前版本数据
* @param {Object} row - 当前行数据
*/
handleUpdate(row) {
this.isAdd = false
this.dialogTitle = '修改版本'
this.dialogVisible = true
getAppVersion(row.id)
.then((res) => {
if (res.code === 200) {
this.formData = {
id: res.data.id,
version: res.data.version,
platform: res.data.platform,
updateContent: res.data.updateContent,
}
}
})
.catch(() => {})
},
/**
* 删除版本
* 业务背景删除指定的App版本记录
* @param {Object} row - 当前行数据
*/
handleDelete(row) {
this.$modal
.confirm('确定要删除该版本记录吗?')
.then(() => {
delAppVersion(row.id)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
this.getList()
}
})
.catch(() => {})
})
.catch(() => {})
},
/**
* 提交表单
* 业务背景保存新增或修改的版本信息
*/
handleSubmit() {
this.$refs.appVersionForm.validate((valid) => {
if (valid) {
const api = this.isAdd ? addAppVersion : updateAppVersion
api(this.formData)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess(
this.isAdd ? '新增成功' : '修改成功',
)
this.dialogVisible = false
this.getList()
}
})
.catch(() => {})
}
})
},
/**
* 重置表单
* 业务背景清空表单数据用于新增或关闭对话框时
*/
resetForm() {
this.formData = {
id: null,
version: '',
platform: '',
updateContent: '',
}
if (this.$refs.appVersionForm) {
this.$refs.appVersionForm.resetFields()
}
},
/**
* 对话框关闭事件
* 业务背景关闭对话框时重置表单避免数据残留
*/
handleDialogClose() {
this.resetForm()
},
},
}
</script>
<style scoped lang="scss">
.app-container {
padding: 20px;
}
.table-card {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
::v-deep .el-card__body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 20px;
min-height: 0;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
}
.table-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
height: 0; // flex: 1 使
}
.toolbar {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.dialog-footer {
text-align: right;
}
</style>

View File

@ -89,9 +89,25 @@ export default {
}
},
//
filterNode(value, data) {
filterNode(value, data, node) {
if (!value) return true
return data.name.indexOf(value) !== -1
// true
if (data.name && data.name.indexOf(value) !== -1) {
return true
}
//
//
let parent = node.parent
while (parent && parent.data) {
if (
parent.data.name &&
parent.data.name.indexOf(value) !== -1
) {
return true
}
parent = parent.parent
}
return false
},
//
handleNodeClick(data) {

View File

@ -467,7 +467,7 @@ export default {
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
//
this.handleRefresh()
// this.handleRefresh()
this.getTableList()
}
})
@ -496,7 +496,7 @@ export default {
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('批量删除成功')
this.handleRefresh()
// this.handleRefresh()
this.getTableList()
}
})
@ -603,7 +603,7 @@ export default {
if (res.code === 200) {
this.$modal.msgSuccess('下发成功')
this.handleCloseSendDownDialog()
this.handleRefresh()
// this.handleRefresh()
this.getTableList()
}
})