arms-app 1.0.69 → 1.0.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/view/3 +199 -0
- package/view/index2.vue +482 -0
package/package.json
CHANGED
package/view/3
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 列拖拽示例页面:支持通过拖拽表头调整列顺序 -->
|
|
3
|
+
<section class="draggable-columns-table-page">
|
|
4
|
+
<!-- 标题与说明文案 -->
|
|
5
|
+
<h1>列拖拽表格</h1>
|
|
6
|
+
<p class="desc">通过拖拽表头,使用 sortablejs 实现列换位。</p>
|
|
7
|
+
|
|
8
|
+
<!-- 表格:通过 columns 数组驱动所有可拖拽列(含序号/操作列),rows 负责行数据 -->
|
|
9
|
+
<el-table
|
|
10
|
+
ref="draggableTable"
|
|
11
|
+
:key="tableKey"
|
|
12
|
+
:data="rows"
|
|
13
|
+
@sort-change="handleSortChange"
|
|
14
|
+
border
|
|
15
|
+
stripe
|
|
16
|
+
style="width: 100%"
|
|
17
|
+
height="420"
|
|
18
|
+
>
|
|
19
|
+
<!-- 所有列(包含序号列/业务列/操作列)均由 columns 数组统一驱动,可参与拖拽 -->
|
|
20
|
+
<el-table-column
|
|
21
|
+
v-for="col in columns"
|
|
22
|
+
:key="col.key || col.prop"
|
|
23
|
+
:prop="col.prop"
|
|
24
|
+
:label="col.label"
|
|
25
|
+
:width="col.width"
|
|
26
|
+
:min-width="col.minWidth"
|
|
27
|
+
:align="col.align || 'left'"
|
|
28
|
+
:header-align="col.headerAlign || col.align || 'left'"
|
|
29
|
+
:sortable="col.sortable"
|
|
30
|
+
>
|
|
31
|
+
<!-- 表头插槽:渲染拖拽手柄(handle),供 sortablejs 使用 -->
|
|
32
|
+
<template slot="header">
|
|
33
|
+
<div class="header-draggable">
|
|
34
|
+
<span class="header-label">{{ col.label }}</span>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
<!-- 单元格插槽:根据是否为操作列渲染不同内容 -->
|
|
38
|
+
<template slot-scope="scope">
|
|
39
|
+
<template v-if="col.isOperation">
|
|
40
|
+
<el-button type="text" size="mini" @click="onView(scope.row)">查看</el-button>
|
|
41
|
+
<el-button type="text" size="mini" @click="onEdit(scope.row)">编辑</el-button>
|
|
42
|
+
<el-button type="text" size="mini" @click="onDelete(scope.row)">删除</el-button>
|
|
43
|
+
</template>
|
|
44
|
+
<template v-else-if="col.isIndex">
|
|
45
|
+
<span>{{ scope.$index + 1 }}</span>
|
|
46
|
+
</template>
|
|
47
|
+
<template v-else>
|
|
48
|
+
<span>{{ scope.row[col.prop] }}</span>
|
|
49
|
+
</template>
|
|
50
|
+
</template>
|
|
51
|
+
</el-table-column>
|
|
52
|
+
</el-table>
|
|
53
|
+
</section>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
import Sortable from "sortablejs";
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
name: "DraggableColumnsTableView",
|
|
61
|
+
data() {
|
|
62
|
+
return {
|
|
63
|
+
// 表格行数据:示例客户信息(实际项目中可从接口或 Vuex 获取)
|
|
64
|
+
rows: [
|
|
65
|
+
{
|
|
66
|
+
id: 1,
|
|
67
|
+
name: "王小虎",
|
|
68
|
+
birthDate: "1990-03-15",
|
|
69
|
+
customerTag: "重点客户",
|
|
70
|
+
manager: "张三",
|
|
71
|
+
contribution: 12000,
|
|
72
|
+
pass1: 98,
|
|
73
|
+
pass2: 87,
|
|
74
|
+
pass3: 93,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 2,
|
|
78
|
+
name: "李小虎",
|
|
79
|
+
birthDate: "1992-07-21",
|
|
80
|
+
customerTag: "潜在客户",
|
|
81
|
+
manager: "李四",
|
|
82
|
+
contribution: 8600,
|
|
83
|
+
pass1: 88,
|
|
84
|
+
pass2: 90,
|
|
85
|
+
pass3: 85,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 3,
|
|
89
|
+
name: "赵六",
|
|
90
|
+
birthDate: "1988-11-02",
|
|
91
|
+
customerTag: "普通客户",
|
|
92
|
+
manager: "王五",
|
|
93
|
+
contribution: 5400,
|
|
94
|
+
pass1: 76,
|
|
95
|
+
pass2: 80,
|
|
96
|
+
pass3: 79,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
// 列配置:用于驱动 el-table-column 渲染,同时作为拖拽排序的数据源
|
|
100
|
+
columns: [
|
|
101
|
+
{ key: "index", label: "#", width: 60, align: "center", isIndex: true },
|
|
102
|
+
{ key: "name", prop: "name", label: "姓名", width: 160, align: "center" },
|
|
103
|
+
{ key: "birthDate", prop: "birthDate", label: "出生日期", width: 140, align: "center", sortable: "custom" },
|
|
104
|
+
{ key: "customerTag", prop: "customerTag", label: "客户标签", width: 120, align: "center" },
|
|
105
|
+
{ key: "manager", prop: "manager", label: "客户人", width: 160, align: "center" },
|
|
106
|
+
{ key: "contribution", prop: "contribution", label: "贡献积分", width: 120, align: "right", headerAlign: "center" },
|
|
107
|
+
{ key: "pass1", prop: "pass1", label: "通关1", width: 100, align: "center" },
|
|
108
|
+
{ key: "pass2", prop: "pass2", label: "通关2", width: 100, align: "center" },
|
|
109
|
+
{ key: "pass3", prop: "pass3", label: "通关3", width: 100, align: "center" },
|
|
110
|
+
{ key: "operation", prop: "__operation__", label: "操作", width: 180, align: "center", headerAlign: "center", isOperation: true },
|
|
111
|
+
],
|
|
112
|
+
// sortablejs 实例引用,用于在组件销毁或重建时手动销毁,避免内存泄露
|
|
113
|
+
headerSortable: null,
|
|
114
|
+
// 用于强制重建 el-table(修改 key),确保列顺序变更后 ElementUI 内部状态与 DOM 同步
|
|
115
|
+
tableKey: 0,
|
|
116
|
+
// 标识组件是否已经进入销毁流程,避免销毁后仍然去访问 DOM 或创建 sortable 实例
|
|
117
|
+
isDestroyed: false,
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
mounted() {
|
|
121
|
+
// 组件挂载后,在下一个渲染周期中初始化表头拖拽能力
|
|
122
|
+
this.$nextTick(() => {
|
|
123
|
+
this.initColumnDrag();
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
beforeDestroy() {
|
|
127
|
+
// 组件销毁前:设置销毁标记并清理 sortable 实例,避免内存泄露
|
|
128
|
+
this.isDestroyed = true;
|
|
129
|
+
if (this.headerSortable && this.headerSortable.destroy) {
|
|
130
|
+
this.headerSortable.destroy();
|
|
131
|
+
this.headerSortable = null;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
methods: {
|
|
135
|
+
// 初始化列拖拽:在 ElementUI 表格头部行(thead > tr)上绑定 sortable 实例
|
|
136
|
+
initColumnDrag() {
|
|
137
|
+
// 若组件已处于销毁阶段,直接返回,避免无意义的 DOM 访问
|
|
138
|
+
if (this.isDestroyed) return;
|
|
139
|
+
// 若已存在 sortable 实例,先销毁,避免重复绑定导致的事件堆积与内存泄露
|
|
140
|
+
if (this.headerSortable && this.headerSortable.destroy) {
|
|
141
|
+
this.headerSortable.destroy();
|
|
142
|
+
this.headerSortable = null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 通过 ref 获取 ElementUI 表格实例,再访问内部根元素
|
|
146
|
+
const table = this.$refs.draggableTable;
|
|
147
|
+
if (!table || !table.$el) return;
|
|
148
|
+
|
|
149
|
+
// ElementUI 表头 DOM:thead 里的第一行 tr,作为 sortable 容器
|
|
150
|
+
const headerRow = table.$el.querySelector(".el-table__header-wrapper thead tr");
|
|
151
|
+
if (!headerRow) return;
|
|
152
|
+
|
|
153
|
+
this.headerSortable = Sortable.create(headerRow, {
|
|
154
|
+
// 拖拽动画时长(毫秒)
|
|
155
|
+
animation: 150,
|
|
156
|
+
// 只允许拖拽 header-draggable 区域作为手柄,避免误拖整个表头
|
|
157
|
+
handle: ".header-draggable",
|
|
158
|
+
// 可被拖动的元素:表头单元格 th(索引列因没有 handle 实际不可拖拽)
|
|
159
|
+
draggable: "th",
|
|
160
|
+
// 拖拽结束时回调:根据新旧索引更新 columns 顺序
|
|
161
|
+
onEnd: (evt) => {
|
|
162
|
+
const { oldIndex, newIndex } = evt;
|
|
163
|
+
if (oldIndex == null || newIndex == null) return;
|
|
164
|
+
if (oldIndex === newIndex) return;
|
|
165
|
+
const from = oldIndex;
|
|
166
|
+
const to = newIndex;
|
|
167
|
+
if (from < 0 || to < 0 || from >= this.columns.length || to >= this.columns.length) return;
|
|
168
|
+
|
|
169
|
+
// 交换 columns 中两列的位置,实现“换列”
|
|
170
|
+
const list = this.columns.slice();
|
|
171
|
+
[list[from], list[to]] = [list[to], list[from]];
|
|
172
|
+
this.columns = list;
|
|
173
|
+
|
|
174
|
+
// 强制重建表格组件,避免 ElementUI 内部列状态与 DOM 拖拽产生偏差,
|
|
175
|
+
// 重建后在下一个 tick 重新绑定 sortable
|
|
176
|
+
this.tableKey += 1;
|
|
177
|
+
this.$nextTick(() => {
|
|
178
|
+
this.initColumnDrag();
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
handleSortChange({ prop, order }) {
|
|
184
|
+
if (!prop || !order) {
|
|
185
|
+
this.rows = this.rows.slice().sort((a, b) => a.id - b.id);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const list = this.rows.slice().sort((a, b) => {
|
|
189
|
+
const av = a[prop];
|
|
190
|
+
const bv = b[prop];
|
|
191
|
+
if (av === bv) return 0;
|
|
192
|
+
const result = av > bv ? 1 : -1;
|
|
193
|
+
return order === "ascending" ? result : -result;
|
|
194
|
+
});
|
|
195
|
+
this.rows = list;
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
</script>
|
package/view/index2.vue
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 人员信息表页面 -->
|
|
3
|
+
<section class="person-table-page">
|
|
4
|
+
<!-- 页面标题 -->
|
|
5
|
+
<h1>人员信息表</h1>
|
|
6
|
+
<!-- 工具栏:新增按钮 -->
|
|
7
|
+
<div class="toolbar">
|
|
8
|
+
<el-button type="primary" size="mini" @click="onOpenAdd">新增</el-button>
|
|
9
|
+
</div>
|
|
10
|
+
<!-- 人员信息表格 -->
|
|
11
|
+
<el-table
|
|
12
|
+
:data="rows"
|
|
13
|
+
border
|
|
14
|
+
stripe
|
|
15
|
+
size="small"
|
|
16
|
+
style="width: 100%"
|
|
17
|
+
>
|
|
18
|
+
<el-table-column
|
|
19
|
+
v-for="col in columns"
|
|
20
|
+
:key="col.key || col.prop || col.type || col.label"
|
|
21
|
+
:type="col.type"
|
|
22
|
+
:prop="col.prop"
|
|
23
|
+
:label="col.label"
|
|
24
|
+
:width="col.width"
|
|
25
|
+
:min-width="col.minWidth"
|
|
26
|
+
:align="col.align"
|
|
27
|
+
:header-align="col.headerAlign"
|
|
28
|
+
>
|
|
29
|
+
<template v-if="col.slot === 'sex'" slot-scope="scope">
|
|
30
|
+
{{ formatSex(scope.row.sex) }}
|
|
31
|
+
</template>
|
|
32
|
+
<template v-else-if="col.slot === 'operation'" slot-scope="scope">
|
|
33
|
+
<el-button type="text" size="mini" @click="onView(scope.row)">详情</el-button>
|
|
34
|
+
<el-button type="text" size="mini" @click="onEdit(scope.row)">编辑</el-button>
|
|
35
|
+
<el-button type="text" size="mini" @click="onRemove(scope.row)">删除</el-button>
|
|
36
|
+
</template>
|
|
37
|
+
</el-table-column>
|
|
38
|
+
</el-table>
|
|
39
|
+
|
|
40
|
+
<!-- 新增/编辑/查看 弹窗 -->
|
|
41
|
+
<el-dialog
|
|
42
|
+
:title="dialogTitle"
|
|
43
|
+
:visible.sync="dialogVisible"
|
|
44
|
+
width="720px"
|
|
45
|
+
>
|
|
46
|
+
<!-- 人员信息表单 -->
|
|
47
|
+
<el-form
|
|
48
|
+
ref="addForm"
|
|
49
|
+
:model="form"
|
|
50
|
+
:rules="rules"
|
|
51
|
+
label-width="90px"
|
|
52
|
+
size="small"
|
|
53
|
+
>
|
|
54
|
+
<!-- 第一行:姓名、岗位 -->
|
|
55
|
+
<el-row :gutter="16">
|
|
56
|
+
<el-col :span="12">
|
|
57
|
+
<el-form-item label="人员姓名" prop="name">
|
|
58
|
+
<el-input v-model="form.name" placeholder="请输入" :disabled="isView" />
|
|
59
|
+
</el-form-item>
|
|
60
|
+
</el-col>
|
|
61
|
+
<el-col :span="12">
|
|
62
|
+
<el-form-item label="岗位" prop="postName">
|
|
63
|
+
<el-select v-model="form.postName" placeholder="请选择" style="width: 100%" :disabled="isView">
|
|
64
|
+
<el-option
|
|
65
|
+
v-for="opt in postOptions"
|
|
66
|
+
:key="opt"
|
|
67
|
+
:label="opt"
|
|
68
|
+
:value="opt"
|
|
69
|
+
/>
|
|
70
|
+
</el-select>
|
|
71
|
+
</el-form-item>
|
|
72
|
+
</el-col>
|
|
73
|
+
</el-row>
|
|
74
|
+
<!-- 第二行:入行日期、性别 -->
|
|
75
|
+
<el-row :gutter="16">
|
|
76
|
+
<el-col :span="12">
|
|
77
|
+
<el-form-item label="入行日期" prop="happenPerio">
|
|
78
|
+
<el-date-picker
|
|
79
|
+
v-model="form.happenPerio"
|
|
80
|
+
type="date"
|
|
81
|
+
placeholder="请选择"
|
|
82
|
+
value-format="yyyy-MM-dd"
|
|
83
|
+
style="width: 100%"
|
|
84
|
+
:disabled="isView"
|
|
85
|
+
/>
|
|
86
|
+
</el-form-item>
|
|
87
|
+
</el-col>
|
|
88
|
+
<el-col :span="12">
|
|
89
|
+
<el-form-item label="性别" prop="sex">
|
|
90
|
+
<el-select v-model="form.sex" placeholder="请选择" style="width: 100%" :disabled="isView">
|
|
91
|
+
<el-option label="男" value="1" />
|
|
92
|
+
<el-option label="女" value="2" />
|
|
93
|
+
</el-select>
|
|
94
|
+
</el-form-item>
|
|
95
|
+
</el-col>
|
|
96
|
+
</el-row>
|
|
97
|
+
<!-- 第三行:联系方式、出生日期 -->
|
|
98
|
+
<el-row :gutter="16">
|
|
99
|
+
<el-col :span="12">
|
|
100
|
+
<el-form-item label="联系方式" prop="telNo">
|
|
101
|
+
<el-input v-model="form.telNo" placeholder="请输入" :disabled="isView" />
|
|
102
|
+
</el-form-item>
|
|
103
|
+
</el-col>
|
|
104
|
+
<el-col :span="12">
|
|
105
|
+
<el-form-item label="出生日期" prop="birthDt">
|
|
106
|
+
<el-date-picker
|
|
107
|
+
v-model="form.birthDt"
|
|
108
|
+
type="date"
|
|
109
|
+
placeholder="请选择"
|
|
110
|
+
value-format="yyyy-MM-dd"
|
|
111
|
+
style="width: 100%"
|
|
112
|
+
:disabled="isView"
|
|
113
|
+
/>
|
|
114
|
+
</el-form-item>
|
|
115
|
+
</el-col>
|
|
116
|
+
</el-row>
|
|
117
|
+
<!-- 第四行:家庭住址 -->
|
|
118
|
+
<el-row :gutter="16">
|
|
119
|
+
<el-col :span="24">
|
|
120
|
+
<el-form-item label="家庭住址" prop="dtlAddr">
|
|
121
|
+
<el-input v-model="form.dtlAddr" placeholder="请输入" :disabled="isView" />
|
|
122
|
+
</el-form-item>
|
|
123
|
+
</el-col>
|
|
124
|
+
</el-row>
|
|
125
|
+
<!-- 第五行:紧急联系人及联系方式 -->
|
|
126
|
+
<el-row :gutter="16">
|
|
127
|
+
<el-col :span="12">
|
|
128
|
+
<el-form-item label="紧急联系人" prop="emergContactPersonName">
|
|
129
|
+
<el-input v-model="form.emergContactPersonName" placeholder="请输入" :disabled="isView" />
|
|
130
|
+
</el-form-item>
|
|
131
|
+
</el-col>
|
|
132
|
+
<el-col :span="12">
|
|
133
|
+
<el-form-item label="紧急联系方式" prop="emergContactPhoneNo">
|
|
134
|
+
<el-input v-model="form.emergContactPhoneNo" placeholder="请输入" :disabled="isView" />
|
|
135
|
+
</el-form-item>
|
|
136
|
+
</el-col>
|
|
137
|
+
</el-row>
|
|
138
|
+
<!-- 第六行:最高学历、备注 -->
|
|
139
|
+
<el-row :gutter="16">
|
|
140
|
+
<el-col :span="12">
|
|
141
|
+
<el-form-item label="最高学历" prop="highestEduDegreeDesc">
|
|
142
|
+
<el-select v-model="form.highestEduDegreeDesc" placeholder="请选择" style="width: 100%" :disabled="isView">
|
|
143
|
+
<el-option
|
|
144
|
+
v-for="opt in eduOptions"
|
|
145
|
+
:key="opt"
|
|
146
|
+
:label="opt"
|
|
147
|
+
:value="opt"
|
|
148
|
+
/>
|
|
149
|
+
</el-select>
|
|
150
|
+
</el-form-item>
|
|
151
|
+
</el-col>
|
|
152
|
+
<el-col :span="12">
|
|
153
|
+
<el-form-item label="备注" prop="rmk">
|
|
154
|
+
<el-input
|
|
155
|
+
v-model="form.rmk"
|
|
156
|
+
type="textarea"
|
|
157
|
+
:rows="3"
|
|
158
|
+
maxlength="100"
|
|
159
|
+
show-word-limit
|
|
160
|
+
placeholder="请输入"
|
|
161
|
+
:disabled="isView"
|
|
162
|
+
/>
|
|
163
|
+
</el-form-item>
|
|
164
|
+
</el-col>
|
|
165
|
+
</el-row>
|
|
166
|
+
<!-- 第七行:附件上传 -->
|
|
167
|
+
<el-row :gutter="16">
|
|
168
|
+
<el-col :span="24">
|
|
169
|
+
<el-form-item label="选择文件">
|
|
170
|
+
<el-upload
|
|
171
|
+
class="upload-block"
|
|
172
|
+
drag
|
|
173
|
+
action="#"
|
|
174
|
+
:auto-upload="false"
|
|
175
|
+
:file-list="fileList"
|
|
176
|
+
:on-change="onFileChange"
|
|
177
|
+
:on-remove="onFileRemove"
|
|
178
|
+
:disabled="isView"
|
|
179
|
+
>
|
|
180
|
+
<el-button type="primary" plain>上传文件</el-button>
|
|
181
|
+
<div slot="tip" class="el-upload__tip">
|
|
182
|
+
支持格式:png/jpg/docx/pdf,单个文件不能超过10mb
|
|
183
|
+
</div>
|
|
184
|
+
</el-upload>
|
|
185
|
+
</el-form-item>
|
|
186
|
+
</el-col>
|
|
187
|
+
</el-row>
|
|
188
|
+
</el-form>
|
|
189
|
+
<!-- 弹窗底部按钮 -->
|
|
190
|
+
<span slot="footer" class="dialog-footer">
|
|
191
|
+
<el-button @click="dialogVisible = false">取消</el-button>
|
|
192
|
+
<el-button
|
|
193
|
+
v-if="dialogMode !== 'view'"
|
|
194
|
+
type="primary"
|
|
195
|
+
@click="onSave"
|
|
196
|
+
>
|
|
197
|
+
保存
|
|
198
|
+
</el-button>
|
|
199
|
+
</span>
|
|
200
|
+
</el-dialog>
|
|
201
|
+
</section>
|
|
202
|
+
</template>
|
|
203
|
+
|
|
204
|
+
<script>
|
|
205
|
+
export default {
|
|
206
|
+
name: "PersonTableView",
|
|
207
|
+
data() {
|
|
208
|
+
return {
|
|
209
|
+
// 表格数据源:人员列表
|
|
210
|
+
rows: [
|
|
211
|
+
{
|
|
212
|
+
// 唯一标识
|
|
213
|
+
id: 3286648151643648,
|
|
214
|
+
// 人员姓名
|
|
215
|
+
name: "李白",
|
|
216
|
+
// 性别:1-男,2-女
|
|
217
|
+
sex: "1",
|
|
218
|
+
// 岗位名称
|
|
219
|
+
postName: "保洁",
|
|
220
|
+
// 入行日期(yyyy-MM-dd)
|
|
221
|
+
happenPerio: "2002-02-02",
|
|
222
|
+
// 联系电话
|
|
223
|
+
telNo: "18966541247",
|
|
224
|
+
// 现居住地
|
|
225
|
+
dtlAddr: "北京",
|
|
226
|
+
// 紧急联系人姓名
|
|
227
|
+
emergContactPersonName: "王安石",
|
|
228
|
+
// 紧急联系人电话
|
|
229
|
+
emergContactPhoneNo: "15466257489",
|
|
230
|
+
// 出生日期(yyyy-MM-dd)
|
|
231
|
+
birthDt: "2000-02-02",
|
|
232
|
+
// 最高学历说明
|
|
233
|
+
highestEduDegreeDesc: "硕士",
|
|
234
|
+
// 创建日期(yyyy-MM-dd)
|
|
235
|
+
createTm: "2025-12-25",
|
|
236
|
+
// 备注信息
|
|
237
|
+
rmk: "好人",
|
|
238
|
+
// 所属机构号
|
|
239
|
+
beloOrgNO: "000291",
|
|
240
|
+
// 创建人工号
|
|
241
|
+
creatorNo: "022171",
|
|
242
|
+
// 删除标识:0-正常 1-删除
|
|
243
|
+
delFlag: "0",
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
columns: [
|
|
247
|
+
{ key: "index", type: "index", label: "序号", width: 60, align: "center", headerAlign: "center" },
|
|
248
|
+
{ key: "name", prop: "name", label: "人员姓名", minWidth: 100, align: "center", headerAlign: "center" },
|
|
249
|
+
{ key: "sex", label: "性别", width: 80, align: "center", headerAlign: "center", slot: "sex" },
|
|
250
|
+
{ key: "postName", prop: "postName", label: "岗位", minWidth: 80, align: "center", headerAlign: "center" },
|
|
251
|
+
{ key: "happenPerio", prop: "happenPerio", label: "入行日期", minWidth: 110, align: "center", headerAlign: "center" },
|
|
252
|
+
{ key: "telNo", prop: "telNo", label: "联系方式", minWidth: 130, align: "center", headerAlign: "center" },
|
|
253
|
+
{ key: "dtlAddr", prop: "dtlAddr", label: "现居住地", minWidth: 120, align: "center", headerAlign: "center" },
|
|
254
|
+
{ key: "emergContactPersonName", prop: "emergContactPersonName", label: "紧急联系人", minWidth: 100, align: "center", headerAlign: "center" },
|
|
255
|
+
{ key: "emergContactPhoneNo", prop: "emergContactPhoneNo", label: "紧急联系方式", minWidth: 130, align: "center", headerAlign: "center" },
|
|
256
|
+
{ key: "birthDt", prop: "birthDt", label: "出生日期", minWidth: 110, align: "center", headerAlign: "center" },
|
|
257
|
+
{ key: "highestEduDegreeDesc", prop: "highestEduDegreeDesc", label: "最高学历", minWidth: 90, align: "center", headerAlign: "center" },
|
|
258
|
+
{ key: "createTm", prop: "createTm", label: "创建日期", minWidth: 110, align: "center", headerAlign: "center" },
|
|
259
|
+
{ key: "rmk", prop: "rmk", label: "备注", minWidth: 120, align: "center", headerAlign: "center" },
|
|
260
|
+
{ key: "operation", label: "操作", width: 200, align: "center", headerAlign: "center", slot: "operation" },
|
|
261
|
+
],
|
|
262
|
+
// 弹窗显隐状态
|
|
263
|
+
dialogVisible: false,
|
|
264
|
+
// 弹窗模式:add 新增 / edit 编辑 / view 查看
|
|
265
|
+
dialogMode: "add",
|
|
266
|
+
// 当前编辑或查看的人员ID
|
|
267
|
+
editingId: null,
|
|
268
|
+
// 表单数据模型
|
|
269
|
+
form: {
|
|
270
|
+
// 人员姓名
|
|
271
|
+
name: "",
|
|
272
|
+
// 性别:1-男,2-女
|
|
273
|
+
sex: "",
|
|
274
|
+
// 岗位名称
|
|
275
|
+
postName: "",
|
|
276
|
+
// 入行日期
|
|
277
|
+
happenPerio: "",
|
|
278
|
+
// 联系电话
|
|
279
|
+
telNo: "",
|
|
280
|
+
// 家庭住址
|
|
281
|
+
dtlAddr: "",
|
|
282
|
+
// 紧急联系人姓名
|
|
283
|
+
emergContactPersonName: "",
|
|
284
|
+
// 紧急联系人电话
|
|
285
|
+
emergContactPhoneNo: "",
|
|
286
|
+
// 出生日期
|
|
287
|
+
birthDt: "",
|
|
288
|
+
// 最高学历说明
|
|
289
|
+
highestEduDegreeDesc: "",
|
|
290
|
+
// 备注信息
|
|
291
|
+
rmk: "",
|
|
292
|
+
},
|
|
293
|
+
// 表单校验规则
|
|
294
|
+
rules: {
|
|
295
|
+
name: [{ required: true, message: "请输入人员姓名", trigger: "blur" }],
|
|
296
|
+
postName: [{ required: true, message: "请选择岗位", trigger: "change" }],
|
|
297
|
+
sex: [{ required: true, message: "请选择性别", trigger: "change" }],
|
|
298
|
+
happenPerio: [{ required: true, message: "请选择入行日期", trigger: "change" }],
|
|
299
|
+
telNo: [{ required: true, message: "请输入联系方式", trigger: "blur" }],
|
|
300
|
+
emergContactPersonName: [{ required: true, message: "请输入紧急联系人", trigger: "blur" }],
|
|
301
|
+
emergContactPhoneNo: [{ required: true, message: "请输入紧急联系方式", trigger: "blur" }],
|
|
302
|
+
},
|
|
303
|
+
// 岗位下拉选项
|
|
304
|
+
postOptions: ["保洁", "柜员", "客户经理", "运营专员"],
|
|
305
|
+
// 学历下拉选项
|
|
306
|
+
eduOptions: ["大专", "本科", "硕士", "博士"],
|
|
307
|
+
// 上传的附件列表
|
|
308
|
+
fileList: [],
|
|
309
|
+
};
|
|
310
|
+
},
|
|
311
|
+
computed: {
|
|
312
|
+
// 弹窗标题文案
|
|
313
|
+
dialogTitle() {
|
|
314
|
+
if (this.dialogMode === "edit") return "编辑";
|
|
315
|
+
if (this.dialogMode === "view") return "详情";
|
|
316
|
+
return "新增";
|
|
317
|
+
},
|
|
318
|
+
// 是否为只读查看模式
|
|
319
|
+
isView() {
|
|
320
|
+
return this.dialogMode === "view";
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
methods: {
|
|
324
|
+
// 性别字段格式化显示
|
|
325
|
+
formatSex(v) {
|
|
326
|
+
if (v === "1" || v === 1) return "男";
|
|
327
|
+
if (v === "2" || v === 2) return "女";
|
|
328
|
+
return "";
|
|
329
|
+
},
|
|
330
|
+
// 打开新增弹窗
|
|
331
|
+
onOpenAdd() {
|
|
332
|
+
this.dialogVisible = true;
|
|
333
|
+
this.dialogMode = "add";
|
|
334
|
+
this.editingId = null;
|
|
335
|
+
this.resetForm();
|
|
336
|
+
},
|
|
337
|
+
// 打开编辑弹窗并回显数据
|
|
338
|
+
onEdit(row) {
|
|
339
|
+
this.dialogMode = "edit";
|
|
340
|
+
this.editingId = row.id;
|
|
341
|
+
this.dialogVisible = true;
|
|
342
|
+
this.form = {
|
|
343
|
+
name: row.name || "",
|
|
344
|
+
sex: row.sex || "",
|
|
345
|
+
postName: row.postName || "",
|
|
346
|
+
happenPerio: row.happenPerio || "",
|
|
347
|
+
telNo: row.telNo || "",
|
|
348
|
+
dtlAddr: row.dtlAddr || "",
|
|
349
|
+
emergContactPersonName: row.emergContactPersonName || "",
|
|
350
|
+
emergContactPhoneNo: row.emergContactPhoneNo || "",
|
|
351
|
+
birthDt: row.birthDt || "",
|
|
352
|
+
highestEduDegreeDesc: row.highestEduDegreeDesc || "",
|
|
353
|
+
rmk: row.rmk || "",
|
|
354
|
+
createTm: row.createTm || "",
|
|
355
|
+
};
|
|
356
|
+
this.fileList = [];
|
|
357
|
+
if (this.$refs.addForm) {
|
|
358
|
+
this.$refs.addForm.clearValidate();
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
// 打开详情弹窗(只读)
|
|
362
|
+
onView(row) {
|
|
363
|
+
this.dialogMode = "view";
|
|
364
|
+
this.editingId = row.id;
|
|
365
|
+
this.dialogVisible = true;
|
|
366
|
+
this.form = {
|
|
367
|
+
name: row.name || "",
|
|
368
|
+
sex: row.sex || "",
|
|
369
|
+
postName: row.postName || "",
|
|
370
|
+
happenPerio: row.happenPerio || "",
|
|
371
|
+
telNo: row.telNo || "",
|
|
372
|
+
dtlAddr: row.dtlAddr || "",
|
|
373
|
+
emergContactPersonName: row.emergContactPersonName || "",
|
|
374
|
+
emergContactPhoneNo: row.emergContactPhoneNo || "",
|
|
375
|
+
birthDt: row.birthDt || "",
|
|
376
|
+
highestEduDegreeDesc: row.highestEduDegreeDesc || "",
|
|
377
|
+
rmk: row.rmk || "",
|
|
378
|
+
createTm: row.createTm || "",
|
|
379
|
+
};
|
|
380
|
+
this.fileList = [];
|
|
381
|
+
if (this.$refs.addForm) {
|
|
382
|
+
this.$refs.addForm.clearValidate();
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
// 重置表单数据及校验
|
|
386
|
+
resetForm() {
|
|
387
|
+
this.form = {
|
|
388
|
+
name: "",
|
|
389
|
+
sex: "",
|
|
390
|
+
postName: "",
|
|
391
|
+
happenPerio: "",
|
|
392
|
+
telNo: "",
|
|
393
|
+
dtlAddr: "",
|
|
394
|
+
emergContactPersonName: "",
|
|
395
|
+
emergContactPhoneNo: "",
|
|
396
|
+
birthDt: "",
|
|
397
|
+
highestEduDegreeDesc: "",
|
|
398
|
+
rmk: "",
|
|
399
|
+
};
|
|
400
|
+
this.fileList = [];
|
|
401
|
+
if (this.$refs.addForm) {
|
|
402
|
+
this.$refs.addForm.clearValidate();
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
// 文件选择变更回调
|
|
406
|
+
onFileChange(file, fileList) {
|
|
407
|
+
this.fileList = fileList.slice();
|
|
408
|
+
},
|
|
409
|
+
// 文件移除回调
|
|
410
|
+
onFileRemove(file, fileList) {
|
|
411
|
+
this.fileList = fileList.slice();
|
|
412
|
+
},
|
|
413
|
+
// 保存(新增或编辑)人员信息
|
|
414
|
+
onSave() {
|
|
415
|
+
if (!this.$refs.addForm) return;
|
|
416
|
+
this.$refs.addForm.validate((valid) => {
|
|
417
|
+
if (!valid) return;
|
|
418
|
+
const now = new Date();
|
|
419
|
+
const createTm =
|
|
420
|
+
this.form.createTm ||
|
|
421
|
+
`${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(
|
|
422
|
+
now.getDate()
|
|
423
|
+
).padStart(2, "0")}`;
|
|
424
|
+
const base = {
|
|
425
|
+
name: this.form.name,
|
|
426
|
+
sex: this.form.sex,
|
|
427
|
+
postName: this.form.postName,
|
|
428
|
+
happenPerio: this.form.happenPerio,
|
|
429
|
+
telNo: this.form.telNo,
|
|
430
|
+
dtlAddr: this.form.dtlAddr,
|
|
431
|
+
emergContactPersonName: this.form.emergContactPersonName,
|
|
432
|
+
emergContactPhoneNo: this.form.emergContactPhoneNo,
|
|
433
|
+
birthDt: this.form.birthDt,
|
|
434
|
+
highestEduDegreeDesc: this.form.highestEduDegreeDesc,
|
|
435
|
+
createTm,
|
|
436
|
+
rmk: this.form.rmk,
|
|
437
|
+
beloOrgNO: "",
|
|
438
|
+
creatorNo: "",
|
|
439
|
+
delFlag: "0",
|
|
440
|
+
};
|
|
441
|
+
if (this.dialogMode === "edit" && this.editingId) {
|
|
442
|
+
// 编辑模式:更新原有记录
|
|
443
|
+
this.rows = this.rows.map((r) =>
|
|
444
|
+
r.id === this.editingId
|
|
445
|
+
? Object.assign({}, r, base, { id: r.id })
|
|
446
|
+
: r
|
|
447
|
+
);
|
|
448
|
+
} else {
|
|
449
|
+
// 新增模式:追加新记录
|
|
450
|
+
const row = Object.assign({}, base, { id: Date.now() });
|
|
451
|
+
this.rows = this.rows.concat(row);
|
|
452
|
+
}
|
|
453
|
+
this.dialogVisible = false;
|
|
454
|
+
});
|
|
455
|
+
},
|
|
456
|
+
// 删除人员信息
|
|
457
|
+
onRemove(row) {
|
|
458
|
+
if (!row || !row.id) return;
|
|
459
|
+
this.$confirm("确认删除该人员吗?", "提示", { type: "warning" })
|
|
460
|
+
.then(() => {
|
|
461
|
+
this.rows = this.rows.filter((r) => r.id !== row.id);
|
|
462
|
+
})
|
|
463
|
+
.catch(() => {});
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
</script>
|
|
468
|
+
|
|
469
|
+
<style scoped>
|
|
470
|
+
.person-table-page {
|
|
471
|
+
padding: 24px;
|
|
472
|
+
}
|
|
473
|
+
.toolbar {
|
|
474
|
+
margin-bottom: 12px;
|
|
475
|
+
}
|
|
476
|
+
.upload-block {
|
|
477
|
+
width: 100%;
|
|
478
|
+
}
|
|
479
|
+
.dialog-footer {
|
|
480
|
+
text-align: center;
|
|
481
|
+
}
|
|
482
|
+
</style>
|