centaline-data-driven 1.6.71 → 1.6.73
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/release-log.md +26 -0
- package/src/Form.vue +2 -2
- package/src/SearchList.vue +16 -11
- package/src/centaline/dialogList/src/dialog.vue +55 -5
- package/src/centaline/dialogList/src/useDraggable.js +133 -0
- package/src/centaline/dynamicDtd/src/dynamicDtd.vue +107 -7
- package/src/centaline/dynamicForm/src/dynamicForm.vue +203 -217
- package/src/centaline/dynamicForm/src/dynamicFormListTable.vue +220 -99
- package/src/centaline/dynamicSearchList/src/dynamicSearchTable.vue +8 -2
- package/src/centaline/loader/src/ctl/Base.js +3 -0
- package/src/centaline/loader/src/ctl/Dtd.js +4 -1
- package/src/centaline/loader/src/ctl/FormList.js +9 -0
- package/src/centaline/loader/src/ctl/SearchTable.js +1 -1
- package/src/centaline/templateControls/src/dynamicTableCurrency.vue +2 -1
- package/src/main.js +20 -18
- package/wwwroot/static/centaline/centaline-data-driven.js +1934 -1510
- package/wwwroot/static/centaline/centaline-data-driven.js.map +1 -1
package/package.json
CHANGED
package/release-log.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# v1.6.73
|
|
2
|
+
2026-10-10
|
|
3
|
+
|
|
4
|
+
优化
|
|
5
|
+
|
|
6
|
+
弹层支持拖动
|
|
7
|
+
|
|
8
|
+
日期区间支持快捷选项
|
|
9
|
+
|
|
10
|
+
列表行操作按钮,点击后要禁用,防止重复点击导致错误
|
|
11
|
+
|
|
12
|
+
BUG
|
|
13
|
+
|
|
14
|
+
刷新行数据返回0会变成空处理
|
|
15
|
+
|
|
16
|
+
列表打开tab表单,tab表单再打开tab表单,最后一个tab表单保存后没有关闭tab处理
|
|
17
|
+
|
|
18
|
+
表单点保存后,其他按钮没有被遮盖处理
|
|
19
|
+
|
|
20
|
+
# v1.6.72
|
|
21
|
+
2026-09-16
|
|
22
|
+
|
|
23
|
+
优化
|
|
24
|
+
|
|
25
|
+
Field添加flagCollapse:是否可以折叠 默认 false(主要用于表单里的表格控件)
|
|
26
|
+
|
|
1
27
|
# v1.6.71
|
|
2
28
|
2026-08-20
|
|
3
29
|
|
package/src/Form.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div id="form-app" class="data-driven" style="width:100%;height:100%;overflow:auto">
|
|
3
3
|
<!-- <ct-form :source="formdata.content" :apiParam="apiParam"></ct-form> -->
|
|
4
|
-
<ct-form :api="'/
|
|
4
|
+
<ct-form :api="'/plannedfeemanage/receivecommission/getLayoutOfEdit'" :apiParam="apiParam" :topHeight="topHeight" :documentHeight="'600px'"></ct-form>
|
|
5
5
|
<ct-dialog-list></ct-dialog-list>
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
data() {
|
|
13
13
|
return {
|
|
14
14
|
apiParam:{
|
|
15
|
-
"
|
|
15
|
+
"commId":"2609230938188840D96DA7184C3880A2","actionType":"3","pageStyle":"2","pageOnly":"true"
|
|
16
16
|
},
|
|
17
17
|
topHeight:10,
|
|
18
18
|
}
|
package/src/SearchList.vue
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div id="app-search" style="width:100%;height:100%;position: fixed;">
|
|
3
3
|
|
|
4
|
-
<!--
|
|
4
|
+
<!-- CCAI -->
|
|
5
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/third-dept-tran/transaction-workflow/getLayoutOfSearch'" :searchDataApi="'/api/third-dept-tran/transaction-workflow/list'"></ct-searchlist> -->
|
|
5
6
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/third-dept-tran/tran-list/layout'" :searchDataApi="'/api/third-dept-tran/tran-list'"></ct-searchlist> -->
|
|
6
7
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/third-dept-tran/profit-return/layout'" :searchDataApi="'/api/third-dept-tran/profit-return'"></ct-searchlist> -->
|
|
7
8
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/third-dept-tran/tran-list/tran-emp-achievement-layout'" :searchDataApi="'/api/third-dept-tran/tran-list/tran-emp-achievement-list'"></ct-searchlist> -->
|
|
8
9
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/finance/tran-commission-allocate/process-layout'" :searchDataApi="'/api/finance/tran-commission-allocate/process-list'"></ct-searchlist> -->
|
|
9
10
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/shift-approver/layout'" :searchDataApi="'/api/shift-approver/list'"></ct-searchlist> -->
|
|
10
11
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/api/necessaryFile/importTransFile/getLayoutOfSearch'" :searchDataApi="'/api/necessaryFile/importTransFile/getTableList'"></ct-searchlist> -->
|
|
11
|
-
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/taskManagement/WorkingCalendarList/getLayoutOfSearch'" :searchDataApi="'
|
|
12
|
-
<!-- <ct-searchlist :searchConditionApi="'/mainlandsecond/CustAndContractRegSumList/getLayoutOfSearch'" :searchDataApi="'/mainlandsecond/CustAndContractRegSumList/getList'"></ct-searchlist> -->
|
|
13
|
-
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/filemanage/batchdownlist/getLayoutOfSearch'" :searchDataApi="'/filemanage/batchdownlist/getList'"></ct-searchlist> -->
|
|
12
|
+
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/api/taskManagement/WorkingCalendarList/getLayoutOfSearch'" :searchDataApi="'/api/taskManagement/WorkingCalendarList/getList'"></ct-searchlist> -->
|
|
13
|
+
<!-- <ct-searchlist :searchConditionApi="'/api/mainlandsecond/CustAndContractRegSumList/getLayoutOfSearch'" :searchDataApi="'/api/mainlandsecond/CustAndContractRegSumList/getList'"></ct-searchlist> -->
|
|
14
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/filemanage/batchdownlist/getLayoutOfSearch'" :searchDataApi="'/api/filemanage/batchdownlist/getList'"></ct-searchlist> -->
|
|
14
15
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/finance/tran-commission-allocate/process-layout'" :searchDataApi="'/api/finance/tran-commission-allocate/process-list'"></ct-searchlist> -->
|
|
15
16
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/finance/invoice-apply/layout'" :searchDataApi="'/api/finance/invoice-apply/list'"></ct-searchlist> -->
|
|
16
17
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/approveManage/contractBatchOperation/getLayoutOfSearch'" :searchDataApi="'/api/approveManage/contractBatchOperation/getTableList'"></ct-searchlist> -->
|
|
17
18
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/distribution/standing-book/layout'" :searchDataApi="'/api/distribution/standing-book/list'"></ct-searchlist> -->
|
|
18
19
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/commission-role-period/commissionRoleLayout'" :searchDataApi="'/api/commission-role-period/commissionRoleList'"></ct-searchlist> -->
|
|
19
|
-
|
|
20
|
-
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/
|
|
20
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/compareList/getLayoutOfSearch'" :searchDataApi="'/api/compareList/getTableList'"></ct-searchlist> -->
|
|
21
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/wf/todo/layout'" :searchDataApi="'/api/wf/todo/list'"></ct-searchlist> -->
|
|
22
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/api/shift-approver/layout'" :searchDataApi="'/api/shift-approver/list'"></ct-searchlist> -->
|
|
21
23
|
|
|
22
24
|
<!-- CCES -->
|
|
23
25
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/salemattersmanage/agentuserlist/getLayoutOfSearch'" :searchDataApi="'/salemattersmanage/agentuserlist/getList'"></ct-searchlist> -->
|
|
@@ -40,6 +42,7 @@
|
|
|
40
42
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/employeelist/getLayoutOfSearch'" :searchDataApi="'/employeelist/getList'"></ct-searchlist> -->
|
|
41
43
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/estatemanage/estatlist/getLayoutOfSearch'" :searchDataApi="'/estatemanage/estatlist/getList'"></ct-searchlist> -->
|
|
42
44
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/system/AreaList/getLayoutOfSearch'" :searchDataApi="'/system/AreaList/getList'"></ct-searchlist> -->
|
|
45
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/systemmanage/CustomerTemplateList/getLayoutOfSearch'" :searchDataApi="'/systemmanage/CustomerTemplateList/getListOfSearchModel'"></ct-searchlist> -->
|
|
43
46
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/salemattersmanage/priceuploadlist/getLayoutOfSearch'" :searchDataApi="'//salemattersmanage/priceuploadlist/getList'"></ct-searchlist> -->
|
|
44
47
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/app/workbenchdetails/getContractLayoutOfSearch'" :searchDataApi="'/app/workbenchdetails/getContractList'"></ct-searchlist> -->
|
|
45
48
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/selectionactivitymanage/EvaluationActWorksList/getLayoutOfSearch'" :searchDataApi="'/selectionactivitymanage/EvaluationActWorksList/getListOfSearchModel'"></ct-searchlist> -->
|
|
@@ -48,17 +51,18 @@
|
|
|
48
51
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/customermanage/ProjectCustomerList/getLayoutOfSearch'" :searchDataApi="'/customermanage/ProjectCustomerList/getList'"></ct-searchlist> -->
|
|
49
52
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/dealmanagementreport/StandingBookSZList/getLayoutOfSearch'" :searchDataApi="'/dealmanagementreport/StandingBookSZList/getList'"></ct-searchlist> -->
|
|
50
53
|
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/dealmanagementreport/standingbookreport/getLayoutOfSearch'" :searchDataApi="'/dealmanagementreport/standingbookreport/getList'"></ct-searchlist> -->
|
|
51
|
-
<ct-searchlist :apiParam="para" :searchConditionApi="'/saleconfigurationmanagement/CurrencyTypeExchangeRateList/getLayoutOfSearch'" :searchDataApi="'/saleconfigurationmanagement/CurrencyTypeExchangeRateList/getListOfSearchModel'"></ct-searchlist>
|
|
54
|
+
<!-- <ct-searchlist :apiParam="para" :searchConditionApi="'/saleconfigurationmanagement/CurrencyTypeExchangeRateList/getLayoutOfSearch'" :searchDataApi="'/saleconfigurationmanagement/CurrencyTypeExchangeRateList/getListOfSearchModel'"></ct-searchlist> -->
|
|
55
|
+
<ct-searchlist :apiParam="para" :searchConditionApi="'/invoicemanage/CommissionInvoiceList/getLayoutOfSearch'" :searchDataApi="'/invoicemanage/CommissionInvoiceList/getList'"></ct-searchlist>
|
|
52
56
|
<!-- CCES -->
|
|
53
57
|
|
|
54
58
|
<!-- <ct-searchlist :apiParam="para"
|
|
55
|
-
:searchConditionApi="'/
|
|
56
|
-
:searchDataApi="'/
|
|
59
|
+
:searchConditionApi="'/transaction/adjustRecord/getLayoutOfSearch'"
|
|
60
|
+
:searchDataApi="'/transaction/adjustRecord/getTableList'">
|
|
57
61
|
</ct-searchlist> -->
|
|
58
62
|
|
|
59
63
|
<!-- <ct-searchlist :apiParam="para"
|
|
60
|
-
:searchConditionApi="'/
|
|
61
|
-
:searchDataApi="'/
|
|
64
|
+
:searchConditionApi="'/transfer_subscribe_master/layout'"
|
|
65
|
+
:searchDataApi="'/transfer_subscribe_master/transferSubscribeMasterList'">
|
|
62
66
|
</ct-searchlist> -->
|
|
63
67
|
|
|
64
68
|
<!-- <ct-searchlist :apiParam="para"
|
|
@@ -124,6 +128,7 @@
|
|
|
124
128
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/ReportAttendanceExceptionList/getLayoutOfSearch'" :searchDataApi="'/ReportAttendanceExceptionList/getListOfSearchModel'"></ct-searchlist> -->
|
|
125
129
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/PersonHolidayList/getLayoutOfSearch'" :searchDataApi="'/PersonHolidayList/getListOfSearchModel'"></ct-searchlist> -->
|
|
126
130
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/EmployeeAttendanceBillList/getLayoutOfSearch'" :searchDataApi="'/EmployeeAttendanceBillList/getListOfSearchModel'"></ct-searchlist> -->
|
|
131
|
+
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/EmployeeAttendanceBillList/getLayoutOfSearchForMy'" :searchDataApi="'/EmployeeAttendanceBillList/getListOfSearchModelForMy'"></ct-searchlist> -->
|
|
127
132
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/HolidayTypeList/getLayoutOfSearch'" :searchDataApi="'/HolidayTypeList/getListOfSearchModel'"></ct-searchlist> -->
|
|
128
133
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/SystemLogList/getLayoutOfSearch'" :searchDataApi="'/SystemLogList/getListOfSearchModel'"></ct-searchlist> -->
|
|
129
134
|
<!-- <ct-searchlist :appRootUrl="appRootUrl" :searchConditionApi="'/AttendanceBalanceAlertList/getLayoutOfSearch'" :searchDataApi="'/AttendanceBalanceAlertList/getListOfSearchModel'"></ct-searchlist> -->
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { useDraggable } from './useDraggable.js'
|
|
2
3
|
export default {
|
|
3
4
|
name: 'ctDialog',
|
|
4
5
|
props: {
|
|
@@ -14,6 +15,9 @@ export default {
|
|
|
14
15
|
captionBarButtons: [],
|
|
15
16
|
modelSelf: null,
|
|
16
17
|
submitCancelData: null,
|
|
18
|
+
draggable: null,
|
|
19
|
+
position: { left: 0, top: 0 },
|
|
20
|
+
hasDragged: false
|
|
17
21
|
};
|
|
18
22
|
},
|
|
19
23
|
activated() {
|
|
@@ -23,6 +27,9 @@ export default {
|
|
|
23
27
|
},
|
|
24
28
|
destroyed() {
|
|
25
29
|
this.$off();
|
|
30
|
+
if (this.draggable) {
|
|
31
|
+
this.draggable.destroy()
|
|
32
|
+
}
|
|
26
33
|
if (this.$el.parentNode) this.$el.parentNode.removeChild(this.$el);
|
|
27
34
|
this.modelSelf = null;
|
|
28
35
|
this.$el = null;
|
|
@@ -43,7 +50,28 @@ export default {
|
|
|
43
50
|
this.contentTop = this.$refs.content.scrollTop;
|
|
44
51
|
ev.cancelBubble = true;
|
|
45
52
|
ev.stopPropagation();
|
|
46
|
-
},
|
|
53
|
+
},
|
|
54
|
+
startDrag(e) {
|
|
55
|
+
if (this.draggable) {
|
|
56
|
+
this.draggable.startDrag(e)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
computed: {
|
|
61
|
+
containerStyle() {
|
|
62
|
+
if (this.hasDragged) {
|
|
63
|
+
return {
|
|
64
|
+
position: 'fixed',
|
|
65
|
+
left: this.position.left + 'px',
|
|
66
|
+
top: this.position.top + 'px',
|
|
67
|
+
margin: '0'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
margin: 'auto',
|
|
72
|
+
position: 'relative'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
47
75
|
},
|
|
48
76
|
mounted() {
|
|
49
77
|
//this.$el.parentNode.removeChild(this.$el);
|
|
@@ -53,6 +81,14 @@ export default {
|
|
|
53
81
|
//else {
|
|
54
82
|
// document.body.appendChild(this.$el);
|
|
55
83
|
//}
|
|
84
|
+
this.draggable = useDraggable('.ct-dialog_draggable', { left: 0, top: 0 })
|
|
85
|
+
// 注册更新回调,拖动时同步到组件响应式数据
|
|
86
|
+
this.draggable.onUpdate(() => {
|
|
87
|
+
const pos = this.draggable.getPosition()
|
|
88
|
+
this.position.left = pos.left
|
|
89
|
+
this.position.top = pos.top
|
|
90
|
+
this.hasDragged = this.draggable.getHasDragged()
|
|
91
|
+
})
|
|
56
92
|
},
|
|
57
93
|
render: function (h) {
|
|
58
94
|
var self = this;
|
|
@@ -86,10 +122,14 @@ export default {
|
|
|
86
122
|
// 'dialog-cover'
|
|
87
123
|
// ]}),
|
|
88
124
|
h('div', {
|
|
125
|
+
// style: {
|
|
126
|
+
// 'margin': 'auto',
|
|
127
|
+
// 'position': 'relative'
|
|
128
|
+
// },
|
|
129
|
+
class: 'ct-dialog_draggable', // 增加 class
|
|
89
130
|
style: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
},
|
|
131
|
+
...this.containerStyle
|
|
132
|
+
}
|
|
93
133
|
//'class': [
|
|
94
134
|
// 'dialog-content '
|
|
95
135
|
//]
|
|
@@ -121,8 +161,14 @@ export default {
|
|
|
121
161
|
style: {
|
|
122
162
|
'position': 'relative',
|
|
123
163
|
'padding': '10px 20px 10px 20px',
|
|
124
|
-
'height': '44px'
|
|
164
|
+
'height': '44px',
|
|
165
|
+
'cursor': this.hasDragged ? 'move' : 'default'
|
|
125
166
|
},
|
|
167
|
+
on: {
|
|
168
|
+
'mousedown': (e) => {
|
|
169
|
+
this.startDrag(e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
126
172
|
}, [
|
|
127
173
|
h('span',
|
|
128
174
|
{
|
|
@@ -350,4 +396,8 @@ export default {
|
|
|
350
396
|
background-color: #e4624c;
|
|
351
397
|
color: fff;
|
|
352
398
|
}
|
|
399
|
+
|
|
400
|
+
.ct-dialog_header{
|
|
401
|
+
cursor: move;
|
|
402
|
+
}
|
|
353
403
|
</style>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对话框拖动工具函数 (Vue2 兼容版)
|
|
3
|
+
* @param {string} selector - 要拖动的容器选择器(默认 '.ct-dialog_draggable')
|
|
4
|
+
* @param {Object} initialPosition - 初始位置 { left, top }
|
|
5
|
+
* @returns {Object} { startDrag, getContainerStyle, onUpdate, getPosition, getHasDragged, destroy }
|
|
6
|
+
*/
|
|
7
|
+
export function useDraggable(selector = '.ct-dialog_draggable', initialPosition = { left: 0, top: 0 }) {
|
|
8
|
+
let hasDragged = false
|
|
9
|
+
let isDragging = false
|
|
10
|
+
let position = Object.assign({}, initialPosition)
|
|
11
|
+
let offset = { x: 0, y: 0 }
|
|
12
|
+
let updateCallbacks = []
|
|
13
|
+
let currentOnDrag = null
|
|
14
|
+
let currentStopDrag = null
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 鼠标按下开始拖动
|
|
18
|
+
* @param {MouseEvent} e
|
|
19
|
+
*/
|
|
20
|
+
function startDrag(e) {
|
|
21
|
+
// 过滤按钮、关闭图标等元素,避免误触发
|
|
22
|
+
if (e.target.closest('button, .el-icon-close, [role="button"]')) return
|
|
23
|
+
|
|
24
|
+
// 查找真正要移动的对话框容器
|
|
25
|
+
const targetEl = e.currentTarget.closest(selector)
|
|
26
|
+
if (!targetEl) return
|
|
27
|
+
|
|
28
|
+
// 记录鼠标与容器左上角的偏移
|
|
29
|
+
const rect = targetEl.getBoundingClientRect()
|
|
30
|
+
offset.x = e.clientX - rect.left
|
|
31
|
+
offset.y = e.clientY - rect.top
|
|
32
|
+
|
|
33
|
+
// 首次拖动时记录当前位置
|
|
34
|
+
if (!hasDragged) {
|
|
35
|
+
position.left = rect.left
|
|
36
|
+
position.top = rect.top
|
|
37
|
+
hasDragged = true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
isDragging = true
|
|
41
|
+
|
|
42
|
+
// 将内部函数保存为闭包变量,以便后续销毁时移除
|
|
43
|
+
currentOnDrag = function (ev) {
|
|
44
|
+
if (!isDragging) return
|
|
45
|
+
position.left = ev.clientX - offset.x
|
|
46
|
+
position.top = ev.clientY - offset.y
|
|
47
|
+
// 通知视图更新
|
|
48
|
+
updateCallbacks.forEach(cb => cb())
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
currentStopDrag = function () {
|
|
52
|
+
isDragging = false
|
|
53
|
+
document.removeEventListener('mousemove', currentOnDrag)
|
|
54
|
+
document.removeEventListener('mouseup', currentStopDrag)
|
|
55
|
+
currentOnDrag = null
|
|
56
|
+
currentStopDrag = null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
document.addEventListener('mousemove', currentOnDrag)
|
|
60
|
+
document.addEventListener('mouseup', currentStopDrag)
|
|
61
|
+
|
|
62
|
+
// 阻止默认行为和文本选择
|
|
63
|
+
e.preventDefault()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 对话框容器动态样式
|
|
68
|
+
* - 未拖动前:margin: auto; position: relative; (保持居中)
|
|
69
|
+
* - 拖动后:position: fixed; left/top 由拖动位置控制
|
|
70
|
+
*/
|
|
71
|
+
function getContainerStyle() {
|
|
72
|
+
if (hasDragged) {
|
|
73
|
+
return {
|
|
74
|
+
position: 'fixed',
|
|
75
|
+
left: position.left + 'px',
|
|
76
|
+
top: position.top + 'px',
|
|
77
|
+
margin: '0'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
margin: 'auto',
|
|
82
|
+
position: 'relative'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 注册视图更新回调(组件侧调用,用于同步响应式数据)
|
|
88
|
+
*/
|
|
89
|
+
function onUpdate(cb) {
|
|
90
|
+
updateCallbacks.push(cb)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 获取当前位置
|
|
95
|
+
*/
|
|
96
|
+
function getPosition() {
|
|
97
|
+
return Object.assign({}, position)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 获取是否已拖动过
|
|
102
|
+
*/
|
|
103
|
+
function getHasDragged() {
|
|
104
|
+
return hasDragged
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 销毁(清理事件监听器和回调)
|
|
109
|
+
*/
|
|
110
|
+
function destroy() {
|
|
111
|
+
updateCallbacks = []
|
|
112
|
+
// 清理可能残留的全局事件监听器
|
|
113
|
+
if (currentOnDrag) {
|
|
114
|
+
document.removeEventListener('mousemove', currentOnDrag)
|
|
115
|
+
currentOnDrag = null
|
|
116
|
+
}
|
|
117
|
+
if (currentStopDrag) {
|
|
118
|
+
document.removeEventListener('mouseup', currentStopDrag)
|
|
119
|
+
currentStopDrag = null
|
|
120
|
+
}
|
|
121
|
+
isDragging = false
|
|
122
|
+
hasDragged = false
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
startDrag,
|
|
127
|
+
getContainerStyle,
|
|
128
|
+
onUpdate,
|
|
129
|
+
getPosition,
|
|
130
|
+
getHasDragged,
|
|
131
|
+
destroy
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
</div>
|
|
8
8
|
<div class="ct-datepicker" v-if="model !== null" :class="[model.showLabel?'showLabel':'']">
|
|
9
9
|
<el-date-picker class="ct-date-picker-editor" v-model="model.value"
|
|
10
|
-
v-bind="model.attrs"
|
|
10
|
+
v-bind="model.attrs" name="startDate"
|
|
11
11
|
@change="changeModel($event)"
|
|
12
12
|
@clear="changeModel($event)"
|
|
13
|
-
:picker-options="
|
|
13
|
+
:picker-options="startPickerOptions"
|
|
14
14
|
:placeholder="model.placeholder"
|
|
15
15
|
:disabled="model.lock">
|
|
16
16
|
</el-date-picker>
|
|
17
17
|
<span class="ct-date-picker-span">-</span>
|
|
18
18
|
<el-date-picker class="ct-date-picker-editor" v-model="model.value1"
|
|
19
|
-
v-bind="model.attrs"
|
|
19
|
+
v-bind="model.attrs" name="endDate"
|
|
20
20
|
@change="changeModel($event)"
|
|
21
21
|
@clear="changeModel($event)"
|
|
22
|
-
:picker-options="
|
|
22
|
+
:picker-options="endPickerOptions"
|
|
23
23
|
:placeholder="model.placeholder1"
|
|
24
24
|
:disabled="model.lock">
|
|
25
25
|
</el-date-picker>
|
|
@@ -45,10 +45,22 @@
|
|
|
45
45
|
},
|
|
46
46
|
data() {
|
|
47
47
|
return {
|
|
48
|
-
|
|
48
|
+
startPickerOptions: this.getPickerOptions(),
|
|
49
|
+
endPickerOptions: this.getPickerOptions(),
|
|
50
|
+
shortcutDefs : [
|
|
51
|
+
{ displayName: '今日', name: '0', code: 'd' },
|
|
52
|
+
{ displayName: '最近3天', name: '-3', code: 'd' },
|
|
53
|
+
{ displayName: '最近7天', name: '-7', code: 'd' },
|
|
54
|
+
{ displayName: '最近半月', name: '-15', code: 'd' },
|
|
55
|
+
{ displayName: '最近一月', name: '-30', code: 'd' },
|
|
56
|
+
{ displayName: '上周', name: '-1', code: 'w' },
|
|
57
|
+
{ displayName: '本月', name: '0', code: 'm' },
|
|
58
|
+
{ displayName: '上个月', name: '-1', code: 'm' },
|
|
59
|
+
{ displayName: '去年', name: '-1', code: 'y' },
|
|
60
|
+
],
|
|
49
61
|
};
|
|
50
62
|
},
|
|
51
|
-
mounted() {
|
|
63
|
+
mounted() {
|
|
52
64
|
var self = this;
|
|
53
65
|
this.$nextTick(function () {
|
|
54
66
|
if (self.vmodel) {
|
|
@@ -73,7 +85,7 @@
|
|
|
73
85
|
},
|
|
74
86
|
methods: {
|
|
75
87
|
getPickerOptions() {
|
|
76
|
-
let self = this
|
|
88
|
+
let self = this;
|
|
77
89
|
return {
|
|
78
90
|
disabledDate(time) {
|
|
79
91
|
let validate = false;
|
|
@@ -87,9 +99,97 @@
|
|
|
87
99
|
}
|
|
88
100
|
}
|
|
89
101
|
},
|
|
102
|
+
calcDateRange(code, offset) {
|
|
103
|
+
/**
|
|
104
|
+
* 根据 code + name 计算日期区间 [start, end]
|
|
105
|
+
* @param {String} code - d:天 | w:周 | m:月 | y:年
|
|
106
|
+
* @param {Number} offset - 偏移量,0=当前,负数=往前推
|
|
107
|
+
* @returns {[Date, Date]} [startDate, endDate]
|
|
108
|
+
*/
|
|
109
|
+
const now = new Date();
|
|
110
|
+
let start, end;
|
|
111
|
+
|
|
112
|
+
switch (code) {
|
|
113
|
+
case 'd': {
|
|
114
|
+
// 按天:end=今天零点,start=今天+offset天零点
|
|
115
|
+
end = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
116
|
+
start = new Date(end);
|
|
117
|
+
if(offset !== 0){
|
|
118
|
+
start.setDate(start.getDate() + offset + 1);
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case 'w': {
|
|
123
|
+
// 按周:以周一为一周起始
|
|
124
|
+
// 先算出本周一
|
|
125
|
+
const dayOfWeek = now.getDay() || 7; // 周日=7
|
|
126
|
+
const thisMonday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - dayOfWeek + 1);
|
|
127
|
+
// 偏移到目标周的周一
|
|
128
|
+
start = new Date(thisMonday);
|
|
129
|
+
start.setDate(start.getDate() + offset * 7);
|
|
130
|
+
// 目标周的周日
|
|
131
|
+
end = new Date(start);
|
|
132
|
+
end.setDate(end.getDate() + 6);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
case 'm': {
|
|
136
|
+
// 按月:目标月的1号 ~ 最后一天
|
|
137
|
+
const targetMonth = new Date(now.getFullYear(), now.getMonth() + offset, 1);
|
|
138
|
+
start = new Date(targetMonth);
|
|
139
|
+
end = new Date(targetMonth.getFullYear(), targetMonth.getMonth() + 1, 0);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case 'y': {
|
|
143
|
+
// 按年:目标年的1月1日 ~ 12月31日
|
|
144
|
+
const targetYear = now.getFullYear() + offset;
|
|
145
|
+
start = new Date(targetYear, 0, 1);
|
|
146
|
+
end = new Date(targetYear, 11, 31);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
default:
|
|
150
|
+
end = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
151
|
+
start = new Date(end);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 统一归零时分秒,避免时间部分干扰比较
|
|
155
|
+
start.setHours(0, 0, 0, 0);
|
|
156
|
+
end.setHours(0, 0, 0, 0);
|
|
157
|
+
|
|
158
|
+
return [start, end];
|
|
159
|
+
},
|
|
160
|
+
getShortcuts(type) {
|
|
161
|
+
let self = this;
|
|
162
|
+
|
|
163
|
+
if (!self.model || self.model.attrs.type !== 'date') return null;
|
|
164
|
+
|
|
165
|
+
// 核心改动:动态选择数据源
|
|
166
|
+
const defs = (self.model.selectItems1 && Array.isArray(self.model.selectItems1) && self.model.selectItems1.length > 0)
|
|
167
|
+
? self.model.selectItems1
|
|
168
|
+
: self.shortcutDefs;
|
|
169
|
+
|
|
170
|
+
return defs.map(def => ({
|
|
171
|
+
text: def.displayName,
|
|
172
|
+
onClick(picker) {
|
|
173
|
+
// ⚡ 仅在用户点击时才计算日期,保证始终使用当前时间
|
|
174
|
+
const offset = parseInt(def.name, 10);
|
|
175
|
+
const [start, end] = self.calcDateRange(def.code, offset);
|
|
176
|
+
|
|
177
|
+
if (type === 'start') {
|
|
178
|
+
self.$set(self.model, 'value1', end);
|
|
179
|
+
picker.$emit('pick', start);
|
|
180
|
+
} else {
|
|
181
|
+
self.$set(self.model, 'value', start);
|
|
182
|
+
picker.$emit('pick', end);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}));
|
|
186
|
+
},
|
|
90
187
|
load(data) {
|
|
91
188
|
this.model = data;
|
|
92
189
|
this.model.self=this;
|
|
190
|
+
|
|
191
|
+
this.startPickerOptions.shortcuts = this.getShortcuts('start');
|
|
192
|
+
this.endPickerOptions.shortcuts = this.getShortcuts('end');
|
|
93
193
|
},
|
|
94
194
|
changeModel(event) {
|
|
95
195
|
this.inputHandler(event);
|