@nokecy/qc-ui-business 2.0.0-beta.0 → 2.0.0-beta.1

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.
@@ -10,6 +10,7 @@ var _formilyCore = require("@nokecy/formily-core");
10
10
  var _antd = require("antd");
11
11
  var _PortalManager = _interopRequireDefault(require("./PortalManager"));
12
12
  var _formilyReact = require("@nokecy/formily-react");
13
+ var _index = _interopRequireDefault(require("@nokecy/qc-ui-components/draggableModal/index"));
13
14
  var _jsxRuntime = require("react/jsx-runtime");
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
@@ -46,6 +47,13 @@ var SchemaFieldComponents = (0, _formilyReact.createSchemaField)({
46
47
  }
47
48
  });
48
49
 
50
+ /** 表单弹窗的可缩放壳:最小宽度取规范最小一档 560,避免缩到字段挤压。 */
51
+ var ResizableFormModal = function ResizableFormModal(modalProps) {
52
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.default, _objectSpread({
53
+ minWidth: 560
54
+ }, modalProps));
55
+ };
56
+
49
57
  /**
50
58
  * 默认的 useFormSchema hook - 直接返回schema配置
51
59
  */
@@ -83,7 +91,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
83
91
  directFormSchema = props.formSchema,
84
92
  apiConfig = props.apiConfig,
85
93
  _props$width = props.width,
86
- width = _props$width === void 0 ? 800 : _props$width,
94
+ width = _props$width === void 0 ? 720 : _props$width,
87
95
  entityId = props.entityId,
88
96
  _props$title = props.title,
89
97
  title = _props$title === void 0 ? '表单' : _props$title,
@@ -99,6 +107,12 @@ var StandardFormDialog = function StandardFormDialog(props) {
99
107
  customSubmitHandler = props.customSubmitHandler,
100
108
  _props$useUnifiedErro = props.useUnifiedErrorHandling,
101
109
  useUnifiedErrorHandling = _props$useUnifiedErro === void 0 ? true : _props$useUnifiedErro,
110
+ _props$locateFirstErr = props.locateFirstError,
111
+ locateFirstError = _props$locateFirstErr === void 0 ? true : _props$locateFirstErr,
112
+ _props$confirmOnDirty = props.confirmOnDirtyClose,
113
+ confirmOnDirtyClose = _props$confirmOnDirty === void 0 ? true : _props$confirmOnDirty,
114
+ _props$resizable = props.resizable,
115
+ resizable = _props$resizable === void 0 ? true : _props$resizable,
102
116
  _props$useFormSchema = props.useFormSchema,
103
117
  useFormSchemaHook = _props$useFormSchema === void 0 ? defaultUseFormSchema : _props$useFormSchema,
104
118
  _props$useSchemaField = props.useSchemaField,
@@ -245,6 +259,18 @@ var StandardFormDialog = function StandardFormDialog(props) {
245
259
 
246
260
  // 表单验证失败回调
247
261
  var handleValidationFailed = (0, _react.useCallback)(function (form) {
262
+ if (locateFirstError) {
263
+ // 提示里直接写出所在页签与字段,不再拼字段名串(DESIGN.md §6.4)。
264
+ // 只在最上层弹窗内找,避免定位到弹窗下面页面里的字段。
265
+ void (0, _formilyAntd.focusFirstError)(form, {
266
+ root: function root() {
267
+ var _modals;
268
+ var modals = document.querySelectorAll('.ant-modal');
269
+ return (_modals = modals[modals.length - 1]) !== null && _modals !== void 0 ? _modals : document;
270
+ }
271
+ });
272
+ return;
273
+ }
248
274
  var errors = form.errors;
249
275
  var errorFields = Object.keys(errors);
250
276
  if (errorFields.length > 0) {
@@ -276,7 +302,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
276
302
  errors: errors
277
303
  });
278
304
  }
279
- }, []);
305
+ }, [locateFirstError]);
280
306
 
281
307
  // 表单属性配置
282
308
  var formProps = (0, _react.useMemo)(function () {
@@ -417,6 +443,8 @@ var StandardFormDialog = function StandardFormDialog(props) {
417
443
  // 不设置静态 loading,使用 FormDialog 自带的 form.submitting。
418
444
  // @author nokecy
419
445
  maskClosable: false,
446
+ confirmOnDirtyClose: confirmOnDirtyClose,
447
+ modalComponent: resizable ? ResizableFormModal : undefined,
420
448
  onOk: function onOk() {
421
449
  if (confirmingRef.current || loadingRef.current) return false;
422
450
  confirmingRef.current = true;
@@ -458,7 +486,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
458
486
  });
459
487
  });
460
488
  formDialog.forConfirm(handleSubmit).open(formProps);
461
- }, [title, width, portalId, schema, SchemaField, formProps, handleSubmit]);
489
+ }, [title, width, portalId, schema, SchemaField, formProps, handleSubmit, confirmOnDirtyClose, resizable]);
462
490
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_formilyAntd.FormDialog.Portal, {
463
491
  id: portalId,
464
492
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Button, _objectSpread(_objectSpread({
@@ -44,8 +44,23 @@ export interface StandardFormDialogConfig {
44
44
  schemaConfig: FormSchemaConfig;
45
45
  /** API配置 */
46
46
  apiConfig: FormApiConfig;
47
- /** 对话框宽度 */
47
+ /** 对话框宽度,默认 720;规范只取 560 / 720 / 960 三档。 */
48
48
  width?: number;
49
+ /**
50
+ * 校验失败时定位首个错误字段(切页签、展开折叠、滚动并聚焦)并给出带位置的提示,默认 true。
51
+ * 传 false 回到旧行为:只弹出「请检查表单错误:字段名…」的汇总提示。
52
+ */
53
+ locateFirstError?: boolean;
54
+ /**
55
+ * 表单被改过时,关闭(叉、Esc、取消按钮)先弹「继续编辑 / 放弃修改」确认,默认 true(DESIGN.md §6.6)。
56
+ * 判据为 form.modified;提交成功后的关闭不确认。传 false 恢复直接关闭。
57
+ */
58
+ confirmOnDirtyClose?: boolean;
59
+ /**
60
+ * 弹窗可拖动标题移动、拖边框缩放,默认 true(表单字段多时需要放大;宽度默认仍按 width,缩放不持久化)。
61
+ * 最小 560 x 300,且不超过视口 95%。传 false 回到固定尺寸。
62
+ */
63
+ resizable?: boolean;
49
64
  /** 实体ID(编辑时) */
50
65
  entityId?: string | number;
51
66
  /** 标题 */
@@ -565,9 +565,12 @@ var StandardAgGridPlus = exports.StandardAgGridPlus = function StandardAgGridPlu
565
565
  hasFilter: hasFilter || !!filterActive,
566
566
  actions: emptyActions,
567
567
  clearFilterAction: clearFilterAction,
568
- onRetry: onRetry
568
+ onRetry: onRetry,
569
+ // 文案可定制:与基座同名 prop 同一语义(§7.8「『包材』下暂无物料」)
570
+ overrideText: props.overlayNoRowsTemplateText,
571
+ texts: props.emptyState
569
572
  };
570
- }, [lastError, hasFilter, filterActive, emptyActions, clearFilterAction, onRetry]);
573
+ }, [lastError, hasFilter, filterActive, emptyActions, clearFilterAction, onRetry, props.overlayNoRowsTemplateText, props.emptyState]);
571
574
  var onGridReady = (0, _react.useCallback)(function (event) {
572
575
  var _restProps$onGridRead;
573
576
  var api = event.api;
@@ -1,13 +1,14 @@
1
1
  /**
2
- * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间 `YYYY-MM-DD HH:mm:ss`,按浏览器本地时区。
2
+ * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间默认 `YYYY-MM-DD HH:mm:ss`(列表传 'minute' 到分钟),按浏览器本地时区。
3
3
  * @author nokecy
4
4
  */
5
5
  /**
6
6
  * 将时间格式化为 yyyy-MM-dd HH:mm:ss 格式
7
7
  * @param value 时间值(字符串、Date对象或null/undefined)
8
+ * @param precision 'second'(默认)带秒;'minute' 到分钟,列表默认用它(DESIGN.md §7.7:列表到分钟,日志与审计到秒)
8
9
  * @returns 格式化后的时间字符串,如果输入无效则返回空字符串
9
10
  */
10
- export declare const formatDateTime: (value: string | Date | null | undefined) => string;
11
+ export declare const formatDateTime: (value: string | Date | null | undefined, precision?: 'minute' | 'second') => string;
11
12
  /**
12
13
  * 将时间格式化为 yyyy-MM-dd 格式
13
14
  * @param value 时间值(字符串、Date对象或null/undefined)
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.formatDateTime = exports.formatDate = void 0;
7
7
  /**
8
- * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间 `YYYY-MM-DD HH:mm:ss`,按浏览器本地时区。
8
+ * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间默认 `YYYY-MM-DD HH:mm:ss`(列表传 'minute' 到分钟),按浏览器本地时区。
9
9
  * @author nokecy
10
10
  */
11
11
 
@@ -17,9 +17,11 @@ var parseDate = function parseDate(value) {
17
17
  /**
18
18
  * 将时间格式化为 yyyy-MM-dd HH:mm:ss 格式
19
19
  * @param value 时间值(字符串、Date对象或null/undefined)
20
+ * @param precision 'second'(默认)带秒;'minute' 到分钟,列表默认用它(DESIGN.md §7.7:列表到分钟,日志与审计到秒)
20
21
  * @returns 格式化后的时间字符串,如果输入无效则返回空字符串
21
22
  */
22
23
  var formatDateTime = exports.formatDateTime = function formatDateTime(value) {
24
+ var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'second';
23
25
  if (!value) return '';
24
26
  try {
25
27
  var date = parseDate(value);
@@ -30,7 +32,7 @@ var formatDateTime = exports.formatDateTime = function formatDateTime(value) {
30
32
  var hours = String(date.getHours()).padStart(2, '0');
31
33
  var minutes = String(date.getMinutes()).padStart(2, '0');
32
34
  var seconds = String(date.getSeconds()).padStart(2, '0');
33
- return "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes, ":").concat(seconds);
35
+ return precision === 'minute' ? "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes) : "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes, ":").concat(seconds);
34
36
  } catch (error) {
35
37
  return '';
36
38
  }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { GridPlusError } from '@nokecy/qc-ui-components/ag-grid-plus/errors/index';
3
+ import type { EmptyStateTexts } from '@nokecy/qc-ui-components/ag-grid-plus/utils/emptyState';
3
4
  /**
4
5
  * 列表空态四分支(U2)。
5
6
  *
@@ -7,7 +8,7 @@ import type { GridPlusError } from '@nokecy/qc-ui-components/ag-grid-plus/errors
7
8
  * 1. **无权限**(请求 403)→ 说明缺权限,不给新建入口;
8
9
  * 2. **加载失败** → 给「重新加载」按钮;
9
10
  * 3. **筛选无结果**(最近一次请求带条件)→ 引导调整/清空筛选;
10
- * 4. **无数据** → 「暂无数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
11
+ * 4. **无数据** → 「还没有数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
11
12
  *
12
13
  * 渲染方式:作为 AG-Grid 的 `noRowsOverlayComponent` 挂在标准列表基座上(见 ./StandardAgGridPlus.tsx)。
13
14
  * ag-grid-react 的 overlay 组件经 portal 渲染、仍在 React 树内,所以用 context 传动态状态,
@@ -26,6 +27,10 @@ export interface GridEmptyContextValue {
26
27
  clearFilterAction?: React.ReactNode;
27
28
  /** 重试(= 重新请求) */
28
29
  onRetry?: () => void;
30
+ /** 四分支文案覆盖(对应基座的 emptyState prop) */
31
+ texts?: EmptyStateTexts;
32
+ /** 对应基座的 overlayNoRowsTemplateText:只替换「无数据」「无结果」两支的文案 */
33
+ overrideText?: string;
29
34
  }
30
35
  export declare const GridEmptyContext: React.Context<GridEmptyContextValue>;
31
36
  /**
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isPermissionDenied = exports.hasActiveFilter = exports.GridEmptyState = exports.GridEmptyContext = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _antd = require("antd");
9
+ var _EmptyIllustration = _interopRequireDefault(require("@nokecy/qc-ui-components/ag-grid-plus/shared/EmptyIllustration"));
10
+ var _emptyState = require("@nokecy/qc-ui-components/ag-grid-plus/utils/emptyState");
9
11
  var _jsxRuntime = require("react/jsx-runtime");
10
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
13
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } /**
@@ -15,7 +17,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
15
17
  * 1. **无权限**(请求 403)→ 说明缺权限,不给新建入口;
16
18
  * 2. **加载失败** → 给「重新加载」按钮;
17
19
  * 3. **筛选无结果**(最近一次请求带条件)→ 引导调整/清空筛选;
18
- * 4. **无数据** → 「暂无数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
20
+ * 4. **无数据** → 「还没有数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
19
21
  *
20
22
  * 渲染方式:作为 AG-Grid 的 `noRowsOverlayComponent` 挂在标准列表基座上(见 ./StandardAgGridPlus.tsx)。
21
23
  * ag-grid-react 的 overlay 组件经 portal 渲染、仍在 React 树内,所以用 context 传动态状态,
@@ -41,37 +43,56 @@ var isPermissionDenied = exports.isPermissionDenied = function isPermissionDenie
41
43
  return status === 403 && (!code || code.startsWith('Volo.Authorization'));
42
44
  };
43
45
  var GridEmptyState = exports.GridEmptyState = function GridEmptyState() {
46
+ var _texts$noData;
44
47
  var _React$useContext = _react.default.useContext(GridEmptyContext),
45
48
  error = _React$useContext.error,
46
49
  hasFilter = _React$useContext.hasFilter,
47
50
  actions = _React$useContext.actions,
48
51
  clearFilterAction = _React$useContext.clearFilterAction,
49
- onRetry = _React$useContext.onRetry;
52
+ onRetry = _React$useContext.onRetry,
53
+ texts = _React$useContext.texts,
54
+ overrideText = _React$useContext.overrideText;
50
55
  var remoteError = error === null || error === void 0 ? void 0 : error.getRemoteServiceError();
56
+ // 插画随分支变化,统一 1.5px 描边(DESIGN.md §10)
57
+ var image = function image(kind) {
58
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyIllustration.default, {
59
+ kind: kind
60
+ });
61
+ };
62
+ var imageStyles = {
63
+ image: {
64
+ height: 64
65
+ }
66
+ };
51
67
 
52
68
  // 组织上下文校验失败不是列表权限配置错误,应提示用户重新选择组织。
53
69
  if ((remoteError === null || remoteError === void 0 ? void 0 : remoteError.code) === 'FactoryManagement:OrganizationNotAvailable') {
54
70
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Empty, {
55
- image: _antd.Empty.PRESENTED_IMAGE_SIMPLE,
71
+ image: image('error'),
72
+ styles: imageStyles,
56
73
  description: remoteError.message || '所选组织不可用或未获得访问权限,请重新选择。'
57
74
  });
58
75
  }
59
76
 
60
- // 分支 1:无权限(403 且不是业务异常)——说明原因,不给任何入口
77
+ // 分支:无权限(403 且不是业务异常)——说明原因,不给任何入口
61
78
  if (error && isPermissionDenied(httpStatusOf(error), remoteError === null || remoteError === void 0 ? void 0 : remoteError.code)) {
79
+ var _texts$noPermission;
62
80
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Empty, {
63
- image: _antd.Empty.PRESENTED_IMAGE_SIMPLE,
64
- description: "\u6CA1\u6709\u6743\u9650\u67E5\u770B\u6B64\u5217\u8868\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5F00\u901A"
81
+ image: image('noPermission'),
82
+ styles: imageStyles,
83
+ description: (_texts$noPermission = texts === null || texts === void 0 ? void 0 : texts.noPermission) !== null && _texts$noPermission !== void 0 ? _texts$noPermission : _emptyState.DEFAULT_EMPTY_TEXTS.noPermission
65
84
  });
66
85
  }
67
86
 
68
- // 分支 2:加载失败——给重试
87
+ // 分支:加载失败——给重试
69
88
  if (error) {
89
+ var _texts$error;
70
90
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Empty, {
71
- image: _antd.Empty.PRESENTED_IMAGE_SIMPLE
72
- // 后端给了业务原因(如数据未维护)时直接显示原因,告诉用户下一步。@author nokecy
91
+ image: image('error'),
92
+ styles: imageStyles
93
+ // 后端给了原因就写「加载失败,原因:…」,告诉用户下一步;页面自定义文案优先。@author nokecy
73
94
  ,
74
- description: remoteError !== null && remoteError !== void 0 && remoteError.code && remoteError.message ? remoteError.message : '加载失败,请检查后重试',
95
+ description: (_texts$error = texts === null || texts === void 0 ? void 0 : texts.error) !== null && _texts$error !== void 0 ? _texts$error : remoteError !== null && remoteError !== void 0 && remoteError.message ? "\u52A0\u8F7D\u5931\u8D25\uFF0C\u539F\u56E0\uFF1A".concat(remoteError.message) : '加载失败,请检查后重试',
75
96
  children: onRetry && /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Button, {
76
97
  size: "small",
77
98
  type: "primary",
@@ -81,19 +102,23 @@ var GridEmptyState = exports.GridEmptyState = function GridEmptyState() {
81
102
  });
82
103
  }
83
104
 
84
- // 分支 3:筛选无结果——引导调整条件,并可提供一键清空入口
105
+ // 分支:筛选无结果——引导调整条件,并可提供一键清空入口
85
106
  if (hasFilter) {
107
+ var _texts$noResult;
86
108
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Empty, {
87
- image: _antd.Empty.PRESENTED_IMAGE_SIMPLE,
88
- description: "\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u6570\u636E",
109
+ image: image('noResult'),
110
+ styles: imageStyles,
111
+ description: overrideText || ((_texts$noResult = texts === null || texts === void 0 ? void 0 : texts.noResult) !== null && _texts$noResult !== void 0 ? _texts$noResult : _emptyState.DEFAULT_EMPTY_TEXTS.noResult),
89
112
  children: clearFilterAction
90
113
  });
91
114
  }
92
115
 
93
- // 分支 4:无数据——业务页可注入新建入口
116
+ // 分支:无数据——业务页可注入新建入口。
117
+ // overrideText(overlayNoRowsTemplateText)只作用于这两支「空」:失败与无权限不能被一句业务文案盖掉。
94
118
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Empty, {
95
- image: _antd.Empty.PRESENTED_IMAGE_SIMPLE,
96
- description: "\u6682\u65E0\u6570\u636E",
119
+ image: image('noData'),
120
+ styles: imageStyles,
121
+ description: overrideText || ((_texts$noData = texts === null || texts === void 0 ? void 0 : texts.noData) !== null && _texts$noData !== void 0 ? _texts$noData : _emptyState.DEFAULT_EMPTY_TEXTS.noData),
97
122
  children: actions
98
123
  });
99
124
  };
@@ -9,6 +9,7 @@ type GridEnumItem = {
9
9
  color?: string;
10
10
  label?: string;
11
11
  value?: unknown;
12
+ status?: string;
12
13
  };
13
14
  type GridColumnLike = {
14
15
  field?: string;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.createNormalizedEnumFallbackRenderer = exports.applyNormalizedEnumFallbacksToColumns = exports.applyGridValueEnumToColumns = void 0;
7
7
  var _react = require("react");
8
8
  var _valueEnumColor = require("@nokecy/qc-ui-components/ag-grid-plus/utils/valueEnumColor");
9
+ var _statusPill = require("@nokecy/qc-ui-components/ag-grid-plus/utils/statusPill");
9
10
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
10
11
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
12
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -58,12 +59,15 @@ var createNormalizedEnumFallbackRenderer = exports.createNormalizedEnumFallbackR
58
59
  return item.value !== params.value && normalizeEnumCode(item.value) === normalizedValue;
59
60
  });
60
61
  if (matched) {
61
- var _matched$label;
62
+ var _matched$label, _matched$label2;
63
+ if ((0, _statusPill.isStatusKey)(matched.status)) return /*#__PURE__*/(0, _react.createElement)(_statusPill.StatusPill, {
64
+ status: matched.status
65
+ }, (_matched$label = matched.label) !== null && _matched$label !== void 0 ? _matched$label : '');
62
66
  return /*#__PURE__*/(0, _react.createElement)('span', {
63
67
  style: {
64
68
  color: matched.color || 'inherit'
65
69
  }
66
- }, (_matched$label = matched.label) !== null && _matched$label !== void 0 ? _matched$label : '');
70
+ }, (_matched$label2 = matched.label) !== null && _matched$label2 !== void 0 ? _matched$label2 : '');
67
71
  }
68
72
  }
69
73
  return fallback ? fallback(params) : params.value;
@@ -11,6 +11,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
11
11
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
12
12
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
13
13
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
14
+ var EMPTY_DATE = '—';
14
15
  /** 从日期类型、字段及标题识别日历日期与操作时间,排除耗时和工时。@author nokecy */
15
16
  var getListDateType = exports.getListDateType = function getListDateType(column) {
16
17
  var _column$field, _column$headerName;
@@ -34,13 +35,15 @@ var getListDateType = exports.getListDateType = function getListDateType(column)
34
35
 
35
36
  /** 列表只格式化展示值,保留数据源中的日期供排序、筛选及提交使用。@author nokecy */
36
37
  var normalizeListDateColumn = exports.normalizeListDateColumn = function normalizeListDateColumn(column) {
37
- var _column$type, _column$cellRenderer;
38
+ var _column$valueFormatte, _column$type, _column$cellRenderer;
38
39
  var dateType = getListDateType(column);
39
40
  if (!dateType) return column;
40
- var formatter = function formatter(_ref) {
41
+ // 列表日期到分钟、空值显示「—」(DESIGN.md §7.7);页面自己传 valueFormatter(如审计列要秒)即覆盖
42
+ var defaultFormatter = function defaultFormatter(_ref) {
41
43
  var value = _ref.value;
42
- return dateType === 'dateTimeColumn' ? (0, _dateFormat.formatDateTime)(value) : (0, _dateFormat.formatDate)(value);
44
+ return (dateType === 'dateTimeColumn' ? (0, _dateFormat.formatDateTime)(value, 'minute') : (0, _dateFormat.formatDate)(value)) || EMPTY_DATE;
43
45
  };
46
+ var formatter = (_column$valueFormatte = column.valueFormatter) !== null && _column$valueFormatte !== void 0 ? _column$valueFormatte : defaultFormatter;
44
47
  return _objectSpread(_objectSpread({}, column), {}, {
45
48
  type: (_column$type = column.type) !== null && _column$type !== void 0 ? _column$type : dateType,
46
49
  valueFormatter: formatter,
@@ -18,11 +18,12 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
18
18
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
19
19
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
20
20
  import React, { useCallback, useMemo, useRef, useEffect } from 'react';
21
- import { FormDialog, FormLayout, FormItem, FormGrid, Input, Select, DatePicker, NumberPicker, Switch } from '@nokecy/formily-antd';
21
+ import { FormDialog, FormLayout, FormItem, FormGrid, Input, Select, DatePicker, NumberPicker, Switch, focusFirstError } from '@nokecy/formily-antd';
22
22
  import { onFormInit, onFormValidateFailed, onFormSubmitEnd } from '@nokecy/formily-core';
23
23
  import { Button, ConfigProvider, message, Spin } from 'antd';
24
24
  import portalManager from "./PortalManager";
25
25
  import { createSchemaField, Observer } from '@nokecy/formily-react';
26
+ import DraggableModal from '@nokecy/qc-ui-components/draggableModal/index';
26
27
 
27
28
  // 创建默认的 SchemaField,包含基本组件和装饰器
28
29
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -40,6 +41,13 @@ var SchemaFieldComponents = createSchemaField({
40
41
  }
41
42
  });
42
43
 
44
+ /** 表单弹窗的可缩放壳:最小宽度取规范最小一档 560,避免缩到字段挤压。 */
45
+ var ResizableFormModal = function ResizableFormModal(modalProps) {
46
+ return /*#__PURE__*/_jsx(DraggableModal, _objectSpread({
47
+ minWidth: 560
48
+ }, modalProps));
49
+ };
50
+
43
51
  /**
44
52
  * 默认的 useFormSchema hook - 直接返回schema配置
45
53
  */
@@ -77,7 +85,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
77
85
  directFormSchema = props.formSchema,
78
86
  apiConfig = props.apiConfig,
79
87
  _props$width = props.width,
80
- width = _props$width === void 0 ? 800 : _props$width,
88
+ width = _props$width === void 0 ? 720 : _props$width,
81
89
  entityId = props.entityId,
82
90
  _props$title = props.title,
83
91
  title = _props$title === void 0 ? '表单' : _props$title,
@@ -93,6 +101,12 @@ var StandardFormDialog = function StandardFormDialog(props) {
93
101
  customSubmitHandler = props.customSubmitHandler,
94
102
  _props$useUnifiedErro = props.useUnifiedErrorHandling,
95
103
  useUnifiedErrorHandling = _props$useUnifiedErro === void 0 ? true : _props$useUnifiedErro,
104
+ _props$locateFirstErr = props.locateFirstError,
105
+ locateFirstError = _props$locateFirstErr === void 0 ? true : _props$locateFirstErr,
106
+ _props$confirmOnDirty = props.confirmOnDirtyClose,
107
+ confirmOnDirtyClose = _props$confirmOnDirty === void 0 ? true : _props$confirmOnDirty,
108
+ _props$resizable = props.resizable,
109
+ resizable = _props$resizable === void 0 ? true : _props$resizable,
96
110
  _props$useFormSchema = props.useFormSchema,
97
111
  useFormSchemaHook = _props$useFormSchema === void 0 ? defaultUseFormSchema : _props$useFormSchema,
98
112
  _props$useSchemaField = props.useSchemaField,
@@ -239,6 +253,18 @@ var StandardFormDialog = function StandardFormDialog(props) {
239
253
 
240
254
  // 表单验证失败回调
241
255
  var handleValidationFailed = useCallback(function (form) {
256
+ if (locateFirstError) {
257
+ // 提示里直接写出所在页签与字段,不再拼字段名串(DESIGN.md §6.4)。
258
+ // 只在最上层弹窗内找,避免定位到弹窗下面页面里的字段。
259
+ void focusFirstError(form, {
260
+ root: function root() {
261
+ var _modals;
262
+ var modals = document.querySelectorAll('.ant-modal');
263
+ return (_modals = modals[modals.length - 1]) !== null && _modals !== void 0 ? _modals : document;
264
+ }
265
+ });
266
+ return;
267
+ }
242
268
  var errors = form.errors;
243
269
  var errorFields = Object.keys(errors);
244
270
  if (errorFields.length > 0) {
@@ -270,7 +296,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
270
296
  errors: errors
271
297
  });
272
298
  }
273
- }, []);
299
+ }, [locateFirstError]);
274
300
 
275
301
  // 表单属性配置
276
302
  var formProps = useMemo(function () {
@@ -411,6 +437,8 @@ var StandardFormDialog = function StandardFormDialog(props) {
411
437
  // 不设置静态 loading,使用 FormDialog 自带的 form.submitting。
412
438
  // @author nokecy
413
439
  maskClosable: false,
440
+ confirmOnDirtyClose: confirmOnDirtyClose,
441
+ modalComponent: resizable ? ResizableFormModal : undefined,
414
442
  onOk: function onOk() {
415
443
  if (confirmingRef.current || loadingRef.current) return false;
416
444
  confirmingRef.current = true;
@@ -452,7 +480,7 @@ var StandardFormDialog = function StandardFormDialog(props) {
452
480
  });
453
481
  });
454
482
  formDialog.forConfirm(handleSubmit).open(formProps);
455
- }, [title, width, portalId, schema, SchemaField, formProps, handleSubmit]);
483
+ }, [title, width, portalId, schema, SchemaField, formProps, handleSubmit, confirmOnDirtyClose, resizable]);
456
484
  return /*#__PURE__*/_jsx(FormDialog.Portal, {
457
485
  id: portalId,
458
486
  children: /*#__PURE__*/_jsx(Button, _objectSpread(_objectSpread({
@@ -44,8 +44,23 @@ export interface StandardFormDialogConfig {
44
44
  schemaConfig: FormSchemaConfig;
45
45
  /** API配置 */
46
46
  apiConfig: FormApiConfig;
47
- /** 对话框宽度 */
47
+ /** 对话框宽度,默认 720;规范只取 560 / 720 / 960 三档。 */
48
48
  width?: number;
49
+ /**
50
+ * 校验失败时定位首个错误字段(切页签、展开折叠、滚动并聚焦)并给出带位置的提示,默认 true。
51
+ * 传 false 回到旧行为:只弹出「请检查表单错误:字段名…」的汇总提示。
52
+ */
53
+ locateFirstError?: boolean;
54
+ /**
55
+ * 表单被改过时,关闭(叉、Esc、取消按钮)先弹「继续编辑 / 放弃修改」确认,默认 true(DESIGN.md §6.6)。
56
+ * 判据为 form.modified;提交成功后的关闭不确认。传 false 恢复直接关闭。
57
+ */
58
+ confirmOnDirtyClose?: boolean;
59
+ /**
60
+ * 弹窗可拖动标题移动、拖边框缩放,默认 true(表单字段多时需要放大;宽度默认仍按 width,缩放不持久化)。
61
+ * 最小 560 x 300,且不超过视口 95%。传 false 回到固定尺寸。
62
+ */
63
+ resizable?: boolean;
49
64
  /** 实体ID(编辑时) */
50
65
  entityId?: string | number;
51
66
  /** 标题 */
@@ -561,9 +561,12 @@ var StandardAgGridPlus = function StandardAgGridPlus(props) {
561
561
  hasFilter: hasFilter || !!filterActive,
562
562
  actions: emptyActions,
563
563
  clearFilterAction: clearFilterAction,
564
- onRetry: onRetry
564
+ onRetry: onRetry,
565
+ // 文案可定制:与基座同名 prop 同一语义(§7.8「『包材』下暂无物料」)
566
+ overrideText: props.overlayNoRowsTemplateText,
567
+ texts: props.emptyState
565
568
  };
566
- }, [lastError, hasFilter, filterActive, emptyActions, clearFilterAction, onRetry]);
569
+ }, [lastError, hasFilter, filterActive, emptyActions, clearFilterAction, onRetry, props.overlayNoRowsTemplateText, props.emptyState]);
567
570
  var onGridReady = useCallback(function (event) {
568
571
  var _restProps$onGridRead;
569
572
  var api = event.api;
@@ -1,13 +1,14 @@
1
1
  /**
2
- * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间 `YYYY-MM-DD HH:mm:ss`,按浏览器本地时区。
2
+ * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间默认 `YYYY-MM-DD HH:mm:ss`(列表传 'minute' 到分钟),按浏览器本地时区。
3
3
  * @author nokecy
4
4
  */
5
5
  /**
6
6
  * 将时间格式化为 yyyy-MM-dd HH:mm:ss 格式
7
7
  * @param value 时间值(字符串、Date对象或null/undefined)
8
+ * @param precision 'second'(默认)带秒;'minute' 到分钟,列表默认用它(DESIGN.md §7.7:列表到分钟,日志与审计到秒)
8
9
  * @returns 格式化后的时间字符串,如果输入无效则返回空字符串
9
10
  */
10
- export declare const formatDateTime: (value: string | Date | null | undefined) => string;
11
+ export declare const formatDateTime: (value: string | Date | null | undefined, precision?: 'minute' | 'second') => string;
11
12
  /**
12
13
  * 将时间格式化为 yyyy-MM-dd 格式
13
14
  * @param value 时间值(字符串、Date对象或null/undefined)
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间 `YYYY-MM-DD HH:mm:ss`,按浏览器本地时区。
2
+ * 列表日期显示格式:日期 `YYYY-MM-DD`,日期时间默认 `YYYY-MM-DD HH:mm:ss`(列表传 'minute' 到分钟),按浏览器本地时区。
3
3
  * @author nokecy
4
4
  */
5
5
 
@@ -11,9 +11,11 @@ var parseDate = function parseDate(value) {
11
11
  /**
12
12
  * 将时间格式化为 yyyy-MM-dd HH:mm:ss 格式
13
13
  * @param value 时间值(字符串、Date对象或null/undefined)
14
+ * @param precision 'second'(默认)带秒;'minute' 到分钟,列表默认用它(DESIGN.md §7.7:列表到分钟,日志与审计到秒)
14
15
  * @returns 格式化后的时间字符串,如果输入无效则返回空字符串
15
16
  */
16
17
  export var formatDateTime = function formatDateTime(value) {
18
+ var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'second';
17
19
  if (!value) return '';
18
20
  try {
19
21
  var date = parseDate(value);
@@ -24,7 +26,7 @@ export var formatDateTime = function formatDateTime(value) {
24
26
  var hours = String(date.getHours()).padStart(2, '0');
25
27
  var minutes = String(date.getMinutes()).padStart(2, '0');
26
28
  var seconds = String(date.getSeconds()).padStart(2, '0');
27
- return "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes, ":").concat(seconds);
29
+ return precision === 'minute' ? "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes) : "".concat(year, "-").concat(month, "-").concat(day, " ").concat(hours, ":").concat(minutes, ":").concat(seconds);
28
30
  } catch (error) {
29
31
  return '';
30
32
  }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { GridPlusError } from '@nokecy/qc-ui-components/ag-grid-plus/errors/index';
3
+ import type { EmptyStateTexts } from '@nokecy/qc-ui-components/ag-grid-plus/utils/emptyState';
3
4
  /**
4
5
  * 列表空态四分支(U2)。
5
6
  *
@@ -7,7 +8,7 @@ import type { GridPlusError } from '@nokecy/qc-ui-components/ag-grid-plus/errors
7
8
  * 1. **无权限**(请求 403)→ 说明缺权限,不给新建入口;
8
9
  * 2. **加载失败** → 给「重新加载」按钮;
9
10
  * 3. **筛选无结果**(最近一次请求带条件)→ 引导调整/清空筛选;
10
- * 4. **无数据** → 「暂无数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
11
+ * 4. **无数据** → 「还没有数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
11
12
  *
12
13
  * 渲染方式:作为 AG-Grid 的 `noRowsOverlayComponent` 挂在标准列表基座上(见 ./StandardAgGridPlus.tsx)。
13
14
  * ag-grid-react 的 overlay 组件经 portal 渲染、仍在 React 树内,所以用 context 传动态状态,
@@ -26,6 +27,10 @@ export interface GridEmptyContextValue {
26
27
  clearFilterAction?: React.ReactNode;
27
28
  /** 重试(= 重新请求) */
28
29
  onRetry?: () => void;
30
+ /** 四分支文案覆盖(对应基座的 emptyState prop) */
31
+ texts?: EmptyStateTexts;
32
+ /** 对应基座的 overlayNoRowsTemplateText:只替换「无数据」「无结果」两支的文案 */
33
+ overrideText?: string;
29
34
  }
30
35
  export declare const GridEmptyContext: React.Context<GridEmptyContextValue>;
31
36
  /**
@@ -1,6 +1,8 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
2
  import React from 'react';
3
3
  import { Button, Empty } from 'antd';
4
+ import EmptyIllustration from '@nokecy/qc-ui-components/ag-grid-plus/shared/EmptyIllustration';
5
+ import { DEFAULT_EMPTY_TEXTS } from '@nokecy/qc-ui-components/ag-grid-plus/utils/emptyState';
4
6
 
5
7
  /**
6
8
  * 列表空态四分支(U2)。
@@ -9,7 +11,7 @@ import { Button, Empty } from 'antd';
9
11
  * 1. **无权限**(请求 403)→ 说明缺权限,不给新建入口;
10
12
  * 2. **加载失败** → 给「重新加载」按钮;
11
13
  * 3. **筛选无结果**(最近一次请求带条件)→ 引导调整/清空筛选;
12
- * 4. **无数据** → 「暂无数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
14
+ * 4. **无数据** → 「还没有数据」+ 业务页注入的操作(通常是 Access 包裹的新建按钮)。
13
15
  *
14
16
  * 渲染方式:作为 AG-Grid 的 `noRowsOverlayComponent` 挂在标准列表基座上(见 ./StandardAgGridPlus.tsx)。
15
17
  * ag-grid-react 的 overlay 组件经 portal 渲染、仍在 React 树内,所以用 context 传动态状态,
@@ -36,37 +38,56 @@ export var isPermissionDenied = function isPermissionDenied(status, code) {
36
38
  return status === 403 && (!code || code.startsWith('Volo.Authorization'));
37
39
  };
38
40
  export var GridEmptyState = function GridEmptyState() {
41
+ var _texts$noData;
39
42
  var _React$useContext = React.useContext(GridEmptyContext),
40
43
  error = _React$useContext.error,
41
44
  hasFilter = _React$useContext.hasFilter,
42
45
  actions = _React$useContext.actions,
43
46
  clearFilterAction = _React$useContext.clearFilterAction,
44
- onRetry = _React$useContext.onRetry;
47
+ onRetry = _React$useContext.onRetry,
48
+ texts = _React$useContext.texts,
49
+ overrideText = _React$useContext.overrideText;
45
50
  var remoteError = error === null || error === void 0 ? void 0 : error.getRemoteServiceError();
51
+ // 插画随分支变化,统一 1.5px 描边(DESIGN.md §10)
52
+ var image = function image(kind) {
53
+ return /*#__PURE__*/_jsx(EmptyIllustration, {
54
+ kind: kind
55
+ });
56
+ };
57
+ var imageStyles = {
58
+ image: {
59
+ height: 64
60
+ }
61
+ };
46
62
 
47
63
  // 组织上下文校验失败不是列表权限配置错误,应提示用户重新选择组织。
48
64
  if ((remoteError === null || remoteError === void 0 ? void 0 : remoteError.code) === 'FactoryManagement:OrganizationNotAvailable') {
49
65
  return /*#__PURE__*/_jsx(Empty, {
50
- image: Empty.PRESENTED_IMAGE_SIMPLE,
66
+ image: image('error'),
67
+ styles: imageStyles,
51
68
  description: remoteError.message || '所选组织不可用或未获得访问权限,请重新选择。'
52
69
  });
53
70
  }
54
71
 
55
- // 分支 1:无权限(403 且不是业务异常)——说明原因,不给任何入口
72
+ // 分支:无权限(403 且不是业务异常)——说明原因,不给任何入口
56
73
  if (error && isPermissionDenied(httpStatusOf(error), remoteError === null || remoteError === void 0 ? void 0 : remoteError.code)) {
74
+ var _texts$noPermission;
57
75
  return /*#__PURE__*/_jsx(Empty, {
58
- image: Empty.PRESENTED_IMAGE_SIMPLE,
59
- description: "\u6CA1\u6709\u6743\u9650\u67E5\u770B\u6B64\u5217\u8868\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5F00\u901A"
76
+ image: image('noPermission'),
77
+ styles: imageStyles,
78
+ description: (_texts$noPermission = texts === null || texts === void 0 ? void 0 : texts.noPermission) !== null && _texts$noPermission !== void 0 ? _texts$noPermission : DEFAULT_EMPTY_TEXTS.noPermission
60
79
  });
61
80
  }
62
81
 
63
- // 分支 2:加载失败——给重试
82
+ // 分支:加载失败——给重试
64
83
  if (error) {
84
+ var _texts$error;
65
85
  return /*#__PURE__*/_jsx(Empty, {
66
- image: Empty.PRESENTED_IMAGE_SIMPLE
67
- // 后端给了业务原因(如数据未维护)时直接显示原因,告诉用户下一步。@author nokecy
86
+ image: image('error'),
87
+ styles: imageStyles
88
+ // 后端给了原因就写「加载失败,原因:…」,告诉用户下一步;页面自定义文案优先。@author nokecy
68
89
  ,
69
- description: remoteError !== null && remoteError !== void 0 && remoteError.code && remoteError.message ? remoteError.message : '加载失败,请检查后重试',
90
+ description: (_texts$error = texts === null || texts === void 0 ? void 0 : texts.error) !== null && _texts$error !== void 0 ? _texts$error : remoteError !== null && remoteError !== void 0 && remoteError.message ? "\u52A0\u8F7D\u5931\u8D25\uFF0C\u539F\u56E0\uFF1A".concat(remoteError.message) : '加载失败,请检查后重试',
70
91
  children: onRetry && /*#__PURE__*/_jsx(Button, {
71
92
  size: "small",
72
93
  type: "primary",
@@ -76,19 +97,23 @@ export var GridEmptyState = function GridEmptyState() {
76
97
  });
77
98
  }
78
99
 
79
- // 分支 3:筛选无结果——引导调整条件,并可提供一键清空入口
100
+ // 分支:筛选无结果——引导调整条件,并可提供一键清空入口
80
101
  if (hasFilter) {
102
+ var _texts$noResult;
81
103
  return /*#__PURE__*/_jsx(Empty, {
82
- image: Empty.PRESENTED_IMAGE_SIMPLE,
83
- description: "\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u6570\u636E",
104
+ image: image('noResult'),
105
+ styles: imageStyles,
106
+ description: overrideText || ((_texts$noResult = texts === null || texts === void 0 ? void 0 : texts.noResult) !== null && _texts$noResult !== void 0 ? _texts$noResult : DEFAULT_EMPTY_TEXTS.noResult),
84
107
  children: clearFilterAction
85
108
  });
86
109
  }
87
110
 
88
- // 分支 4:无数据——业务页可注入新建入口
111
+ // 分支:无数据——业务页可注入新建入口。
112
+ // overrideText(overlayNoRowsTemplateText)只作用于这两支「空」:失败与无权限不能被一句业务文案盖掉。
89
113
  return /*#__PURE__*/_jsx(Empty, {
90
- image: Empty.PRESENTED_IMAGE_SIMPLE,
91
- description: "\u6682\u65E0\u6570\u636E",
114
+ image: image('noData'),
115
+ styles: imageStyles,
116
+ description: overrideText || ((_texts$noData = texts === null || texts === void 0 ? void 0 : texts.noData) !== null && _texts$noData !== void 0 ? _texts$noData : DEFAULT_EMPTY_TEXTS.noData),
92
117
  children: actions
93
118
  });
94
119
  };
@@ -9,6 +9,7 @@ type GridEnumItem = {
9
9
  color?: string;
10
10
  label?: string;
11
11
  value?: unknown;
12
+ status?: string;
12
13
  };
13
14
  type GridColumnLike = {
14
15
  field?: string;
@@ -14,6 +14,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
14
14
  */
15
15
  import { createElement } from 'react';
16
16
  import { gridValueEnum } from '@nokecy/qc-ui-components/ag-grid-plus/utils/valueEnumColor';
17
+ import { isStatusKey, StatusPill } from '@nokecy/qc-ui-components/ag-grid-plus/utils/statusPill';
17
18
  /**
18
19
  * 递归给 columnDefs / 列组 children 的 valueEnum 套上 `gridValueEnum`,并补默认未知值显示。
19
20
  * 没有 valueEnum 且没有 children 的列保持原引用。
@@ -53,12 +54,15 @@ export var createNormalizedEnumFallbackRenderer = function createNormalizedEnumF
53
54
  return item.value !== params.value && normalizeEnumCode(item.value) === normalizedValue;
54
55
  });
55
56
  if (matched) {
56
- var _matched$label;
57
+ var _matched$label, _matched$label2;
58
+ if (isStatusKey(matched.status)) return /*#__PURE__*/createElement(StatusPill, {
59
+ status: matched.status
60
+ }, (_matched$label = matched.label) !== null && _matched$label !== void 0 ? _matched$label : '');
57
61
  return /*#__PURE__*/createElement('span', {
58
62
  style: {
59
63
  color: matched.color || 'inherit'
60
64
  }
61
- }, (_matched$label = matched.label) !== null && _matched$label !== void 0 ? _matched$label : '');
65
+ }, (_matched$label2 = matched.label) !== null && _matched$label2 !== void 0 ? _matched$label2 : '');
62
66
  }
63
67
  }
64
68
  return fallback ? fallback(params) : params.value;
@@ -5,6 +5,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
7
  import { formatDate, formatDateTime } from "./dateFormat";
8
+ var EMPTY_DATE = '—';
8
9
  /** 从日期类型、字段及标题识别日历日期与操作时间,排除耗时和工时。@author nokecy */
9
10
  export var getListDateType = function getListDateType(column) {
10
11
  var _column$field, _column$headerName;
@@ -28,13 +29,15 @@ export var getListDateType = function getListDateType(column) {
28
29
 
29
30
  /** 列表只格式化展示值,保留数据源中的日期供排序、筛选及提交使用。@author nokecy */
30
31
  export var normalizeListDateColumn = function normalizeListDateColumn(column) {
31
- var _column$type, _column$cellRenderer;
32
+ var _column$valueFormatte, _column$type, _column$cellRenderer;
32
33
  var dateType = getListDateType(column);
33
34
  if (!dateType) return column;
34
- var formatter = function formatter(_ref) {
35
+ // 列表日期到分钟、空值显示「—」(DESIGN.md §7.7);页面自己传 valueFormatter(如审计列要秒)即覆盖
36
+ var defaultFormatter = function defaultFormatter(_ref) {
35
37
  var value = _ref.value;
36
- return dateType === 'dateTimeColumn' ? formatDateTime(value) : formatDate(value);
38
+ return (dateType === 'dateTimeColumn' ? formatDateTime(value, 'minute') : formatDate(value)) || EMPTY_DATE;
37
39
  };
40
+ var formatter = (_column$valueFormatte = column.valueFormatter) !== null && _column$valueFormatte !== void 0 ? _column$valueFormatte : defaultFormatter;
38
41
  return _objectSpread(_objectSpread({}, column), {}, {
39
42
  type: (_column$type = column.type) !== null && _column$type !== void 0 ? _column$type : dateType,
40
43
  valueFormatter: formatter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nokecy/qc-ui-business",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "QC_UI business components and ABP adapters",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -45,10 +45,10 @@
45
45
  "typecheck": "tsc --noEmit -p tsconfig.json"
46
46
  },
47
47
  "dependencies": {
48
- "@nokecy/formily-antd": "1.2.4",
48
+ "@nokecy/formily-antd": "1.2.5",
49
49
  "@nokecy/formily-core": "2.3.7",
50
50
  "@nokecy/formily-react": "2.3.7",
51
- "@nokecy/qc-ui-components": "2.0.0-beta.0",
51
+ "@nokecy/qc-ui-components": "2.0.0-beta.1",
52
52
  "ahooks": "3.10.0"
53
53
  },
54
54
  "peerDependencies": {