centaline-data-driven 1.6.72 → 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.72",
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,22 @@
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
+
1
20
  # v1.6.72
2
21
  2026-09-16
3
22
 
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="'/api/third-dept-tran/transaction/detail'" :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
- "originalTraId":"1526444754463850498","columnName":"transactionNo","actionType":"1","pageStyle":"2","pageTitle":"成交报告","pageOnly":"true"
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);