vercerl-express-test 1.0.2 → 1.0.4
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.
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!--
|
|
3
|
+
会议列表页面
|
|
4
|
+
功能:
|
|
5
|
+
1. 顶部查询条件:所属机构、会议主题、会议类型、创建日期范围
|
|
6
|
+
2. 工具栏:新建按钮(预留后续接入创建弹窗)
|
|
7
|
+
3. 中间表格:
|
|
8
|
+
- 支持列拖拽(除操作列外)
|
|
9
|
+
- 展示会议基本信息
|
|
10
|
+
4. 底部分页:基于筛选结果做前端分页
|
|
11
|
+
-->
|
|
12
|
+
<section class="page meeting-page">
|
|
13
|
+
<h1 class="meeting-title">会议列表</h1>
|
|
14
|
+
|
|
15
|
+
<!-- 查询条件区域:用于筛选会议列表 -->
|
|
16
|
+
<div class="meeting-search-card">
|
|
17
|
+
<el-form :inline="true" :model="filters" size="small" class="meeting-search-form">
|
|
18
|
+
<!-- 所属机构下拉框 -->
|
|
19
|
+
<el-form-item label="所属机构">
|
|
20
|
+
<el-select
|
|
21
|
+
v-model="filters.belOrgNo"
|
|
22
|
+
placeholder="请选择"
|
|
23
|
+
clearable
|
|
24
|
+
style="width: 200px"
|
|
25
|
+
>
|
|
26
|
+
<el-option
|
|
27
|
+
v-for="opt in orgOptions"
|
|
28
|
+
:key="opt.value"
|
|
29
|
+
:label="opt.label"
|
|
30
|
+
:value="opt.value"
|
|
31
|
+
/>
|
|
32
|
+
</el-select>
|
|
33
|
+
</el-form-item>
|
|
34
|
+
<!-- 会议主题输入框(模糊匹配) -->
|
|
35
|
+
<el-form-item label="会议主题">
|
|
36
|
+
<el-input
|
|
37
|
+
v-model="filters.meetSubj"
|
|
38
|
+
placeholder="请输入"
|
|
39
|
+
clearable
|
|
40
|
+
style="width: 220px"
|
|
41
|
+
/>
|
|
42
|
+
</el-form-item>
|
|
43
|
+
<!-- 会议类型下拉框 -->
|
|
44
|
+
<el-form-item label="会议类型">
|
|
45
|
+
<el-select
|
|
46
|
+
v-model="filters.meetTypeCd"
|
|
47
|
+
placeholder="全部"
|
|
48
|
+
clearable
|
|
49
|
+
style="width: 160px"
|
|
50
|
+
>
|
|
51
|
+
<el-option
|
|
52
|
+
v-for="opt in typeOptions"
|
|
53
|
+
:key="opt.value"
|
|
54
|
+
:label="opt.label"
|
|
55
|
+
:value="opt.value"
|
|
56
|
+
/>
|
|
57
|
+
</el-select>
|
|
58
|
+
</el-form-item>
|
|
59
|
+
<!-- 创建日期范围选择 -->
|
|
60
|
+
<el-form-item label="创建日期">
|
|
61
|
+
<el-date-picker
|
|
62
|
+
v-model="filters.createDateRange"
|
|
63
|
+
type="daterange"
|
|
64
|
+
range-separator="至"
|
|
65
|
+
start-placeholder="开始日期"
|
|
66
|
+
end-placeholder="结束日期"
|
|
67
|
+
format="yyyy-MM-dd"
|
|
68
|
+
value-format="yyyy-MM-dd"
|
|
69
|
+
unlink-panels
|
|
70
|
+
/>
|
|
71
|
+
</el-form-item>
|
|
72
|
+
<!-- 查询 / 重置按钮 -->
|
|
73
|
+
<el-form-item>
|
|
74
|
+
<el-button type="primary" size="small" @click="onSearch">
|
|
75
|
+
查询
|
|
76
|
+
</el-button>
|
|
77
|
+
<el-button size="small" @click="onReset">
|
|
78
|
+
重置
|
|
79
|
+
</el-button>
|
|
80
|
+
</el-form-item>
|
|
81
|
+
</el-form>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- 工具栏:后续可扩展更多操作按钮 -->
|
|
85
|
+
<div class="meeting-toolbar">
|
|
86
|
+
<el-button type="primary" size="small" icon="el-icon-plus">
|
|
87
|
+
新建
|
|
88
|
+
</el-button>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<!--
|
|
92
|
+
主表格:
|
|
93
|
+
- ref/:key:配合拖拽重建表头
|
|
94
|
+
- index 列固定在最左侧
|
|
95
|
+
- 中间列通过 columns 配置,支持拖拽调整顺序
|
|
96
|
+
- 操作列固定在最右侧且不可拖拽
|
|
97
|
+
-->
|
|
98
|
+
<el-table
|
|
99
|
+
ref="meetingTable"
|
|
100
|
+
:key="tableKey"
|
|
101
|
+
:data="pagedRows"
|
|
102
|
+
border
|
|
103
|
+
stripe
|
|
104
|
+
size="small"
|
|
105
|
+
style="width: 100%"
|
|
106
|
+
:default-sort="{ prop: 'createTm', order: 'descending' }"
|
|
107
|
+
@sort-change="onSortChange"
|
|
108
|
+
>
|
|
109
|
+
<!-- 序号列:仅显示索引,不参与拖拽 -->
|
|
110
|
+
<el-table-column
|
|
111
|
+
type="index"
|
|
112
|
+
label="序号"
|
|
113
|
+
width="60"
|
|
114
|
+
align="center"
|
|
115
|
+
/>
|
|
116
|
+
<!--
|
|
117
|
+
中间业务列:
|
|
118
|
+
由 columns 数组驱动,通过 header 上的 header-draggable 类来实现拖拽
|
|
119
|
+
-->
|
|
120
|
+
<el-table-column
|
|
121
|
+
v-for="col in columns"
|
|
122
|
+
:key="col.key"
|
|
123
|
+
:prop="col.prop"
|
|
124
|
+
:label="col.label"
|
|
125
|
+
:width="col.width"
|
|
126
|
+
:min-width="col.minWidth"
|
|
127
|
+
:align="col.align || 'left'"
|
|
128
|
+
:header-align="col.headerAlign || col.align || 'left'"
|
|
129
|
+
:sortable="col.sortable"
|
|
130
|
+
:label-class-name="'meeting-header-' + col.key"
|
|
131
|
+
>
|
|
132
|
+
<!-- 表头内容:包一层 div 以作为拖拽的 handle -->
|
|
133
|
+
<template slot="header">
|
|
134
|
+
<div class="header-wrapper header-draggable">
|
|
135
|
+
<span class="header-label">{{ col.label }}</span>
|
|
136
|
+
</div>
|
|
137
|
+
</template>
|
|
138
|
+
<!-- 根据列类型渲染不同的单元格内容 -->
|
|
139
|
+
<template slot-scope="scope">
|
|
140
|
+
<span v-if="col.type === 'type'">
|
|
141
|
+
<el-tag
|
|
142
|
+
:type="getTypeTagType(scope.row.meetTypeCd)"
|
|
143
|
+
size="mini"
|
|
144
|
+
>
|
|
145
|
+
{{ formatMeetType(scope.row.meetTypeCd) }}
|
|
146
|
+
</el-tag>
|
|
147
|
+
</span>
|
|
148
|
+
<div v-else-if="col.type === 'content'">
|
|
149
|
+
<div class="meeting-subject">
|
|
150
|
+
{{ scope.row.meetSubj }}
|
|
151
|
+
</div>
|
|
152
|
+
<div
|
|
153
|
+
v-if="scope.row.plainContent"
|
|
154
|
+
class="meeting-content"
|
|
155
|
+
>
|
|
156
|
+
{{ scope.row.plainContent }}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<span v-else-if="col.type === 'createDate'">
|
|
160
|
+
{{ formatDate(scope.row.createTm) }}
|
|
161
|
+
</span>
|
|
162
|
+
<span v-else-if="col.type === 'updateDate'">
|
|
163
|
+
{{ formatDateTime(scope.row.updateTm) }}
|
|
164
|
+
</span>
|
|
165
|
+
<span v-else>
|
|
166
|
+
{{ scope.row[col.prop] }}
|
|
167
|
+
</span>
|
|
168
|
+
</template>
|
|
169
|
+
</el-table-column>
|
|
170
|
+
<!-- 操作列:固定在右侧,不参与拖拽(通过 label-class-name 区分) -->
|
|
171
|
+
<el-table-column
|
|
172
|
+
label="操作"
|
|
173
|
+
width="140"
|
|
174
|
+
align="center"
|
|
175
|
+
fixed="right"
|
|
176
|
+
label-class-name="meeting-header-action"
|
|
177
|
+
>
|
|
178
|
+
<template slot-scope="scope">
|
|
179
|
+
<el-button
|
|
180
|
+
type="text"
|
|
181
|
+
size="mini"
|
|
182
|
+
@click="onView(scope.row)"
|
|
183
|
+
>
|
|
184
|
+
详情
|
|
185
|
+
</el-button>
|
|
186
|
+
<el-button
|
|
187
|
+
type="text"
|
|
188
|
+
size="mini"
|
|
189
|
+
@click="onDelete(scope.row)"
|
|
190
|
+
>
|
|
191
|
+
删除
|
|
192
|
+
</el-button>
|
|
193
|
+
</template>
|
|
194
|
+
</el-table-column>
|
|
195
|
+
</el-table>
|
|
196
|
+
|
|
197
|
+
<div class="meeting-pagination">
|
|
198
|
+
<el-pagination
|
|
199
|
+
layout="total, prev, pager, next"
|
|
200
|
+
:current-page.sync="page"
|
|
201
|
+
:page-size="pageSize"
|
|
202
|
+
:total="filteredRows.length"
|
|
203
|
+
@current-change="onPageChange"
|
|
204
|
+
/>
|
|
205
|
+
</div>
|
|
206
|
+
</section>
|
|
207
|
+
</template>
|
|
208
|
+
|
|
209
|
+
<script>
|
|
210
|
+
import Sortable from "sortablejs";
|
|
211
|
+
|
|
212
|
+
export default {
|
|
213
|
+
name: "MeetingListPage",
|
|
214
|
+
data() {
|
|
215
|
+
return {
|
|
216
|
+
// 可拖拽的业务列配置(不包含序号列与操作列)
|
|
217
|
+
columns: [
|
|
218
|
+
{ key: "type", prop: "meetTypeCd", label: "类型", width: 120, align: "center", type: "type" },
|
|
219
|
+
{ key: "content", prop: "meetSubj", label: "内容", minWidth: 260, type: "content" },
|
|
220
|
+
{ key: "organizationName", prop: "organizationName", label: "所属机构", minWidth: 160 },
|
|
221
|
+
{ key: "displayName", prop: "displayName", label: "创建人", width: 120 },
|
|
222
|
+
{ key: "createDate", prop: "createTm", label: "创建日期", width: 160, align: "center", type: "createDate", sortable: "custom" },
|
|
223
|
+
{ key: "updateDate", prop: "updateTm", label: "最近编辑时间", width: 190, align: "center", type: "updateDate", sortable: "custom" }
|
|
224
|
+
],
|
|
225
|
+
// 示例数据:模拟接口返回的会议列表,用于本地展示
|
|
226
|
+
rows: [
|
|
227
|
+
{
|
|
228
|
+
id: 33029032315325800,
|
|
229
|
+
belOrgNo: "31021",
|
|
230
|
+
organizationName: "上海浦东支行",
|
|
231
|
+
meetSubj: "安全测试",
|
|
232
|
+
meetConte: "<p>1231</p>",
|
|
233
|
+
plainContent: "1231",
|
|
234
|
+
meetDt: "2026-01-07",
|
|
235
|
+
meetNo: "ORTHER2026-01-16 17:02:05",
|
|
236
|
+
meetTypeCd: "TRAINING",
|
|
237
|
+
displayName: "刘晓鸣",
|
|
238
|
+
createTm: "2026-01-16",
|
|
239
|
+
updateTm: "2026-01-16 17:02:05"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 33029032315325801,
|
|
243
|
+
belOrgNo: "11001",
|
|
244
|
+
organizationName: "北京西城支行",
|
|
245
|
+
meetSubj: "二化管理体系例会",
|
|
246
|
+
meetConte: "<p>1.各部门汇报日常工作以及问题</p><p>2.当前阶段化重点说明</p>",
|
|
247
|
+
plainContent: "各部门汇报日常工作以及问题;当前阶段化重点说明",
|
|
248
|
+
meetDt: "2026-01-15",
|
|
249
|
+
meetNo: "MORNING2026-01-15 19:56:24",
|
|
250
|
+
meetTypeCd: "MORNING",
|
|
251
|
+
displayName: "黄丽丽",
|
|
252
|
+
createTm: "2026-01-15",
|
|
253
|
+
updateTm: "2026-01-15 19:56:24"
|
|
254
|
+
}
|
|
255
|
+
],
|
|
256
|
+
// 查询条件
|
|
257
|
+
filters: {
|
|
258
|
+
belOrgNo: "",
|
|
259
|
+
meetSubj: "",
|
|
260
|
+
meetTypeCd: "",
|
|
261
|
+
createDateRange: []
|
|
262
|
+
},
|
|
263
|
+
// 所属机构下拉选项
|
|
264
|
+
orgOptions: [
|
|
265
|
+
{ label: "全部", value: "" },
|
|
266
|
+
{ label: "上海浦东支行", value: "31021" },
|
|
267
|
+
{ label: "北京西城支行", value: "11001" }
|
|
268
|
+
],
|
|
269
|
+
// 会议类型下拉选项
|
|
270
|
+
typeOptions: [
|
|
271
|
+
{ label: "培训", value: "TRAINING" },
|
|
272
|
+
{ label: "晨夕会", value: "MORNING" }
|
|
273
|
+
],
|
|
274
|
+
// 当前页码
|
|
275
|
+
page: 1,
|
|
276
|
+
// 每页条数
|
|
277
|
+
pageSize: 10,
|
|
278
|
+
// 预留:如果后续接接口,可以用来缓存上次查询 key
|
|
279
|
+
lastSearchKey: "",
|
|
280
|
+
// 当前远程排序字段(与 el-table-column 的 prop 对应)
|
|
281
|
+
sortField: "createTm",
|
|
282
|
+
// 当前远程排序方向:ascending / descending
|
|
283
|
+
sortOrder: "descending",
|
|
284
|
+
// 表头拖拽实例
|
|
285
|
+
headerSortable: null,
|
|
286
|
+
// 强制刷新表头用的 key(列顺序改变后重建表格)
|
|
287
|
+
tableKey: 0,
|
|
288
|
+
// 标记组件是否已销毁,避免销毁后仍操作 DOM
|
|
289
|
+
isDestroyed: false
|
|
290
|
+
};
|
|
291
|
+
},
|
|
292
|
+
mounted() {
|
|
293
|
+
// 等 DOM 渲染完成后初始化列拖拽
|
|
294
|
+
this.$nextTick(() => {
|
|
295
|
+
this.initColumnDrag();
|
|
296
|
+
});
|
|
297
|
+
},
|
|
298
|
+
beforeDestroy() {
|
|
299
|
+
this.isDestroyed = true;
|
|
300
|
+
if (this.headerSortable && this.headerSortable.destroy) {
|
|
301
|
+
this.headerSortable.destroy();
|
|
302
|
+
this.headerSortable = null;
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
computed: {
|
|
306
|
+
// 根据查询条件得到过滤后的数据列表
|
|
307
|
+
filteredRows() {
|
|
308
|
+
const subj = (this.filters.meetSubj || "").trim();
|
|
309
|
+
const belOrgNo = this.filters.belOrgNo || "";
|
|
310
|
+
const meetTypeCd = this.filters.meetTypeCd || "";
|
|
311
|
+
const [start, end] = Array.isArray(this.filters.createDateRange) ? this.filters.createDateRange : [];
|
|
312
|
+
|
|
313
|
+
const list = this.rows.filter(row => {
|
|
314
|
+
if (belOrgNo && row.belOrgNo !== belOrgNo) return false;
|
|
315
|
+
if (meetTypeCd && row.meetTypeCd !== meetTypeCd) return false;
|
|
316
|
+
if (subj && !row.meetSubj.includes(subj)) return false;
|
|
317
|
+
if (start && end) {
|
|
318
|
+
const d = row.createTm;
|
|
319
|
+
if (!d || d < start || d > end) return false;
|
|
320
|
+
}
|
|
321
|
+
return true;
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
if (this.sortField && this.sortOrder) {
|
|
325
|
+
const field = this.sortField;
|
|
326
|
+
const order = this.sortOrder === "ascending" ? 1 : -1;
|
|
327
|
+
list.sort((a, b) => {
|
|
328
|
+
const av = this.getTimeValue(a[field]);
|
|
329
|
+
const bv = this.getTimeValue(b[field]);
|
|
330
|
+
if (av === bv) return 0;
|
|
331
|
+
return av > bv ? order : -order;
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return list;
|
|
336
|
+
},
|
|
337
|
+
// 当前页应显示的数据(在 filteredRows 基础上做前端分页)
|
|
338
|
+
pagedRows() {
|
|
339
|
+
const start = (this.page - 1) * this.pageSize;
|
|
340
|
+
return this.filteredRows.slice(start, start + this.pageSize);
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
watch: {
|
|
344
|
+
// 当过滤后的数据量变化时,自动纠正当前页,避免超出最大页码
|
|
345
|
+
filteredRows() {
|
|
346
|
+
const maxPage = Math.max(1, Math.ceil(this.filteredRows.length / this.pageSize) || 1);
|
|
347
|
+
if (this.page > maxPage) this.page = maxPage;
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
methods: {
|
|
351
|
+
/**
|
|
352
|
+
* 初始化表头拖拽
|
|
353
|
+
* 说明:
|
|
354
|
+
* - 使用 SortableJS 绑定在 thead 的 tr 元素上
|
|
355
|
+
* - handle: 仅允许拖拽 header-draggable 区域
|
|
356
|
+
* - draggable: 排除操作列表头(.meeting-header-action)
|
|
357
|
+
* - 序号列位于最左,其 th 索引为 0,不在 columns 数组中,因此需要 -1 做映射
|
|
358
|
+
*/
|
|
359
|
+
initColumnDrag() {
|
|
360
|
+
if (this.isDestroyed) return;
|
|
361
|
+
if (this.headerSortable && this.headerSortable.destroy) {
|
|
362
|
+
this.headerSortable.destroy();
|
|
363
|
+
this.headerSortable = null;
|
|
364
|
+
}
|
|
365
|
+
const table = this.$refs.meetingTable;
|
|
366
|
+
if (!table || !table.$el) return;
|
|
367
|
+
const headerRow = table.$el.querySelector(".el-table__header-wrapper thead tr");
|
|
368
|
+
if (!headerRow) return;
|
|
369
|
+
this.headerSortable = Sortable.create(headerRow, {
|
|
370
|
+
animation: 150,
|
|
371
|
+
handle: ".header-draggable",
|
|
372
|
+
draggable: "th:not(.meeting-header-action)",
|
|
373
|
+
onEnd: evt => {
|
|
374
|
+
const { oldIndex, newIndex } = evt;
|
|
375
|
+
if (oldIndex == null || newIndex == null) return;
|
|
376
|
+
// 索引 0 对应序号列,从 1 开始才对应 columns 数组
|
|
377
|
+
const from = oldIndex - 1;
|
|
378
|
+
const to = newIndex - 1;
|
|
379
|
+
if (from < 0 || to < 0 || from >= this.columns.length || to >= this.columns.length) return;
|
|
380
|
+
const list = this.columns.slice();
|
|
381
|
+
const moved = list.splice(from, 1)[0];
|
|
382
|
+
list.splice(to, 0, moved);
|
|
383
|
+
this.columns = list;
|
|
384
|
+
this.tableKey += 1;
|
|
385
|
+
this.$nextTick(() => {
|
|
386
|
+
this.initColumnDrag();
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
},
|
|
391
|
+
/**
|
|
392
|
+
* 处理表格远程排序事件
|
|
393
|
+
* Element UI 会传入:{ column, prop, order }
|
|
394
|
+
* - prop:对应列的 prop,如 createTm / updateTm
|
|
395
|
+
* - order:ascending / descending / null
|
|
396
|
+
*/
|
|
397
|
+
onSortChange({ prop, order }) {
|
|
398
|
+
this.sortField = prop || "";
|
|
399
|
+
this.sortOrder = order || "";
|
|
400
|
+
this.page = 1;
|
|
401
|
+
},
|
|
402
|
+
// 点击“查询”:仅重置到第一页,筛选逻辑在 computed 中统一处理
|
|
403
|
+
onSearch() {
|
|
404
|
+
this.page = 1;
|
|
405
|
+
},
|
|
406
|
+
// 点击“重置”:清空所有查询条件并回到第一页
|
|
407
|
+
onReset() {
|
|
408
|
+
this.filters = {
|
|
409
|
+
belOrgNo: "",
|
|
410
|
+
meetSubj: "",
|
|
411
|
+
meetTypeCd: "",
|
|
412
|
+
createDateRange: []
|
|
413
|
+
};
|
|
414
|
+
this.page = 1;
|
|
415
|
+
},
|
|
416
|
+
// 分页器切换页码
|
|
417
|
+
onPageChange(p) {
|
|
418
|
+
this.page = p;
|
|
419
|
+
},
|
|
420
|
+
// 将会议类型编码转换为中文文案
|
|
421
|
+
formatMeetType(code) {
|
|
422
|
+
if (code === "TRAINING") return "培训";
|
|
423
|
+
if (code === "MORNING") return "晨夕会";
|
|
424
|
+
return code || "";
|
|
425
|
+
},
|
|
426
|
+
// 根据会议类型返回不同颜色的 Tag 类型
|
|
427
|
+
getTypeTagType(code) {
|
|
428
|
+
if (code === "TRAINING") return "primary";
|
|
429
|
+
if (code === "MORNING") return "warning";
|
|
430
|
+
return "info";
|
|
431
|
+
},
|
|
432
|
+
// 格式化日期为 yyyy-MM-dd
|
|
433
|
+
formatDate(value) {
|
|
434
|
+
if (!value) return "";
|
|
435
|
+
if (value.length === 10) return value;
|
|
436
|
+
const d = new Date(value);
|
|
437
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
438
|
+
const yyyy = d.getFullYear();
|
|
439
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
440
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
441
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
442
|
+
},
|
|
443
|
+
// 格式化时间为 yyyy-MM-dd HH:mm:ss
|
|
444
|
+
formatDateTime(value) {
|
|
445
|
+
if (!value) return "";
|
|
446
|
+
if (value.length >= 16 && value.includes(" ")) return value;
|
|
447
|
+
const d = new Date(value);
|
|
448
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
449
|
+
const yyyy = d.getFullYear();
|
|
450
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
451
|
+
const dd = String(d.getDate() + 0).padStart(2, "0");
|
|
452
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
453
|
+
const mi = String(d.getMinutes()).padStart(2, "0");
|
|
454
|
+
const ss = String(d.getSeconds()).padStart(2, "0");
|
|
455
|
+
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`;
|
|
456
|
+
},
|
|
457
|
+
// 将各种形式的日期值转换为时间戳,用于排序
|
|
458
|
+
getTimeValue(value) {
|
|
459
|
+
if (!value) return 0;
|
|
460
|
+
const d = new Date(value);
|
|
461
|
+
if (Number.isNaN(d.getTime())) return 0;
|
|
462
|
+
return d.getTime();
|
|
463
|
+
},
|
|
464
|
+
// 点击“详情”:弹出对话框展示会议详细信息
|
|
465
|
+
onView(row) {
|
|
466
|
+
const lines = [
|
|
467
|
+
`会议主题:${row.meetSubj || ""}`,
|
|
468
|
+
`内容:${row.plainContent || ""}`,
|
|
469
|
+
`所属机构:${row.organizationName || ""}`,
|
|
470
|
+
`会议类型:${this.formatMeetType(row.meetTypeCd)}`,
|
|
471
|
+
`创建人:${row.displayName || ""}`,
|
|
472
|
+
`创建日期:${this.formatDate(row.createTm)}`,
|
|
473
|
+
`最近编辑时间:${this.formatDateTime(row.updateTm)}`
|
|
474
|
+
];
|
|
475
|
+
this.$alert(lines.join("\n"), "会议详情", {
|
|
476
|
+
confirmButtonText: "确定"
|
|
477
|
+
});
|
|
478
|
+
},
|
|
479
|
+
// 点击“删除”:二次确认后从当前 rows 中移除
|
|
480
|
+
onDelete(row) {
|
|
481
|
+
this.$confirm(`确定删除会议「${row.meetSubj || ""}」吗?`, "提示", {
|
|
482
|
+
type: "warning",
|
|
483
|
+
confirmButtonText: "确定",
|
|
484
|
+
cancelButtonText: "取消"
|
|
485
|
+
})
|
|
486
|
+
.then(() => {
|
|
487
|
+
this.rows = this.rows.filter(item => item.id !== row.id);
|
|
488
|
+
this.$message({
|
|
489
|
+
type: "success",
|
|
490
|
+
message: "删除成功"
|
|
491
|
+
});
|
|
492
|
+
})
|
|
493
|
+
.catch(() => {});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
</script>
|
|
498
|
+
|
|
499
|
+
<style scoped>
|
|
500
|
+
.meeting-page {
|
|
501
|
+
padding: 24px;
|
|
502
|
+
}
|
|
503
|
+
.meeting-title {
|
|
504
|
+
margin-bottom: 16px;
|
|
505
|
+
}
|
|
506
|
+
.meeting-search-card {
|
|
507
|
+
padding: 12px 16px 4px;
|
|
508
|
+
background: #fafafa;
|
|
509
|
+
border-radius: 4px;
|
|
510
|
+
border: 1px solid #ebeef5;
|
|
511
|
+
margin-bottom: 12px;
|
|
512
|
+
}
|
|
513
|
+
.meeting-search-form {
|
|
514
|
+
display: flex;
|
|
515
|
+
flex-wrap: wrap;
|
|
516
|
+
}
|
|
517
|
+
.meeting-toolbar {
|
|
518
|
+
margin-bottom: 12px;
|
|
519
|
+
}
|
|
520
|
+
.meeting-subject {
|
|
521
|
+
font-weight: 500;
|
|
522
|
+
margin-bottom: 4px;
|
|
523
|
+
}
|
|
524
|
+
.meeting-content {
|
|
525
|
+
font-size: 12px;
|
|
526
|
+
color: #909399;
|
|
527
|
+
}
|
|
528
|
+
.meeting-pagination {
|
|
529
|
+
margin-top: 12px;
|
|
530
|
+
text-align: right;
|
|
531
|
+
}
|
|
532
|
+
.header-wrapper {
|
|
533
|
+
display: inline-flex;
|
|
534
|
+
align-items: center;
|
|
535
|
+
}
|
|
536
|
+
.header-draggable {
|
|
537
|
+
cursor: move;
|
|
538
|
+
}
|
|
539
|
+
.header-label {
|
|
540
|
+
white-space: nowrap;
|
|
541
|
+
}
|
|
542
|
+
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import LineChartPage from '../pages/LineChartPage.vue'
|
|
2
2
|
import MedalSetting from '../pages/MedalSetting.vue'
|
|
3
|
+
import MeetingListPage from '../pages/MeetingListPage.vue'
|
|
3
4
|
|
|
4
5
|
export const routes = [
|
|
5
6
|
{
|
|
@@ -25,5 +26,15 @@ export const routes = [
|
|
|
25
26
|
icon: 'el-icon-medal',
|
|
26
27
|
showInMenu: true
|
|
27
28
|
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
path: '/meeting-list',
|
|
32
|
+
name: 'MeetingList',
|
|
33
|
+
component: MeetingListPage,
|
|
34
|
+
meta: {
|
|
35
|
+
title: '会议列表',
|
|
36
|
+
icon: 'el-icon-date',
|
|
37
|
+
showInMenu: true
|
|
38
|
+
}
|
|
28
39
|
}
|
|
29
40
|
]
|
package/p/split.zip
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vercerl-express-test",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "nodemon --watch src --ext ts --exec \"ts-node src/app.ts\"",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"typecheck": "tsc --noEmit",
|
|
10
10
|
"lint": "eslint .",
|
|
11
11
|
"test": "npm run build && node --test",
|
|
12
|
+
"front-dev": "cd frontEnd && npm run serve",
|
|
12
13
|
"front-build": "cd frontEnd && npm run build",
|
|
13
14
|
"copy-frontend": "rm -rf dist/public && mkdir -p dist/public && cp -R frontEnd/dist/* dist/public/",
|
|
14
15
|
"build:all": "npm run build && npm run front-build && npm run copy-frontend",
|