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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "centaline-data-driven",
3
- "version": "1.6.71",
3
+ "version": "1.6.73",
4
4
  "description": "ccai",
5
5
  "author": "hjc <3226136347@qq.com>",
6
6
  "private": false,
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="'/PropertyTrust/readDetail'" :apiParam="apiParam" :topHeight="topHeight" :documentHeight="'600px'"></ct-form>
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
- "trustID":"2082015429542465536","actionType":1
15
+ "commId":"2609230938188840D96DA7184C3880A2","actionType":"3","pageStyle":"2","pageOnly":"true"
16
16
  },
17
17
  topHeight:10,
18
18
  }
@@ -1,23 +1,25 @@
1
1
  <template>
2
2
  <div id="app-search" style="width:100%;height:100%;position: fixed;">
3
3
 
4
- <!-- <ct-searchlist :searchConditionApi="'/api/third-dept-tran/transaction-workflow/getLayoutOfSearch'" :searchDataApi="'/api/third-dept-tran/transaction-workflow/list'"></ct-searchlist> -->
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="'//taskManagement/WorkingCalendarList/getList'"></ct-searchlist> -->
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="'/compareList/getLayoutOfSearch'" :searchDataApi="'/compareList/getTableList'"></ct-searchlist> -->
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="'/api/transaction/adjustRecord/getLayoutOfSearch'"
56
- :searchDataApi="'/api/transaction/adjustRecord/getTableList'">
59
+ :searchConditionApi="'/transaction/adjustRecord/getLayoutOfSearch'"
60
+ :searchDataApi="'/transaction/adjustRecord/getTableList'">
57
61
  </ct-searchlist> -->
58
62
 
59
63
  <!-- <ct-searchlist :apiParam="para"
60
- :searchConditionApi="'/api/transfer_subscribe_master/layout'"
61
- :searchDataApi="'/api/transfer_subscribe_master/transferSubscribeMasterList'">
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
- 'margin': 'auto',
91
- 'position': 'relative'
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="pickerOptions"
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="pickerOptions"
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
- pickerOptions: this.getPickerOptions()
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);