UNPKG

ze-react-component-library

Version:
885 lines (795 loc) 23.9 kB
import "antd/es/space/style"; import _Space from "antd/es/space"; import "antd/es/drawer/style"; import _Drawer from "antd/es/drawer"; import "antd/es/message/style"; import _message from "antd/es/message"; import "antd/es/popconfirm/style"; import _Popconfirm from "antd/es/popconfirm"; import "antd/es/button/style"; import _Button from "antd/es/button"; var __assign = this && this.__assign || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } } return t; }; return __assign.apply(this, arguments); }; var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = this && this.__generator || function (thisArg, body) { var _ = { label: 0, sent: function sent() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) { try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = this && this.__spreadArray || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) { to[j] = from[i]; } return to; }; import React, { useState, useContext, useRef } from "react"; import { useRequest } from "@umijs/hooks"; import _ from "underscore"; import flatten from "flat"; import ProProvider from "@ant-design/pro-provider"; import { EditableProTable } from "@ant-design/pro-table"; import { BetaSchemaForm } from "@ant-design/pro-form"; import { getSchemas } from "zeroetp-api-sdk"; import TsEditor from "../components/TsEditor"; import JsonEditor from "./JsonEditor"; import { customValueTypes, typePropertyOfSchema, formatWithProperty } from "../util"; import { getMeasurements, postMeasurements, deleteMeasurementsByName } from "./apis"; var tsCodeRenderer = { render: function render(v, props) { return (props === null || props === void 0 ? void 0 : props.value) ? /*#__PURE__*/React.createElement(TsEditor, __assign({}, props, { readOnly: true, height: "100px", width: "100%" })) : "-"; }, renderFormItem: function renderFormItem(props) { return /*#__PURE__*/React.createElement(TsEditor, __assign({}, props === null || props === void 0 ? void 0 : props.fieldProps, { height: "100px", width: "100%" })); } }; var optionsOfTypeColumn = __spreadArray(__spreadArray([], typePropertyOfSchema.constraints.enum), ["report"]).map(function (d) { return { label: typePropertyOfSchema.constraints.enumText[d] || d, value: d }; }); var MeasurementEditor = function MeasurementEditor() { var _a = useState(false), drawerVisible = _a[0], setDrawerVisible = _a[1]; var _b = useState(), editingRecord = _b[0], setEditingRecord = _b[1]; var _c = useState(false), saveLoading = _c[0], setSaveLoading = _c[1]; var editorRef = useRef(); var values = useContext(ProProvider); // 用来自定义ValueType // EditableProTable var _d = useState([]), editableKeys = _d[0], setEditableRowKeys = _d[1]; var _e = useState({}), codeEditorType = _e[0], setCodeEditorType = _e[1]; var _f = useState(), codeEditorId = _f[0], setCodeEditorId = _f[1]; var _g = useState([]), data = _g[0], setData = _g[1]; var codeValuesRef = useRef({}); var formRef = useRef(); var _h = useRequest(getMeasurements, { formatResult: function formatResult(res) { var v = _.sortBy((res === null || res === void 0 ? void 0 : res.data) || [], "schema"); setData(v.map(function (d) { return flatten(d, { safe: true }); })); return v; } }), loading = _h.loading, originalData = _h.data, reloadData = _h.run; var _j = useRequest(getSchemas, { formatResult: function formatResult(res) { return (res === null || res === void 0 ? void 0 : res.schemas) || []; } }), _k = _j.data, schemas = _k === void 0 ? [] : _k, schemasLoading = _j.loading; var codeColumns = [{ dataIndex: "codeEditorType", title: "类型", valueEnum: { sql: { text: "sql" }, js: { text: "js" } }, hideInPayload: true }, { dataIndex: "run", title: "run函数", valueType: "code", hideInForm: codeEditorType[codeEditorId] !== "js", renderFormItem: tsCodeRenderer.renderFormItem }, { dataIndex: "shouldSplitGroupby", title: "shouldSplitGroupby函数", valueType: "code", hideInForm: codeEditorType[codeEditorId] !== "js", renderFormItem: tsCodeRenderer.renderFormItem }, { dataIndex: "sql", title: "sql", valueType: "code", hideInForm: codeEditorType[codeEditorId] !== "sql" }, { dataIndex: "sqlLeftJoinClause", title: "sqlLeftJoinClause", valueType: "code", hideInForm: codeEditorType[codeEditorId] !== "sql" }]; var getCodeType = function getCodeType(record) { var values = __assign(__assign({}, record), codeValuesRef.current[record._id]); var codeIsJs = values.run || values.shouldSplitGroupby; return codeIsJs ? "js" : "sql"; }; var onCodeCancel = function onCodeCancel(record) { var _a; codeValuesRef.current[record._id] = {}; var type = getCodeType(record); setCodeEditorType(function (p) { var _a; return __assign(__assign({}, p), (_a = {}, _a[record._id] = type, _a)); }); (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.setFieldsValue({ codeEditorType: type }); }; var columns = [{ title: "Schema", dataIndex: "schema", valueType: "select", fixed: "left", fieldProps: { dropdownMatchSelectWidth: false, options: schemas === null || schemas === void 0 ? void 0 : schemas.map(function (d) { return { label: d.name + "\uFF08" + d._id + "\uFF09", value: d._id }; }) }, formItemProps: { rules: [{ required: true, message: "必填项" }] }, width: 160 }, { title: "指标名", dataIndex: "name", valueType: "text", fixed: "left", width: 120 }, { title: "同义词", dataIndex: "syno", valueType: "tag", hideInSearch: true, width: 200 }, { title: "类型", dataIndex: "type", valueType: "select", hideInSearch: true, width: 120, fieldProps: { options: optionsOfTypeColumn }, formItemProps: { rules: [{ required: true, message: "必填项" }] } }, { title: "是否可加?", dataIndex: "is_additive", valueType: "radio", hideInSearch: true, width: 120, fieldProps: { options: [{ label: "是", value: true }, { label: "否", value: false }] } }, { title: "代码", hideInSearch: true, hideInPayload: true, width: 120, render: function render(item, record) { var codeIsJs = record.run || record.shouldSplitGroupby; return /*#__PURE__*/React.createElement(BetaSchemaForm, { layoutType: "ModalForm", title: "\u4EE3\u7801\u8BE6\u60C5", initialValues: record, trigger: /*#__PURE__*/React.createElement(_Button, { type: "link", style: { padding: 0 } }, "\u70B9\u51FB\u67E5\u770B"), modalProps: { width: "80%", centered: true }, columns: [{ dataIndex: "run", title: "run函数", valueType: "code", readonly: true, hideInDescriptions: !codeIsJs, render: tsCodeRenderer.render }, { dataIndex: "shouldSplitGroupby", title: "shouldSplitGroupby函数", valueType: "code", readonly: true, hideInDescriptions: !codeIsJs, render: tsCodeRenderer.render }, { dataIndex: "sql", title: "sql", valueType: "code", readonly: true, hideInDescriptions: codeIsJs, fieldProps: { style: { width: "100%", overflow: "auto" } } }, { dataIndex: "sqlLeftJoinClause", title: "sqlLeftJoinClause", valueType: "code", readonly: true, hideInDescriptions: codeIsJs, fieldProps: { style: { width: "100%", overflow: "auto" } } }].filter(function (d) { return !d.hideInDescriptions; }), submitter: false }); }, renderFormItem: function renderFormItem(item, _a) { var record = _a.record; var type = codeEditorType[record._id] || getCodeType(record); return /*#__PURE__*/React.createElement(BetaSchemaForm, { layoutType: "ModalForm", title: "\u4EE3\u7801\u7F16\u8F91", formRef: formRef, initialValues: __assign(__assign(__assign({}, record), codeValuesRef.current[record._id]), { codeEditorType: type }), trigger: /*#__PURE__*/React.createElement(_Button, { type: "link", style: { padding: 0 }, onClick: function onClick() { setCodeEditorId(record._id); setCodeEditorType(function (p) { var _a; return __assign(__assign({}, p), (_a = {}, _a[record._id] = type, _a)); }); } }, "\u70B9\u51FB\u4FEE\u6539"), columns: codeColumns.map(function (d) { if (d.dataIndex === "codeEditorType") { return __assign(__assign({}, d), { fieldProps: { onChange: function onChange(v) { var _a; var values = ((_a = formRef.current) === null || _a === void 0 ? void 0 : _a.getFieldsValue()) || {}; codeValuesRef.current[record._id] = __assign(__assign({}, codeValuesRef.current[record._id] || {}), values); setCodeEditorType(function (p) { var _a; return __assign(__assign({}, p), (_a = {}, _a[record._id] = v, _a)); }); } } }); } return d; }), modalProps: { width: "80%", centered: true, onCancel: function onCancel() { onCodeCancel(record); } }, onFinish: function onFinish(values) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { if (values.codeEditorType === "js") { codeValuesRef.current[record._id] = __assign(__assign({}, values), { sql: undefined, sqlLeftJoinClause: undefined }); } else { codeValuesRef.current[record._id] = __assign(__assign({}, values), { run: undefined, shouldSplitGroupby: undefined }); } return [2 /*return*/ , true]; }); }); } }); } }, { title: "基础指标", width: 120, dataIndex: "basePred", hideInSearch: true, valueType: "string", tooltip: "【专家选项】指定此公式在智能归因功能中的结构分析所用的基础聚合指标。例:毛利率的基础聚合指标为销售额,那么毛利率公式的basePred就填销售额。" }, { title: "目标", width: 120, dataIndex: "target", hideInSearch: true, valueType: "number", render: function render(v, record) { if (typeof record.target !== "number") { return "-"; } return formatWithProperty({ type: record.type, primal_type: record.primal_type }, record.target); } }, { title: "单位", dataIndex: "unit", width: 120, tooltip: "例如: (元)。此字段会显示在问答的结果旁边。" }, { title: "数字格式", dataIndex: "ui.formatter", width: 120, tooltip: "例如: 0,0.0A。格式配置详情请见使用文档" }, { title: "图表格式", dataIndex: "ui.representation", width: 120, valueType: "select", fieldProps: { options: [{ label: "柱状图", value: "column" }, { label: "横向柱状图", value: "bar" }, { label: "折线图", value: "line" }, { label: "面积图", value: "area" }, { label: "饼图", value: "pie" }] } }, { title: "说明", dataIndex: "description", hideInSearch: true, width: 200 }, { title: "操作", width: 160, valueType: "option", hideInSearch: true, hideInPayload: true, fixed: "right", render: function render(_text, record, _index, action) { return [/*#__PURE__*/React.createElement("a", { key: "editable", onClick: function onClick() { var _a; (_a = action === null || action === void 0 ? void 0 : action.startEditable) === null || _a === void 0 ? void 0 : _a.call(action, record._id); } }, "\u7F16\u8F91"), /*#__PURE__*/React.createElement("a", { key: "expert", onClick: function onClick() { setDrawerVisible(true); setEditingRecord(record); } }, "\u4E13\u5BB6"), /*#__PURE__*/React.createElement(_Popconfirm, { title: "\u662F\u5426\u786E\u5B9A\u5220\u9664", key: "delete", onConfirm: function onConfirm() { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/ , deleteMeasurementsByName(record)]; case 1: _a.sent(); reloadData(); return [2 /*return*/ ]; } }); }); } }, /*#__PURE__*/React.createElement(_Button, { type: "link", danger: true, style: { padding: 0 } }, "\u5220\u9664"))]; } }]; var onExpertCancel = function onExpertCancel() { setDrawerVisible(false); }; var getPayload = function getPayload(record) { if (!record) { return {}; } var payload = {}; Object.keys(record).forEach(function (k) { var _a; var v = (_a = record[k]) !== null && _a !== void 0 ? _a : ""; payload[k] = ("" + v).trim() === "" ? undefined : v; }); var finalPayload = flatten.unflatten(payload); if ("index" in finalPayload) { delete finalPayload._id; delete finalPayload[finalPayload.index]; delete finalPayload.index; } return finalPayload; }; var onSave = function onSave(rowKey, d) { return __awaiter(void 0, void 0, void 0, function () { var target, record, payload; return __generator(this, function (_a) { switch (_a.label) { case 0: setSaveLoading(true); target = data.find(function (d) { return d._id === rowKey; }); if (!target) return [3 /*break*/ , 2]; return [4 /*yield*/ , deleteMeasurementsByName(target)]; case 1: _a.sent(); _a.label = 2; case 2: record = __assign(__assign({}, flatten(d, { safe: true })), codeValuesRef.current[rowKey]); payload = getPayload(record); return [2 /*return*/ , postMeasurements(payload).then(function () { _message.success("保存成功"); reloadData(); return true; }).catch(function (e) { _message.error("" + e.message); // 如果是edit模式,那么因为之前delete掉了,所以存回来 if (target) { return postMeasurements(target); } return Promise.reject(e); }).finally(function () { setSaveLoading(false); })]; } }); }); }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProProvider.Provider, { value: __assign(__assign({}, values), { valueTypeMap: customValueTypes({ name: "schema", properties: columns.map(function (d) { return { name: d.dataIndex, type: d.valueType, primal_type: d.valueType }; }), type: "entity", _id: "schema" }) }) }, /*#__PURE__*/React.createElement(EditableProTable, { rowKey: "_id", scroll: { x: columns.reduce(function (p, c) { return p + Number(c.width); }, 0) }, recordCreatorProps: { position: "bottom", record: function record() { return { _id: (Math.random() * 1000000).toFixed(0) }; } }, loading: loading || schemasLoading, search: { labelWidth: "auto" }, onReset: function onReset() { setData(originalData); }, onSubmit: function onSubmit(filters) { setData(_.filter(originalData, function (item) { var keys = Object.keys(filters); var res = true; keys.forEach(function (k) { var _a; res = res && ((_a = item[k]) === null || _a === void 0 ? void 0 : _a.includes(filters[k])); }); return res; })); }, columns: columns, value: data, editable: { type: "multiple", editableKeys: editableKeys, onCancel: function onCancel(rowKey, d, record) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { onCodeCancel(record); return [2 /*return*/ , true]; }); }); }, onSave: onSave, onChange: setEditableRowKeys } })), /*#__PURE__*/React.createElement(_Drawer, { open: drawerVisible, width: "90%", maskClosable: false, onClose: function onClose(e) { // 取消按esc退出弹窗 if (e.type === "keydown") { return; } onExpertCancel(); }, title: "\u6307\u6807\u7F16\u8F91-" + (editingRecord === null || editingRecord === void 0 ? void 0 : editingRecord.name), destroyOnClose: true, footer: /*#__PURE__*/React.createElement("div", { style: { display: "flex", flexDirection: "row-reverse" } }, /*#__PURE__*/React.createElement(_Space, null, /*#__PURE__*/React.createElement(_Button, { onClick: function onClick() { onExpertCancel(); } }, "\u53D6\u6D88"), /*#__PURE__*/React.createElement(_Button, { type: "primary", onClick: function onClick() { return __awaiter(void 0, void 0, void 0, function () { var errors, record, codeIsJs, codeIsSql; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!editorRef.current) return [3 /*break*/ , 3]; return [4 /*yield*/ , editorRef.current.validate()]; case 1: errors = _a.sent(); if (errors && errors.length > 0) { _message.error("校验不通过,请检查!"); return [2 /*return*/ ]; } record = editorRef.current.get(); codeIsJs = record.run || record.shouldSplitGroupby; codeIsSql = record.sql || record.sqlLeftJoinClause; if (codeIsJs && codeIsSql) { _message.error("js\u76F8\u5173\u5B57\u6BB5\uFF08run\u3001shouldSplitGroupby\uFF09\u6216sql\u76F8\u5173\u5B57\u6BB5\uFF08sql\u3001sqlLeftJoinClause\uFF09\n \u4E24\u7EC4\u5B57\u6BB5\u4E0D\u80FD\u540C\u65F6\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\uFF01"); return [2 /*return*/ ]; } return [4 /*yield*/ , onSave(editingRecord._id, record)]; case 2: _a.sent(); setDrawerVisible(false); _a.label = 3; case 3: return [2 /*return*/ ]; } }); }); }, loading: saveLoading }, "\u786E\u5B9A"))) }, /*#__PURE__*/React.createElement(JsonEditor, { value: getPayload(editingRecord), editorRef: editorRef, editable: true, isCreate: editingRecord === null }))); }; export default MeasurementEditor;