cloud-web-corejs 1.0.54-dev.801 → 1.0.54-dev.802

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.
Files changed (31) hide show
  1. package/package.json +1 -1
  2. package/src/components/baseArea/index.vue +82 -27
  3. package/src/components/table/tableForm.vue +16 -5
  4. package/src/components/table/tableFormMixin.js +35 -7
  5. package/src/components/wf/content.vue +9 -1
  6. package/src/components/wf/wfActionDropdown.vue +32 -5
  7. package/src/components/wf/wfActionItems.js +22 -2
  8. package/src/components/wf/wfUtil.js +34 -10
  9. package/src/components/xform/form-designer/designer.js +6 -1
  10. package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +9 -3
  11. package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +3 -2
  12. package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +3 -12
  13. package/src/components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin.js +2 -46
  14. package/src/components/xform/form-designer/form-widget/field-widget/mixins/relative-default-mixin.js +107 -0
  15. package/src/components/xform/form-designer/form-widget/field-widget/mixins/relativeDateUtil.js +321 -0
  16. package/src/components/xform/form-designer/form-widget/field-widget/mixins/time-limit-mixin.js +2 -17
  17. package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +3 -2
  18. package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +3 -12
  19. package/src/components/xform/form-designer/setting-panel/property-editor/field-date/date-defaultValue-editor.vue +35 -36
  20. package/src/components/xform/form-designer/setting-panel/property-editor/field-date-range/date-range-defaultValue-editor.vue +35 -18
  21. package/src/components/xform/form-designer/setting-panel/property-editor/field-time/time-defaultValue-editor.vue +34 -36
  22. package/src/components/xform/form-designer/setting-panel/property-editor/field-time-range/time-range-defaultValue-editor.vue +35 -18
  23. package/src/components/xform/form-designer/setting-panel/property-editor/fixedQuery-editor.vue +39 -0
  24. package/src/components/xform/form-designer/setting-panel/property-editor/relative-default-block.vue +369 -0
  25. package/src/components/xform/form-designer/setting-panel/propertyRegister.js +1 -0
  26. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +34 -2
  27. package/src/components/xform/form-render/container-item/data-table-mixin.js +116 -74
  28. package/src/components/xform/lang/en-US.js +3 -0
  29. package/src/components/xform/lang/zh-CN.js +3 -0
  30. package/src/components/xform/utils/fixedQueryUtil.js +93 -0
  31. package/src/views/user/wf/wf_manage/list.vue +17 -1
@@ -82,6 +82,9 @@ f = async function (option) {
82
82
  let showStartBtn = option.showStartBtn != null ? option.showStartBtn : true;
83
83
  let showModifyBtn = option.showModifyBtn != null ? option.showModifyBtn : true;
84
84
  let contentInstance = null; //流程面板实例,标题栏下拉要点它的方法
85
+ //宿主声明「不挂流程信息面板」:面板整棵 v-if 掉,标题栏那份审批入口也不能挂
86
+ let _hideWf = that._hideWf || that.$attrs._hideWf;
87
+ let isHideWf = _hideWf === true || _hideWf === 'true';
85
88
 
86
89
  if (wfInfo) {
87
90
  let wfModel = configUtil.settingConfig.wfModel || 1;
@@ -103,8 +106,6 @@ f = async function (option) {
103
106
  });
104
107
  instances.push(instance);
105
108
  contentInstance = instance;
106
- let _hideWf = that._hideWf || that.$attrs._hideWf;
107
- let isHideWf = _hideWf === true || _hideWf === 'true';
108
109
  if (!_hideWf && slideWrap) {
109
110
  let navVm = new configUtil.Vue({
110
111
  render: function (h) {
@@ -198,15 +199,21 @@ f = async function (option) {
198
199
  appendPrevChildDom(wfBtnRegion, startVm.$mount().$el)
199
200
  }
200
201
 
201
- /* 审批操作下拉:开了 wfActionInHeaderEnabled 时,在详情模块标题栏再挂一份「流程操作」
202
- 下拉。流程模块里的原按钮条不动、不隐藏;下拉项点击走流程面板实例上的同一套方法。
202
+ /* 审批操作:开了 wfActionInHeaderEnabled 时,在详情模块标题栏再挂一份 —— 通过/驳回/撤回
203
+ 平铺成独立按钮,其余收进「流程操作」下拉(wfActionDropdown.vue)。流程模块里的
204
+ 原按钮条不动、不隐藏;点击走流程面板实例上的同一套方法。
203
205
  放在「修改单据」「流程启动」之后挂——appendPrevChildDom 是前插,最后插的排最左,
204
- 最终顺序:流程操作下拉 → 修改单据 → 内建/业务按钮。
205
- hiddenAllButton / 素身详情(取不到 .fr) 自动跳过。 */
206
- let actionInHeader = option.actionInHeader != null
207
- ? option.actionInHeader
208
- : configUtil.settingConfig.wfActionInHeaderEnabled === true;
209
- if (actionInHeader && wfBtnRegion && contentInstance && !option.hiddenAllButton) {
206
+ 最终顺序:通过/驳回/撤回/流程操作 → 修改单据 → 内建/业务按钮。
207
+ hiddenAllButton / 素身详情(取不到 .fr) 自动跳过。
208
+ _hideWf 也必须跳过:那种页面 content.vue 根节点 v-if 掉了,弹框根本没渲染出来,
209
+ 挂上去就是一排点了没反应的按钮(wfInfo 照样有值,光看 items 判断不出来)。 */
210
+ if (shouldMountHeaderActions({
211
+ option,
212
+ settingConfig: configUtil.settingConfig,
213
+ wfBtnRegion,
214
+ contentInstance,
215
+ isHideWf
216
+ })) {
210
217
  let Dropdown = configUtil.Vue.extend(configUtil.getWfObj('/wfActionDropdown.vue'));
211
218
  let dropdownVm = new Dropdown({
212
219
  i18n: that._i18n,
@@ -236,6 +243,23 @@ f = async function (option) {
236
243
  }
237
244
  }
238
245
 
246
+ /* 标题栏那份审批入口挂不挂。抽成函数是为了能单测——done() 整条链路要打 http、要真 DOM。
247
+ ctx: { option, settingConfig, wfBtnRegion, contentInstance, isHideWf } */
248
+ export function shouldMountHeaderActions(ctx) {
249
+ let option = (ctx && ctx.option) || {};
250
+ let settingConfig = (ctx && ctx.settingConfig) || {};
251
+ let actionInHeader = option.actionInHeader != null
252
+ ? option.actionInHeader
253
+ : settingConfig.wfActionInHeaderEnabled === true;
254
+ return !!(
255
+ actionInHeader
256
+ && ctx.wfBtnRegion //素身详情取不到 .d-header > .fr
257
+ && ctx.contentInstance //没流程面板就没方法可调
258
+ && !ctx.isHideWf //面板被 v-if 掉了,挂上去全是哑按钮
259
+ && !option.hiddenAllButton
260
+ );
261
+ }
262
+
239
263
  function getModifyButtonName(that, taskParam) {
240
264
  let buttonName = null;
241
265
  if (!taskParam.buttonName || taskParam.buttonName == "修改单据") {
@@ -1660,10 +1660,13 @@ let chartContainers = [],
1660
1660
  "'}";
1661
1661
  dataTableCon.buttons.push(tableExportButton);
1662
1662
 
1663
+ // 两个查询条件的值由树节点点击注入,勾上「固定查询条件」后
1664
+ // 刷新、查询条件设置的还原/确定都不会把它清掉
1663
1665
  let searchInput = this.copyNewFieldWidget(
1664
1666
  this.getFieldWidgetByType("input")
1665
1667
  );
1666
1668
  searchInput.options.disabled = true;
1669
+ searchInput.options.fixedQuery = true;
1667
1670
  searchInput.options.label = newCon.options.treeLabel;
1668
1671
  dataTableCon.widgetList.push(searchInput);
1669
1672
 
@@ -1672,10 +1675,12 @@ let chartContainers = [],
1672
1675
  );
1673
1676
  searchIdInput.options.disabled = true;
1674
1677
  searchIdInput.options.hidden = true;
1678
+ searchIdInput.options.fixedQuery = true;
1675
1679
  searchIdInput.options.label = `隐藏${newCon.options.treeLabel}ID`;
1676
1680
  dataTableCon.widgetList.push(searchIdInput);
1677
1681
 
1678
- //列表重置的时候,忽略该字段
1682
+ // 存量表单没有 fixedQuery 开关,仍靠 ignoreFields 兜底刷新按钮;
1683
+ // 新建的表单两条通道并存(取并集),不冲突
1679
1684
  dataTableCon.options.onResetTable = `this.resetEvent({\n ignoreFields:['${searchInput.options.name}', '${searchIdInput.options.name}']\n});`;
1680
1685
 
1681
1686
  //初始化树
@@ -17,7 +17,7 @@
17
17
  <template #form>
18
18
  <template v-if="widget.options.isQueryTable">
19
19
  <div class="clearfix screen-btns">
20
- <div class="fl" style="width: 700px;">
20
+ <div class="fl button-drag-zone">
21
21
  <!-- <vxe-button status="primary" class="button-sty" icon="el-icon-upload2"
22
22
  v-if="widget.options.showExportBtn!==false">导出
23
23
  </vxe-button>-->
@@ -247,9 +247,14 @@ div.table-container {
247
247
  }
248
248
  }
249
249
 
250
+ /* 按钮拖放区:宽度自适应,最多占满除右侧刷新/搜索按钮外的空间,超出后按钮换行 */
251
+ .screen-btns .fl.button-drag-zone {
252
+ max-width: calc(100% - 180px);
253
+ }
254
+
250
255
  .sub-form-table {
251
256
  min-height: 68px;
252
- min-width: max-content
257
+ min-width: 200px
253
258
  }
254
259
 
255
260
  .sub-form-table .sub-form-drag-drop-zone {
@@ -257,7 +262,8 @@ div.table-container {
257
262
  }
258
263
 
259
264
  .sub-form-table div.sub-form-table-column {
260
- display: inline-block
265
+ display: inline-block;
266
+ vertical-align: top
261
267
  }
262
268
 
263
269
  </style>
@@ -26,11 +26,12 @@ import emitter from '../../../../../components/xform/utils/emitter'
26
26
  import i18n from "../../../../../components/xform/utils/i18n";
27
27
  import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";
28
28
  import utcTransformMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/mixins/utc-transform-mixin";
29
+ import relativeDefaultMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/mixins/relative-default-mixin";
29
30
 
30
31
  export default {
31
32
  name: "date-range-widget",
32
33
  componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
33
- mixins: [emitter, fieldMixin, i18n, utcTransformMixin],
34
+ mixins: [emitter, fieldMixin, i18n, utcTransformMixin, relativeDefaultMixin],
34
35
  props: {
35
36
  field: Object,
36
37
  parentWidget: Object,
@@ -83,7 +84,7 @@ export default {
83
84
  created() {
84
85
  /* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
85
86
  需要在父组件created中初始化!! */
86
- this.initFieldModel()
87
+ this.initRelativeFieldModel()
87
88
  this.registerToRefList()
88
89
  this.initEventHandler()
89
90
  this.buildFieldRules()
@@ -27,11 +27,12 @@ import i18n from "../../../../../components/xform/utils/i18n";
27
27
  import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";
28
28
  import dateLimitMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin";
29
29
  import utcTransformMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/mixins/utc-transform-mixin";
30
+ import relativeDefaultMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/mixins/relative-default-mixin";
30
31
 
31
32
  export default {
32
33
  name: "date-widget",
33
34
  componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
34
- mixins: [emitter, fieldMixin, i18n, dateLimitMixin, utcTransformMixin],
35
+ mixins: [emitter, fieldMixin, i18n, dateLimitMixin, utcTransformMixin, relativeDefaultMixin],
35
36
  props: {
36
37
  field: Object,
37
38
  parentWidget: Object,
@@ -102,7 +103,7 @@ export default {
102
103
  created() {
103
104
  /* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
104
105
  需要在父组件created中初始化!! */
105
- this.initDateFieldModel()
106
+ this.initRelativeFieldModel()
106
107
  this.registerToRefList()
107
108
  this.initEventHandler()
108
109
  this.buildFieldRules()
@@ -138,16 +139,6 @@ export default {
138
139
  },
139
140
  setNow() {
140
141
  this.$refs.fieldEditor.panel.changeToNow()
141
- },
142
- refreshDefaultValue() {
143
- if (this.designState !== true) {
144
- return
145
- }
146
- if (this.isNowDateValueType(this.field.options.defaultValueType)) {
147
- this.fieldModel = this.getNowDateValue()
148
- } else if (this.field.options.defaultValue !== undefined) {
149
- this.fieldModel = this.field.options.defaultValue
150
- }
151
142
  }
152
143
  }
153
144
  }
@@ -1,4 +1,5 @@
1
- /* 日期组件的最小日期、默认值支持配置为「当前时间」,此处统一解析 */
1
+ /* 日期组件的最小日期支持配置为「当前时间」,此处统一解析。
2
+ 默认值(含「当前时间」与相对偏移)已收敛到 relative-default-mixin,不在此处理。 */
2
3
  export const DATE_VALUE_TYPE_NOW = "now";
3
4
 
4
5
  export default {
@@ -9,35 +10,6 @@ export default {
9
10
  isNowDateValueType(valueType) {
10
11
  return valueType === DATE_VALUE_TYPE_NOW;
11
12
  },
12
- /* 按组件的valueFormat格式化,valueFormat为空时picker的值为Date对象 */
13
- formatDateValue(date, valueFormat) {
14
- if (!valueFormat) {
15
- return date;
16
- }
17
- if (valueFormat === "timestamp") {
18
- return date.getTime();
19
- }
20
- const pad = (val) => (val < 10 ? "0" + val : String(val));
21
- const tokenMap = {
22
- yyyy: String(date.getFullYear()),
23
- yy: String(date.getFullYear()).slice(-2),
24
- MM: pad(date.getMonth() + 1),
25
- dd: pad(date.getDate()),
26
- HH: pad(date.getHours()),
27
- mm: pad(date.getMinutes()),
28
- ss: pad(date.getSeconds()),
29
- };
30
- return valueFormat.replace(
31
- /yyyy|yy|MM|dd|HH|mm|ss/g,
32
- (token) => tokenMap[token]
33
- );
34
- },
35
- /* 当前时间,dates(多选日期)类型的值为数组 */
36
- getNowDateValue() {
37
- const options = this.getDateLimitOptions();
38
- const nowValue = this.formatDateValue(new Date(), options.valueFormat);
39
- return options.type === "dates" ? [nowValue] : nowValue;
40
- },
41
13
  /* 最小日期:固定日期或当前时间 */
42
14
  getDateLimitMinValue() {
43
15
  const options = this.getDateLimitOptions();
@@ -202,21 +174,5 @@ export default {
202
174
  }
203
175
  return "日期超出允许范围";
204
176
  },
205
- /* 默认值配置为「当前时间」时,临时替换 defaultValue 后再走通用的取值逻辑 */
206
- initDateFieldModel() {
207
- const options = this.getDateLimitOptions();
208
- if (!this.isNowDateValueType(options.defaultValueType)) {
209
- this.initFieldModel();
210
- return;
211
- }
212
-
213
- const rawDefaultValue = options.defaultValue;
214
- options.defaultValue = this.getNowDateValue();
215
- try {
216
- this.initFieldModel();
217
- } finally {
218
- options.defaultValue = rawDefaultValue;
219
- }
220
- },
221
177
  },
222
178
  };
@@ -0,0 +1,107 @@
1
+ /**
2
+ * 日期/时间组件「相对默认值」的取值入口(date、date-range、time、time-range 共用)。
3
+ *
4
+ * 相对值必须每次初始化重算,绝不能写回 options.defaultValue —— options 会被序列化保存,
5
+ * 写回就变成死值。这里的做法是:先照常跑 initFieldModel(此时 options.defaultValue 为空,
6
+ * 不会填任何值),再在「本该取默认值」的场景下用 initValue 灌入现算的相对值。
7
+ *
8
+ * 放在 initFieldModel 之后灌值还顺带绕开了 utc-transform-mixin:相对值本身就是本地时间,
9
+ * 若参与 UTC→本地转换会再偏一次时区。
10
+ */
11
+ import { resolveDefaultValueFromOptions } from "./relativeDateUtil";
12
+
13
+ export default {
14
+ methods: {
15
+ /**
16
+ * 当前配置对应的相对默认值;未配相对默认值返回 undefined(调用方走静态默认值)。
17
+ * @param {Date} baseDate 基准时刻,仅测试用
18
+ */
19
+ getRelativeDefaultValue(baseDate) {
20
+ return resolveDefaultValueFromOptions(
21
+ this.field?.options,
22
+ this.field?.type,
23
+ baseDate
24
+ );
25
+ },
26
+
27
+ /** @returns {Boolean} 值是否为空(范围组件的空值是空数组) */
28
+ isEmptyFieldValue(value) {
29
+ if (value === null || value === undefined || value === "") {
30
+ return true;
31
+ }
32
+ return Array.isArray(value) && value.length === 0;
33
+ },
34
+
35
+ /**
36
+ * 是否落在「新增时取默认值」的场景。
37
+ * 判定与 fieldMixin.initFieldModel 里的默认值分支保持一致:值为空 + 新增单据/新增明细行。
38
+ * @returns {Boolean}
39
+ */
40
+ willInitDefaultValue() {
41
+ if (!this.field?.formItemFlag) {
42
+ return false;
43
+ }
44
+ const currentData
45
+ = this.tableParam && this.tableParam.row
46
+ ? this.tableParam.row
47
+ : this.formModel;
48
+ if (!currentData) {
49
+ return false;
50
+ }
51
+ if (!this.isEmptyFieldValue(currentData[this.fieldKeyName])) {
52
+ return false;
53
+ }
54
+ if (this.tableParam) {
55
+ return !this.tableParam.row.id; //明细:只有新增行才填默认值
56
+ }
57
+ const dataId = this.getFormRef()?.dataId ?? null;
58
+ return !dataId; //主表:只有新增单据才填默认值
59
+ },
60
+
61
+ /** 取值入口,替代各日期组件 created 里直接调的 initFieldModel */
62
+ initRelativeFieldModel() {
63
+ const relativeValue = this.getRelativeDefaultValue();
64
+ if (relativeValue === undefined) {
65
+ this.initFieldModel();
66
+ return;
67
+ }
68
+ const shouldInit = this.willInitDefaultValue();
69
+ this.initFieldModel();
70
+ if (shouldInit) {
71
+ this.initValue(relativeValue);
72
+ }
73
+ },
74
+
75
+ /*
76
+ * 表单重置:相对模式按重置时刻重算,与新增时同口径;静态默认值维持 fieldMixin 的行为。
77
+ * 这里不委托 fieldMixin.resetField,是为了不把它那条重依赖链(公式引擎、codemirror)
78
+ * 拖进本文件;它对本 mixin 覆盖的日期/时间组件也只多一段附件组件的分支,用不上。
79
+ */
80
+ resetField() {
81
+ if (this.subFormItemFlag) {
82
+ return;
83
+ }
84
+ const relativeValue = this.getRelativeDefaultValue();
85
+ this.setValue(
86
+ relativeValue === undefined
87
+ ? this.field.options.defaultValue
88
+ : relativeValue
89
+ );
90
+ },
91
+
92
+ /* 设计器里改默认值配置后的预览刷新,由 propertyMixin.emitDefaultValueChange 调用 */
93
+ refreshDefaultValue() {
94
+ if (this.designState !== true) {
95
+ return;
96
+ }
97
+ const relativeValue = this.getRelativeDefaultValue();
98
+ if (relativeValue !== undefined) {
99
+ this.fieldModel = relativeValue;
100
+ return;
101
+ }
102
+ if (this.field.options.defaultValue !== undefined) {
103
+ this.fieldModel = this.field.options.defaultValue;
104
+ }
105
+ },
106
+ },
107
+ };