Commit 0b6110a8fc92a11df6501346e093246a5abe2b0e

Authored by vben
1 parent 4ddee05d

feat(form-page): add form page demo

Showing 43 changed files with 1389 additions and 116 deletions
CHANGELOG.zh_CN.md
... ... @@ -4,6 +4,9 @@
4 4  
5 5 - 新增 base64 文件流下载
6 6 - 优化上传组件及示例
  7 +- 新增可编辑行示例
  8 +- 新增个人页
  9 +- 新增表单页
7 10  
8 11 ### 🎫 Chores
9 12  
... ...
README.md
... ... @@ -232,6 +232,8 @@ yarn clean:lib # 删除node_modules,兼容window系统
232 232  
233 233 ## 正在开发的功能
234 234  
  235 +- [ ] 新分支全局国家化
  236 +- [ ] 示例 page 页面
235 237 - [ ] 主题配置
236 238 - [ ] 黑暗主题
237 239 - [ ] 打包 CDN
... ...
package.json
... ... @@ -23,7 +23,7 @@
23 23 "dependencies": {
24 24 "@iconify/iconify": "^2.0.0-rc.2",
25 25 "@vueuse/core": "^4.0.0-beta.41",
26   - "ant-design-vue": "^2.0.0-rc.1",
  26 + "ant-design-vue": "^2.0.0-beta.15",
27 27 "apexcharts": "3.22.0",
28 28 "axios": "^0.21.0",
29 29 "echarts": "^4.9.0",
... ...
src/components/Basic/src/BasicHelp.vue
... ... @@ -48,6 +48,10 @@
48 48 bottom: 0,
49 49 }),
50 50 },
  51 + placement: {
  52 + type: String as PropType<string>,
  53 + defualt: 'right',
  54 + },
51 55 },
52 56 setup(props, { slots }) {
53 57 const getOverlayStyleRef = computed(() => {
... ... @@ -97,7 +101,7 @@
97 101 overlayClassName: 'base-help__wrap',
98 102 autoAdjustOverflow: true,
99 103 overlayStyle: unref(getOverlayStyleRef),
100   - placement: 'right',
  104 + placement: props.placement,
101 105 getPopupContainer: () => getPopupContainer(),
102 106 },
103 107 {
... ...
src/components/Footer/index.ts 0 → 100644
  1 +export { default as AppFooter } from './src/index.vue';
... ...
src/components/Footer/src/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-footer" :style="{ width: getWidth }">
  3 + <div class="app-footer__left">
  4 + <slot name="left" />
  5 + </div>
  6 + <div class="app-footer__right">
  7 + <slot name="right" />
  8 + </div>
  9 + </div>
  10 +</template>
  11 +<script lang="ts">
  12 + import { defineComponent, computed, unref } from 'vue';
  13 + import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
  14 + import { appStore } from '/@/store/modules/app';
  15 + import { menuStore } from '/@/store/modules/menu';
  16 + export default defineComponent({
  17 + name: 'AppFooter',
  18 + setup() {
  19 + const getMiniWidth = computed(() => {
  20 + const {
  21 + menuSetting: { collapsedShowTitle },
  22 + } = appStore.getProjectConfig;
  23 + return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
  24 + });
  25 +
  26 + const getWidth = computed(() => {
  27 + const { getCollapsedState, getMenuWidthState } = menuStore;
  28 + const width = getCollapsedState ? unref(getMiniWidth) : getMenuWidthState;
  29 + return `calc(100% - ${width}px)`;
  30 + });
  31 +
  32 + return { getWidth };
  33 + },
  34 + });
  35 +</script>
  36 +<style lang="less" scoped>
  37 + .app-footer {
  38 + position: fixed;
  39 + right: 0;
  40 + bottom: 0;
  41 + z-index: 99;
  42 + display: flex;
  43 + width: 100%;
  44 + align-items: center;
  45 + padding: 0 24px;
  46 + line-height: 44px;
  47 + background: #fff;
  48 + border-top: 1px solid #f0f0f0;
  49 + box-shadow: 0 -6px 16px -8px rgba(0, 0, 0, 0.08), 0 -9px 28px 0 rgba(0, 0, 0, 0.05),
  50 + 0 -12px 48px 16px rgba(0, 0, 0, 0.03);
  51 + transition: width 0.3s;
  52 +
  53 + &__left {
  54 + flex: 1 1;
  55 + }
  56 + }
  57 +</style>
... ...
src/components/Form/src/BasicForm.vue
1 1 <template>
2   - <Form v-bind="$attrs" ref="formElRef" :model="formModel">
  2 + <Form v-bind="{ ...$attrs, ...$props }" ref="formElRef" :model="formModel">
3 3 <Row :class="getProps.compact ? 'compact-form-row' : ''">
4 4 <slot name="formHeader" />
5 5 <template v-for="schema in getSchema" :key="schema.field">
... ... @@ -54,8 +54,8 @@
54 54 const formModel = reactive({});
55 55  
56 56 const actionState = reactive({
57   - resetAction: () => {},
58   - submitAction: () => {},
  57 + resetAction: {},
  58 + submitAction: {},
59 59 });
60 60  
61 61 const advanceState = reactive<AdvanceState>({
... ... @@ -67,7 +67,7 @@
67 67  
68 68 const defaultValueRef = ref<any>({});
69 69 const propsRef = ref<Partial<FormProps>>({});
70   - const schemaRef = ref<FormSchema[] | null>(null);
  70 + const schemaRef = ref<Nullable<FormSchema[]>>(null);
71 71 const formElRef = ref<Nullable<FormActionType>>(null);
72 72  
73 73 const getMergePropsRef = computed(
... ... @@ -98,7 +98,15 @@
98 98 for (const schema of schemas) {
99 99 const { defaultValue, component } = schema;
100 100 if (defaultValue && dateItemType.includes(component!)) {
101   - schema.defaultValue = moment(defaultValue);
  101 + if (!Array.isArray(defaultValue)) {
  102 + schema.defaultValue = moment(defaultValue);
  103 + } else {
  104 + const def: moment.Moment[] = [];
  105 + defaultValue.forEach((item) => {
  106 + def.push(moment(item));
  107 + });
  108 + schema.defaultValue = def;
  109 + }
102 110 }
103 111 }
104 112 return schemas as FormSchema[];
... ... @@ -139,8 +147,8 @@
139 147 formModel,
140 148 getSchema,
141 149 defaultValueRef,
142   - formElRef: formElRef as any,
143   - schemaRef: schemaRef as any,
  150 + formElRef: formElRef as Ref<FormActionType>,
  151 + schemaRef: schemaRef as Ref<FormSchema[]>,
144 152 handleFormValues,
145 153 actionState,
146 154 });
... ... @@ -156,6 +164,13 @@
156 164 }
157 165 );
158 166  
  167 + watch(
  168 + () => getSchema.value,
  169 + () => {
  170 + initDefault();
  171 + }
  172 + );
  173 +
159 174 /**
160 175 * @description:设置表单
161 176 */
... ...
src/components/Form/src/FormItem.tsx
... ... @@ -250,14 +250,21 @@ export default defineComponent({
250 250 }
251 251  
252 252 function renderLabelHelpMessage() {
253   - const { label, helpMessage, helpComponentProps } = props.schema;
  253 + const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
  254 + const renderLabel = subLabel ? (
  255 + <span>
  256 + {label} <span style="color:#00000073">{subLabel}</span>
  257 + </span>
  258 + ) : (
  259 + label
  260 + );
254 261 if (!helpMessage || (Array.isArray(helpMessage) && helpMessage.length === 0)) {
255   - return label;
  262 + return renderLabel;
256 263 }
257 264 return (
258 265 <span>
259   - {label}
260   - <BasicHelp class="mx-1" text={helpMessage} {...helpComponentProps} />
  266 + {renderLabel}
  267 + <BasicHelp placement="top" class="mx-1" text={helpMessage} {...helpComponentProps} />
261 268 </span>
262 269 );
263 270 }
... ... @@ -291,6 +298,7 @@ export default defineComponent({
291 298 const { colProps = {}, colSlot, renderColContent, component } = props.schema;
292 299 if (!componentMap.has(component)) return null;
293 300 const { baseColProps = {} } = props.formProps;
  301 +
294 302 const realColProps = { ...baseColProps, ...colProps };
295 303 const { isIfShow, isShow } = getShow();
296 304 const getContent = () => {
... ...
src/components/Form/src/helper.ts
... ... @@ -7,7 +7,7 @@ export function createPlaceholderMessage(component: ComponentType) {
7 7 if (component.includes('Input') || component.includes('Complete')) {
8 8 return '请输入';
9 9 }
10   - if (component.includes('Picker') && !component.includes('Range')) {
  10 + if (component.includes('Picker')) {
11 11 return '请选择';
12 12 }
13 13 if (
... ...
src/components/Form/src/hooks/useLabelWidth.ts
... ... @@ -25,19 +25,26 @@ export function useItemLabelWidth(schemaItemRef: Ref&lt;FormSchema&gt;, propsRef: Ref&lt;
25 25 const { labelCol = {}, wrapperCol = {} } = schemaItem.itemProps || {};
26 26 const { labelWidth, disabledLabelWidth } = schemaItem;
27 27  
28   - const { labelWidth: globalLabelWidth } = unref(propsRef) as any;
  28 + const {
  29 + labelWidth: globalLabelWidth,
  30 + labelCol: globalLabelCol,
  31 + wrapperCol: globWrapperCol,
  32 + } = unref(propsRef) as any;
  33 +
29 34 // 如果全局有设置labelWidth, 则所有item使用
30   - if ((!globalLabelWidth && !labelWidth) || disabledLabelWidth) {
  35 + if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) {
31 36 return { labelCol, wrapperCol };
32 37 }
33 38 let width = labelWidth || globalLabelWidth;
  39 + const col = { ...globalLabelCol, ...labelCol };
  40 + const wrapCol = { ...globWrapperCol, ...wrapperCol };
34 41  
35 42 if (width) {
36 43 width = isNumber(width) ? `${width}px` : width;
37 44 }
38 45 return {
39   - labelCol: { style: { width }, ...labelCol },
40   - wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapperCol },
  46 + labelCol: { style: { width }, ...col },
  47 + wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapCol },
41 48 };
42 49 });
43 50 }
... ...
src/components/Form/src/types/form.ts
... ... @@ -41,6 +41,7 @@ export type RegisterFn = (formInstance: FormActionType) =&gt; void;
41 41 export type UseFormReturnType = [RegisterFn, FormActionType];
42 42  
43 43 export interface FormProps {
  44 + // layout?: 'vertical' | 'inline' | 'horizontal';
44 45 // 表单值
45 46 model?: any;
46 47 // 整个表单所有项宽度
... ... @@ -108,6 +109,8 @@ export interface FormSchema {
108 109 valueField?: string;
109 110 // 标签名
110 111 label: string;
  112 + // 辅助文本
  113 + subLabel?: string;
111 114 // 文本右侧帮助文本
112 115 helpMessage?: string | string[];
113 116 // BaseHelp组件props
... ...
src/components/Menu/src/BasicMenu.tsx
... ... @@ -136,9 +136,9 @@ export default defineComponent({
136 136 const flag = await beforeClickFn(menu);
137 137 if (!flag) return;
138 138 }
  139 + emit('menuClick', menu);
139 140 const { path } = menu;
140 141 menuState.selectedKeys = [path];
141   - emit('menuClick', menu);
142 142 }
143 143  
144 144 function handleMenuChange() {
... ... @@ -219,7 +219,6 @@ export default defineComponent({
219 219 : {};
220 220 return (
221 221 <Menu
222   - forceSubMenuRender={props.isAppMenu}
223 222 selectedKeys={selectedKeys}
224 223 defaultSelectedKeys={defaultSelectedKeys}
225 224 mode={mode}
... ...
src/components/Table/index.ts
1 1 export { default as BasicTable } from './src/BasicTable.vue';
2 2 export { default as TableAction } from './src/components/TableAction';
3 3 export { default as TableImg } from './src/components/TableImg.vue';
4   -export { renderEditableCell } from './src/components/renderEditableCell';
  4 +export { renderEditableCell, renderEditableRow } from './src/components/renderEditable';
5 5 export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue';
6 6  
7 7 export * from './src/types/table';
... ... @@ -11,3 +11,5 @@ export * from &#39;./src/types/tableAction&#39;;
11 11 export { useTable } from './src/hooks/useTable';
12 12  
13 13 export type { FormSchema, FormProps } from '/@/components/Form/src/types/form';
  14 +
  15 +export type { EditRecordRow } from './src/components/renderEditable';
... ...
src/components/Table/src/components/TableAction.tsx
... ... @@ -32,7 +32,7 @@ export default defineComponent({
32 32 disabled={disabled}
33 33 color={color}
34 34 {...action}
35   - key={index}
  35 + key={`${index}-${label}`}
36 36 >
37 37 {() => (
38 38 <>
... ... @@ -60,7 +60,7 @@ export default defineComponent({
60 60 } = popConfirm;
61 61 return (
62 62 <Popconfirm
63   - key={`P-${index}`}
  63 + key={`p-${index}-${title}`}
64 64 title={title}
65 65 onConfirm={confirm}
66 66 onCancel={cancel}
... ...
src/components/Table/src/components/renderEditableCell.tsx renamed to src/components/Table/src/components/renderEditable.tsx
1   -import { defineComponent, PropType, ref, unref, nextTick } from 'vue';
2   -import { injectTable } from '../hooks/useProvinceTable';
  1 +import { defineComponent, PropType, ref, unref, nextTick, watchEffect } from 'vue';
3 2 import ClickOutSide from '/@/components/ClickOutSide/index.vue';
4 3  
5 4 import { RenderEditableCellParams } from '../types/table';
6 5 import { ComponentType } from '../types/componentType';
7 6  
8 7 import { componentMap } from '../componentMap';
9   -import '../style/editable-cell.less';
10 8 import { isString, isBoolean } from '/@/utils/is';
11 9 import { FormOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
12 10  
  11 +import '../style/editable-cell.less';
  12 +
13 13 const prefixCls = 'editable-cell';
14 14 const EditableCell = defineComponent({
15 15 name: 'EditableCell',
... ... @@ -37,14 +37,35 @@ const EditableCell = defineComponent({
37 37 type: String as PropType<ComponentType>,
38 38 default: 'Input',
39 39 },
  40 + editable: {
  41 + type: Boolean as PropType<boolean>,
  42 + default: false,
  43 + },
  44 + editRow: {
  45 + type: Boolean as PropType<boolean>,
  46 + default: false,
  47 + },
  48 + record: {
  49 + type: Object as PropType<EditRecordRow>,
  50 + },
  51 + placeholder: {
  52 + type: String as PropType<string>,
  53 + },
40 54 },
41 55 emits: ['submit', 'cancel'],
42 56 setup(props, { attrs, emit }) {
43   - const table = injectTable();
44 57 const elRef = ref<any>(null);
45 58  
46 59 const isEditRef = ref(false);
47 60 const currentValueRef = ref<string | boolean>(props.value);
  61 + const defaultValueRef = ref<string | boolean>(props.value);
  62 +
  63 + watchEffect(() => {
  64 + defaultValueRef.value = props.value;
  65 + if (isBoolean(props.editable)) {
  66 + isEditRef.value = props.editable;
  67 + }
  68 + });
48 69  
49 70 function handleChange(e: any) {
50 71 if (e && e.target && Reflect.has(e.target, 'value')) {
... ... @@ -65,37 +86,55 @@ const EditableCell = defineComponent({
65 86  
66 87 function handleCancel() {
67 88 isEditRef.value = false;
  89 + currentValueRef.value = defaultValueRef.value;
68 90 emit('cancel');
69 91 }
70 92  
  93 + if (props.record) {
  94 + /* eslint-disable */
  95 + props.record.onCancel = handleCancel;
  96 + /* eslint-disable */
  97 + props.record.onSubmit = handleSubmit;
  98 + }
  99 +
71 100 function handleSubmit() {
72 101 const { dataKey, dataIndex } = props;
73   - if (!dataKey || !dataIndex) {
74   - return;
75   - }
76   - isEditRef.value = false;
  102 + if (!dataKey || !dataIndex) return;
77 103  
78   - const { getDataSource } = table;
79   - const dataSource = getDataSource();
80   - const target = dataSource.find((item) => item.key === dataKey);
81   - if (target) {
82   - target[dataIndex] = unref(currentValueRef);
83   - emit('submit', { dataKey, dataIndex, value: unref(currentValueRef) });
  104 + if (props.record) {
  105 + /* eslint-disable */
  106 + props.record[dataIndex] = unref(currentValueRef) as string;
84 107 }
  108 + isEditRef.value = false;
85 109 }
86 110  
87 111 function onClickOutside() {
  112 + if (props.editRow) return;
88 113 const { component } = props;
89 114  
90 115 if (component && component.includes('Input')) {
91 116 handleCancel();
92 117 }
93 118 }
  119 +
  120 + function renderValue() {
  121 + const { value } = props;
  122 + if (props.editRow) {
  123 + return !unref(isEditRef) ? value : null;
  124 + }
  125 + return (
  126 + !unref(isEditRef) && (
  127 + <div class={`${prefixCls}__normal`} onClick={handleEdit}>
  128 + {value}
  129 + <FormOutlined class={`${prefixCls}__normal-icon`} />
  130 + </div>
  131 + )
  132 + );
  133 + }
94 134 return () => {
95   - const { value, component, componentProps = {} } = props;
  135 + const { component, componentProps = {} } = props;
96 136  
97 137 const Comp = componentMap.get(component!) as any;
98   - // const propsData: any = {};
99 138 return (
100 139 <div class={prefixCls}>
101 140 {unref(isEditRef) && (
... ... @@ -103,6 +142,7 @@ const EditableCell = defineComponent({
103 142 {() => (
104 143 <div class={`${prefixCls}__wrapper`}>
105 144 <Comp
  145 + placeholder={props.placeholder}
106 146 {...{
107 147 ...attrs,
108 148 ...componentProps,
... ... @@ -114,21 +154,20 @@ const EditableCell = defineComponent({
114 154 onChange={handleChange}
115 155 onPressEnter={handleSubmit}
116 156 />
117   - <div class={`${prefixCls}__action`}>
118   - <CheckOutlined class={[`${prefixCls}__icon`, 'mx-2']} onClick={handleSubmit} />
119   - <CloseOutlined class={[`${prefixCls}__icon `]} onClick={handleCancel} />
120   - </div>
  157 + {!props.editRow && (
  158 + <div class={`${prefixCls}__action`}>
  159 + <CheckOutlined
  160 + class={[`${prefixCls}__icon`, 'mx-2']}
  161 + onClick={handleSubmit}
  162 + />
  163 + <CloseOutlined class={[`${prefixCls}__icon `]} onClick={handleCancel} />
  164 + </div>
  165 + )}
121 166 </div>
122 167 )}
123 168 </ClickOutSide>
124 169 )}
125   -
126   - {!unref(isEditRef) && (
127   - <div class={`${prefixCls}__normal`} onClick={handleEdit}>
128   - {value}
129   - <FormOutlined class={`${prefixCls}__normal-icon`} />
130   - </div>
131   - )}
  170 + {renderValue()}
132 171 </div>
133 172 );
134 173 };
... ... @@ -138,15 +177,16 @@ const EditableCell = defineComponent({
138 177 export function renderEditableCell({
139 178 dataIndex,
140 179 component,
141   - componentOn = {},
142 180 componentProps = {},
  181 + placeholder,
143 182 }: RenderEditableCellParams) {
144   - return ({ text, record }: { text: string; record: any }) => {
  183 + return ({ text, record }: { text: string; record: EditRecordRow }) => {
145 184 return (
146 185 <EditableCell
147   - {...componentOn}
148 186 {...componentProps}
  187 + placeholder={placeholder}
149 188 value={text}
  189 + record={record}
150 190 dataKey={record.key}
151 191 dataIndex={dataIndex}
152 192 component={component}
... ... @@ -154,3 +194,32 @@ export function renderEditableCell({
154 194 );
155 195 };
156 196 }
  197 +
  198 +export function renderEditableRow({
  199 + dataIndex,
  200 + component,
  201 + componentProps = {},
  202 + placeholder,
  203 +}: RenderEditableCellParams) {
  204 + return ({ text, record }: { text: string; record: EditRecordRow }) => {
  205 + return (
  206 + <EditableCell
  207 + {...componentProps}
  208 + value={text}
  209 + placeholder={placeholder}
  210 + editRow={true}
  211 + editable={record.editable}
  212 + dataKey={record.key}
  213 + record={record}
  214 + dataIndex={dataIndex}
  215 + component={component}
  216 + />
  217 + );
  218 + };
  219 +}
  220 +
  221 +export type EditRecordRow<T = { [key: string]: any }> = {
  222 + editable: boolean;
  223 + onCancel: Fn;
  224 + onSubmit: Fn;
  225 +} & T;
... ...
src/components/Table/src/types/table.ts
... ... @@ -68,8 +68,8 @@ export interface SorterResult {
68 68 export interface RenderEditableCellParams {
69 69 dataIndex: string;
70 70 component?: ComponentType;
71   - componentOn?: { [key: string]: Fn };
72 71 componentProps?: any;
  72 + placeholder?: string;
73 73 }
74 74  
75 75 export interface FetchParams {
... ... @@ -88,15 +88,15 @@ export type SizeType = &#39;default&#39; | &#39;middle&#39; | &#39;small&#39; | &#39;large&#39;;
88 88  
89 89 export interface TableActionType {
90 90 reload: (opt?: FetchParams) => Promise<void>;
91   - getSelectRows: () => any[];
  91 + getSelectRows: <T = any>() => T[];
92 92 clearSelectedRowKeys: () => void;
93 93 getSelectRowKeys: () => string[];
94 94 deleteSelectRowByKey: (key: string) => void;
95 95 setPagination: (info: Partial<PaginationProps>) => void;
96   - setTableData: (values: any[]) => void;
  96 + setTableData: <T = any>(values: T[]) => void;
97 97 getColumns: (opt?: GetColumnsParams) => BasicColumn[];
98 98 setColumns: (columns: BasicColumn[] | string[]) => void;
99   - getDataSource: () => any[];
  99 + getDataSource: <T = any>() => T[];
100 100 setLoading: (loading: boolean) => void;
101 101 setProps: (props: Partial<BasicTableProps>) => void;
102 102 redoHeight: () => void;
... ...
src/components/Table/src/types/tableAction.ts
1 1 export interface ActionItem {
2   - on?: any;
3 2 onClick?: any;
4 3 label: string;
5 4 disabled?: boolean;
... ...
src/components/registerGlobComp.ts
1 1 import Icon from './Icon/index';
2 2 import Button from './Button/index.vue';
  3 +import { AppFooter } from './Footer';
3 4 import {
4 5 // Need
5 6 Button as AntButton,
... ... @@ -28,10 +29,12 @@ import {
28 29 Upload,
29 30 Transfer,
30 31 Steps,
  32 + PageHeader,
  33 + Result,
31 34 } from 'ant-design-vue';
32 35 import { getApp } from '/@/useApp';
33 36  
34   -const compList = [Icon, Button, AntButton.Group];
  37 +const compList = [Icon, Button, AntButton.Group, AppFooter];
35 38  
36 39 // Fix hmr multiple registered components
37 40 let registered = false;
... ... @@ -70,5 +73,7 @@ export function registerGlobComp() {
70 73 .use(Upload)
71 74 .use(Transfer)
72 75 .use(Steps)
  76 + .use(PageHeader)
  77 + .use(Result)
73 78 .use(Tabs);
74 79 }
... ...
src/design/ant/index.less
... ... @@ -109,18 +109,21 @@
109 109 content: '';
110 110 }
111 111  
  112 +.ant-form-item-with-help {
  113 + margin-bottom: 0;
  114 +}
  115 +
112 116 .ant-form-item {
113 117 &-label label::after {
114 118 margin: 0 6px 0 2px;
115 119 }
  120 +}
116 121  
117   - &-control {
118   - line-height: 36px;
119   - }
  122 +.ant-form-item:not(.ant-form-item-with-help) {
  123 + margin-bottom: 20px;
120 124 }
121 125  
122 126 .ant-form-explain {
123   - margin-bottom: 2px;
124 127 font-size: 14px;
125 128 }
126 129  
... ...
src/design/index.less
... ... @@ -13,6 +13,14 @@
13 13 box-sizing: border-box;
14 14 }
15 15  
  16 +input:-webkit-autofill {
  17 + -webkit-box-shadow: 0 0 0 1000px white inset !important;
  18 +}
  19 +
  20 +:-webkit-autofill {
  21 + transition: background-color 5000s ease-in-out 0s !important;
  22 +}
  23 +
16 24 // Background color setting in full screen state in each browser
17 25 ::backdrop,
18 26 html,
... ...
src/design/transition/base.less
1 1 .transition-default() {
2 2 &-enter-active,
3 3 &-leave-active {
4   - transition: 0.2s cubic-bezier(0.25, 0.8, 0.5, 1) !important;
  4 + transition: 0.1s cubic-bezier(0.25, 0.8, 0.5, 1) !important;
5 5 }
6 6  
7 7 &-move {
8   - transition: transform 0.5s;
  8 + transition: transform 0.2s;
9 9 }
10 10 }
11 11  
... ...
src/design/transition/fade.less
... ... @@ -11,7 +11,7 @@
11 11 /* fade-slide */
12 12 .fade-slide-leave-active,
13 13 .fade-slide-enter-active {
14   - transition: all 0.5s;
  14 + transition: all 0.2s;
15 15 }
16 16  
17 17 .fade-slide-enter-from {
... ...
src/design/var/index.less
... ... @@ -16,4 +16,4 @@
16 16 @page-loading-z-index: 10000;
17 17  
18 18 // left-menu
19   -@app-menu-item-height: 44px;
  19 +@app-menu-item-height: 46px;
... ...
src/layouts/default/menu/LayoutMenu.tsx
... ... @@ -154,12 +154,12 @@ export default defineComponent({
154 154 function handleMenuClick(menu: Menu) {
155 155 const { path } = menu;
156 156 if (path) {
  157 + push(path);
157 158 const { splitType } = props;
158 159 // split mode top
159 160 if (splitType === MenuSplitTyeEnum.TOP) {
160 161 menuStore.commitCurrentTopSplitMenuPathState(path);
161 162 }
162   - push(path);
163 163 }
164 164 }
165 165  
... ...
src/router/menus/modules/demo/form.ts
... ... @@ -14,7 +14,7 @@ const menu: MenuModule = {
14 14 name: '基础表单',
15 15 tag: {
16 16 type: 'warn',
17   - content: 'updated',
  17 + dot: true,
18 18 },
19 19 },
20 20 {
... ... @@ -34,7 +34,7 @@ const menu: MenuModule = {
34 34 name: '表单校验',
35 35 tag: {
36 36 type: 'warn',
37   - content: 'updated',
  37 + dot: true,
38 38 },
39 39 },
40 40 {
... ... @@ -42,7 +42,7 @@ const menu: MenuModule = {
42 42 name: '动态表单',
43 43 tag: {
44 44 type: 'warn',
45   - content: 'updated',
  45 + dot: true,
46 46 },
47 47 },
48 48 {
... ... @@ -50,7 +50,7 @@ const menu: MenuModule = {
50 50 name: '自定义组件',
51 51 tag: {
52 52 type: 'warn',
53   - content: 'updated',
  53 + dot: true,
54 54 },
55 55 },
56 56 ],
... ...
src/router/menus/modules/demo/page.ts
... ... @@ -16,6 +16,27 @@ const menu: MenuModule = {
16 16 },
17 17 children: [
18 18 {
  19 + path: 'form',
  20 + name: '表单页',
  21 + tag: {
  22 + content: 'new',
  23 + },
  24 + children: [
  25 + {
  26 + path: 'basic',
  27 + name: '基础表单',
  28 + },
  29 + {
  30 + path: 'step',
  31 + name: '分步表单',
  32 + },
  33 + {
  34 + path: 'high',
  35 + name: '高级表单',
  36 + },
  37 + ],
  38 + },
  39 + {
19 40 path: 'result',
20 41 name: '结果页',
21 42 tag: {
... ...
src/router/menus/modules/demo/table.ts
... ... @@ -4,6 +4,9 @@ const menu: MenuModule = {
4 4 menu: {
5 5 path: '/table',
6 6 name: 'Table',
  7 + tag: {
  8 + dot: true,
  9 + },
7 10 children: [
8 11 {
9 12 path: 'basic',
... ... @@ -61,6 +64,13 @@ const menu: MenuModule = {
61 64 path: 'editCellTable',
62 65 name: '可编辑单元格',
63 66 },
  67 + {
  68 + path: 'editRowTable',
  69 + name: '可编辑行',
  70 + tag: {
  71 + content: 'new',
  72 + },
  73 + },
64 74 ],
65 75 },
66 76 };
... ...
src/router/routes/modules/demo/page.ts
... ... @@ -15,6 +15,43 @@ const page: AppRouteModule = {
15 15 title: '页面',
16 16 },
17 17 children: [
  18 + // =============================form start=============================
  19 + {
  20 + path: '/form',
  21 + name: 'FormPage',
  22 + redirect: '/page-demo/form/basic',
  23 + meta: {
  24 + title: '表单页',
  25 + },
  26 + children: [
  27 + {
  28 + path: 'basic',
  29 + name: 'FormBasicPage',
  30 + component: () => import('/@/views/demo/page/form/basic/index.vue'),
  31 + meta: {
  32 + title: '基础表单',
  33 + },
  34 + },
  35 + {
  36 + path: 'step',
  37 + name: 'FormStepPage',
  38 + component: () => import('/@/views/demo/page/form/step/index.vue'),
  39 + meta: {
  40 + title: '分步表单',
  41 + },
  42 + },
  43 + {
  44 + path: 'high',
  45 + name: 'FormHightPage',
  46 + component: () => import('/@/views/demo/page/form/high/index.vue'),
  47 + meta: {
  48 + title: '高级表单',
  49 + },
  50 + },
  51 + ],
  52 + },
  53 + // =============================form end=============================
  54 +
18 55 // =============================result start=============================
19 56 {
20 57 path: '/result',
... ...
src/router/routes/modules/demo/table.ts
... ... @@ -127,6 +127,14 @@ const table: AppRouteModule = {
127 127 title: '可编辑单元格',
128 128 },
129 129 },
  130 + {
  131 + path: '/editRowTable',
  132 + name: 'EditRowTableDemo',
  133 + component: () => import('/@/views/demo/table/EditRowTable.vue'),
  134 + meta: {
  135 + title: '可编辑行',
  136 + },
  137 + },
130 138 ],
131 139 };
132 140  
... ...
src/views/demo/page/account/center/Project.vue
... ... @@ -51,7 +51,6 @@
51 51  
52 52 img {
53 53 width: 100%;
54   - height: 100px;
55 54 }
56 55  
57 56 &-title {
... ...
src/views/demo/page/form/basic/data.ts 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +
  3 +export const schemas: FormSchema[] = [
  4 + {
  5 + field: 'title',
  6 + component: 'Input',
  7 + label: '标题',
  8 + componentProps: {
  9 + placeholder: '给目标起个名字',
  10 + },
  11 + required: true,
  12 + },
  13 + {
  14 + field: 'time',
  15 + component: 'RangePicker',
  16 + label: '起止日期',
  17 + required: true,
  18 + },
  19 + {
  20 + field: 'target',
  21 + component: 'InputTextArea',
  22 + label: '目标描述',
  23 + componentProps: {
  24 + placeholder: '请输入你的阶段性工作目标',
  25 + rows: 4,
  26 + },
  27 + required: true,
  28 + },
  29 + {
  30 + field: 'metrics',
  31 + component: 'InputTextArea',
  32 + label: '衡量标准',
  33 + componentProps: {
  34 + placeholder: '请输入衡量标准',
  35 + rows: 4,
  36 + },
  37 + required: true,
  38 + },
  39 + {
  40 + field: 'client',
  41 + component: 'Input',
  42 + label: '客户',
  43 + helpMessage: '目标的服务对象',
  44 + subLabel: '( 选填 )',
  45 + componentProps: {
  46 + placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
  47 + },
  48 + },
  49 + {
  50 + field: 'inviteer',
  51 + component: 'Input',
  52 + label: '邀评人',
  53 + subLabel: '( 选填 )',
  54 + componentProps: {
  55 + placeholder: '请直接 @姓名/工号,最多可邀请 5 人',
  56 + },
  57 + },
  58 + {
  59 + field: 'weights',
  60 + component: 'InputNumber',
  61 + label: '权重',
  62 + subLabel: '( 选填 )',
  63 + componentProps: {
  64 + formatter: (value: string) => (value ? `${value}%` : ''),
  65 + parser: (value: string) => value.replace('%', ''),
  66 + placeholder: '请输入',
  67 + },
  68 + },
  69 + {
  70 + field: 'disclosure',
  71 + component: 'RadioGroup',
  72 + label: '目标公开',
  73 + itemProps: {
  74 + extra: '客户、邀评人默认被分享',
  75 + },
  76 + componentProps: {
  77 + options: [
  78 + {
  79 + label: '公开',
  80 + value: '1',
  81 + },
  82 + {
  83 + label: '部分公开',
  84 + value: '2',
  85 + },
  86 + {
  87 + label: '不公开',
  88 + value: '3',
  89 + },
  90 + ],
  91 + },
  92 + },
  93 + {
  94 + field: 'disclosurer',
  95 + component: 'Select',
  96 + label: ' ',
  97 + show: ({ model }) => {
  98 + return model.disclosure === '2';
  99 + },
  100 + componentProps: {
  101 + placeholder: '公开给',
  102 + mode: 'multiple',
  103 + options: [
  104 + {
  105 + label: '同事1',
  106 + value: '1',
  107 + },
  108 + {
  109 + label: '同事2',
  110 + value: '2',
  111 + },
  112 + {
  113 + label: '同事3',
  114 + value: '3',
  115 + },
  116 + ],
  117 + },
  118 + },
  119 +];
... ...
src/views/demo/page/form/basic/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <a-page-header title="基础表单" :ghost="false">
  4 + 表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。
  5 + </a-page-header>
  6 +
  7 + <div class="m-5 form-wrap">
  8 + <BasicForm @register="register" />
  9 + </div>
  10 + </div>
  11 +</template>
  12 +<script lang="ts">
  13 + import { BasicForm, useForm } from '/@/components/Form';
  14 + import { defineComponent } from 'vue';
  15 + import { schemas } from './data';
  16 + import { useMessage } from '/@/hooks/web/useMessage';
  17 + export default defineComponent({
  18 + components: { BasicForm },
  19 + setup() {
  20 + const { createMessage } = useMessage();
  21 + const [register, { validate, setProps }] = useForm({
  22 + labelCol: {
  23 + span: 7,
  24 + },
  25 + wrapperCol: {
  26 + span: 10,
  27 + },
  28 + schemas: schemas,
  29 + actionColOptions: {
  30 + offset: 8,
  31 + },
  32 + submitButtonOptions: {
  33 + text: '提交',
  34 + },
  35 + submitFunc: customSubmitFunc,
  36 + });
  37 +
  38 + async function customSubmitFunc() {
  39 + try {
  40 + await validate();
  41 + setProps({
  42 + submitButtonOptions: {
  43 + loading: true,
  44 + },
  45 + });
  46 + setTimeout(() => {
  47 + setProps({
  48 + submitButtonOptions: {
  49 + loading: false,
  50 + },
  51 + });
  52 + createMessage.success('提交成功!');
  53 + }, 2000);
  54 + } catch (error) {}
  55 + }
  56 +
  57 + return { register };
  58 + },
  59 + });
  60 +</script>
  61 +<style lang="less" scoped>
  62 + .form-wrap {
  63 + padding: 24px;
  64 + background: #fff;
  65 + }
  66 +</style>
... ...
src/views/demo/page/form/high/PersonTable.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <BasicTable @register="registerTable">
  4 + <template #action="{ record, column }">
  5 + <TableAction :actions="createActions(record, column)" />
  6 + </template>
  7 + </BasicTable>
  8 + <a-button block class="mt-5" type="dashed" @click="handleAdd">新增成员</a-button>
  9 + </div>
  10 +</template>
  11 +<script lang="ts">
  12 + import { defineComponent } from 'vue';
  13 + import {
  14 + BasicTable,
  15 + useTable,
  16 + TableAction,
  17 + BasicColumn,
  18 + ActionItem,
  19 + renderEditableRow,
  20 + EditTableHeaderIcon,
  21 + EditRecordRow,
  22 + } from '/@/components/Table';
  23 +
  24 + const columns: BasicColumn[] = [
  25 + {
  26 + title: '成员姓名',
  27 + dataIndex: 'name',
  28 + customRender: renderEditableRow({ dataIndex: 'name', placeholder: '请输入成员姓名' }),
  29 + },
  30 + {
  31 + title: '工号',
  32 + dataIndex: 'no',
  33 + customRender: renderEditableRow({ dataIndex: 'no', placeholder: '请输入工号' }),
  34 + },
  35 + {
  36 + title: '所属部门',
  37 + dataIndex: 'dept',
  38 + customRender: renderEditableRow({ dataIndex: 'dept', placeholder: '请输入所属部门' }),
  39 + },
  40 + ];
  41 +
  42 + const data: any[] = [
  43 + {
  44 + name: 'John Brown',
  45 + no: '00001',
  46 + dept: 'New York No. 1 Lake Park',
  47 + },
  48 + {
  49 + name: 'John Brown2',
  50 + no: '00002',
  51 + dept: 'New York No. 2 Lake Park',
  52 + },
  53 + {
  54 + name: 'John Brown3',
  55 + no: '00003',
  56 + dept: 'New York No. 3Lake Park',
  57 + },
  58 + ];
  59 + export default defineComponent({
  60 + components: { BasicTable, EditTableHeaderIcon, TableAction },
  61 + setup() {
  62 + const [registerTable, { getDataSource }] = useTable({
  63 + columns: columns,
  64 + showIndexColumn: false,
  65 + dataSource: data,
  66 + actionColumn: {
  67 + width: 160,
  68 + title: '操作',
  69 + dataIndex: 'action',
  70 + slots: { customRender: 'action' },
  71 + },
  72 + pagination: false,
  73 + });
  74 +
  75 + function handleEdit(record: EditRecordRow) {
  76 + record.editable = true;
  77 + }
  78 +
  79 + function handleCancel(record: EditRecordRow) {
  80 + record.editable = false;
  81 + record.onCancel && record.onCancel();
  82 + if (record.isNew) {
  83 + const data = getDataSource();
  84 + const index = data.findIndex((item) => item.key === record.key);
  85 + data.splice(index, 1);
  86 + }
  87 + }
  88 +
  89 + function handleSave(record: EditRecordRow) {
  90 + record.editable = false;
  91 + record.onSubmit && record.onSubmit();
  92 + }
  93 +
  94 + function handleAdd() {
  95 + const data = getDataSource();
  96 + const addRow: EditRecordRow = {
  97 + name: '',
  98 + no: '',
  99 + dept: '',
  100 + editable: true,
  101 + isNew: true,
  102 + };
  103 + data.push(addRow);
  104 + }
  105 +
  106 + function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
  107 + if (!record.editable) {
  108 + return [
  109 + {
  110 + label: '编辑',
  111 + onClick: handleEdit.bind(null, record),
  112 + },
  113 + {
  114 + label: '删除',
  115 + },
  116 + ];
  117 + }
  118 + return [
  119 + {
  120 + label: '保存',
  121 + onClick: handleSave.bind(null, record, column),
  122 + },
  123 + {
  124 + label: '取消',
  125 + popConfirm: {
  126 + title: '是否取消编辑',
  127 + confirm: handleCancel.bind(null, record, column),
  128 + },
  129 + },
  130 + ];
  131 + }
  132 +
  133 + return {
  134 + registerTable,
  135 + handleEdit,
  136 + createActions,
  137 + handleAdd,
  138 + getDataSource,
  139 + };
  140 + },
  141 + });
  142 +</script>
... ...
src/views/demo/page/form/high/data.ts 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +
  3 +const basicOptions: SelectOptions = [
  4 + {
  5 + label: '付晓晓',
  6 + value: '1',
  7 + },
  8 + {
  9 + label: '周毛毛',
  10 + value: '2',
  11 + },
  12 +];
  13 +
  14 +const storeTypeOptions: SelectOptions = [
  15 + {
  16 + label: '私密',
  17 + value: '1',
  18 + },
  19 + {
  20 + label: '公开',
  21 + value: '2',
  22 + },
  23 +];
  24 +
  25 +export const schemas: FormSchema[] = [
  26 + {
  27 + field: 'f1',
  28 + component: 'Input',
  29 + label: '仓库名',
  30 + required: true,
  31 + },
  32 + {
  33 + field: 'f2',
  34 + component: 'Input',
  35 + label: '仓库域名',
  36 + required: true,
  37 + componentProps: {
  38 + addonBefore: 'http://',
  39 + addonAfter: 'com',
  40 + },
  41 + colProps: {
  42 + offset: 2,
  43 + },
  44 + },
  45 + {
  46 + field: 'f3',
  47 + component: 'Select',
  48 + label: '仓库管理员',
  49 + componentProps: {
  50 + options: basicOptions,
  51 + },
  52 + required: true,
  53 + colProps: {
  54 + offset: 2,
  55 + },
  56 + },
  57 + {
  58 + field: 'f4',
  59 + component: 'Select',
  60 + label: '审批人',
  61 + componentProps: {
  62 + options: basicOptions,
  63 + },
  64 + required: true,
  65 + },
  66 + {
  67 + field: 'f5',
  68 + component: 'RangePicker',
  69 + label: '生效日期',
  70 + required: true,
  71 + colProps: {
  72 + offset: 2,
  73 + },
  74 + },
  75 + {
  76 + field: 'f6',
  77 + component: 'Select',
  78 + label: '仓库类型',
  79 + componentProps: {
  80 + options: storeTypeOptions,
  81 + },
  82 + required: true,
  83 + colProps: {
  84 + offset: 2,
  85 + },
  86 + },
  87 +];
  88 +export const taskSchemas: FormSchema[] = [
  89 + {
  90 + field: 't1',
  91 + component: 'Input',
  92 + label: '任务名',
  93 + required: true,
  94 + },
  95 + {
  96 + field: 't2',
  97 + component: 'Input',
  98 + label: '任务描述',
  99 + required: true,
  100 + colProps: {
  101 + offset: 2,
  102 + },
  103 + },
  104 + {
  105 + field: 't3',
  106 + component: 'Select',
  107 + label: '执行人',
  108 + componentProps: {
  109 + options: basicOptions,
  110 + },
  111 + required: true,
  112 + colProps: {
  113 + offset: 2,
  114 + },
  115 + },
  116 + {
  117 + field: 't4',
  118 + component: 'Select',
  119 + label: '责任人',
  120 + componentProps: {
  121 + options: basicOptions,
  122 + },
  123 + required: true,
  124 + },
  125 + {
  126 + field: 't5',
  127 + component: 'TimePicker',
  128 + label: '生效日期',
  129 + required: true,
  130 + componentProps: {
  131 + style: { width: '100%' },
  132 + },
  133 + colProps: {
  134 + offset: 2,
  135 + },
  136 + },
  137 + {
  138 + field: 't6',
  139 + component: 'Select',
  140 + label: '任务类型',
  141 + componentProps: {
  142 + options: storeTypeOptions,
  143 + },
  144 + required: true,
  145 + colProps: {
  146 + offset: 2,
  147 + },
  148 + },
  149 +];
... ...
src/views/demo/page/form/high/index.vue 0 → 100644
  1 +<template>
  2 + <div class="high-form">
  3 + <a-page-header title="高级表单" :ghost="false">
  4 + 高级表单常见于一次性输入和提交大批量数据的场景。
  5 + </a-page-header>
  6 +
  7 + <div class="m-5">
  8 + <a-card title="仓库管理" :bordered="false">
  9 + <BasicForm @register="register" layout="vertical" />
  10 + </a-card>
  11 + <a-card title="任务管理" :bordered="false" class="mt-5">
  12 + <BasicForm @register="registerTask" layout="vertical" />
  13 + </a-card>
  14 + <a-card title="成员管理" :bordered="false" class="mt-5">
  15 + <PersonTable ref="tableRef" />
  16 + </a-card>
  17 + </div>
  18 +
  19 + <app-footer>
  20 + <template #right>
  21 + <a-button type="primary" @click="submitAll">提交</a-button>
  22 + </template>
  23 + </app-footer>
  24 + </div>
  25 +</template>
  26 +<script lang="ts">
  27 + import { BasicForm, useForm } from '/@/components/Form';
  28 + import { defineComponent, ref } from 'vue';
  29 + import PersonTable from './PersonTable.vue';
  30 + import { schemas, taskSchemas } from './data';
  31 +
  32 + export default defineComponent({
  33 + components: { BasicForm, PersonTable },
  34 + setup() {
  35 + const tableRef = ref<{ getDataSource: () => any } | null>(null);
  36 +
  37 + const [register, { validate }] = useForm({
  38 + baseColProps: {
  39 + span: 6,
  40 + },
  41 + schemas: schemas,
  42 + showActionButtonGroup: false,
  43 + });
  44 +
  45 + const [registerTask, { validate: validateTaskForm }] = useForm({
  46 + baseColProps: {
  47 + span: 6,
  48 + },
  49 + schemas: taskSchemas,
  50 + showActionButtonGroup: false,
  51 + });
  52 +
  53 + async function submitAll() {
  54 + try {
  55 + if (tableRef.value) {
  56 + console.log('table data:', tableRef.value.getDataSource());
  57 + }
  58 +
  59 + const [values, taskValues] = await Promise.all([validate(), validateTaskForm()]);
  60 + console.log('form data:', values, taskValues);
  61 + } catch (error) {}
  62 + }
  63 +
  64 + return { register, registerTask, submitAll, tableRef };
  65 + },
  66 + });
  67 +</script>
  68 +<style lang="less" scoped>
  69 + .high-form {
  70 + padding-bottom: 48px;
  71 + }
  72 +</style>
... ...
src/views/demo/page/form/step/Step1.vue 0 → 100644
  1 +<template>
  2 + <div class="step1">
  3 + <div class="step1-form">
  4 + <BasicForm @register="register">
  5 + <template #fac="{ model, field }">
  6 + <a-input-group compact>
  7 + <a-select v-model:value="model['pay']" class="pay-select">
  8 + <a-select-option value="zfb"> 支付宝 </a-select-option>
  9 + <a-select-option value="yl"> 银联 </a-select-option>
  10 + </a-select>
  11 + <a-input class="pay-input" v-model:value="model[field]" />
  12 + </a-input-group>
  13 + </template>
  14 + </BasicForm>
  15 + </div>
  16 + <a-divider />
  17 + <h3>说明</h3>
  18 + <h4>转账到支付宝账户</h4>
  19 + <p>
  20 + 如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。
  21 + </p>
  22 +
  23 + <h4>转账到银行卡</h4>
  24 + <p>
  25 + 如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。
  26 + </p>
  27 + </div>
  28 +</template>
  29 +<script lang="ts">
  30 + import { defineComponent } from 'vue';
  31 + import { BasicForm, useForm } from '/@/components/Form';
  32 + import { step1Schemas } from './data';
  33 +
  34 + export default defineComponent({
  35 + components: { BasicForm },
  36 + emits: ['next'],
  37 + setup(_, { emit }) {
  38 + const [register, { validate }] = useForm({
  39 + labelWidth: 100,
  40 + schemas: step1Schemas,
  41 + actionColOptions: {
  42 + span: 14,
  43 + },
  44 + showResetButton: false,
  45 + submitButtonOptions: {
  46 + text: '下一步',
  47 + },
  48 + submitFunc: customSubmitFunc,
  49 + });
  50 +
  51 + async function customSubmitFunc() {
  52 + try {
  53 + const values = await validate();
  54 + emit('next', values);
  55 + } catch (error) {}
  56 + }
  57 +
  58 + return { register };
  59 + },
  60 + });
  61 +</script>
  62 +<style lang="less" scoped>
  63 + .step1 {
  64 + &-form {
  65 + width: 450px;
  66 + margin: 0 auto;
  67 + }
  68 +
  69 + h3 {
  70 + margin: 0 0 12px;
  71 + font-size: 16px;
  72 + line-height: 32px;
  73 + color: rgba(0, 0, 0, 0.45);
  74 + }
  75 +
  76 + h4 {
  77 + margin: 0 0 4px;
  78 + font-size: 14px;
  79 + line-height: 22px;
  80 + color: rgba(0, 0, 0, 0.45);
  81 + }
  82 +
  83 + p {
  84 + color: rgba(0, 0, 0, 0.45);
  85 + }
  86 + }
  87 +
  88 + .pay-select {
  89 + width: 20%;
  90 + }
  91 +
  92 + .pay-input {
  93 + width: 70%;
  94 + }
  95 +</style>
... ...
src/views/demo/page/form/step/Step2.vue 0 → 100644
  1 +<template>
  2 + <div class="step2">
  3 + <a-alert message="确认转账后,资金将直接打入对方账户,无法退回。" show-icon />
  4 + <a-descriptions :column="1" class="mt-5">
  5 + <a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
  6 + <a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
  7 + <a-descriptions-item label="收款人姓名"> Vben </a-descriptions-item>
  8 + <a-descriptions-item label="转账金额"> 500元 </a-descriptions-item>
  9 + </a-descriptions>
  10 + <a-divider />
  11 + <BasicForm @register="register" />
  12 + </div>
  13 +</template>
  14 +<script lang="ts">
  15 + import { defineComponent } from 'vue';
  16 + import { BasicForm, useForm } from '/@/components/Form';
  17 + import { step2Schemas } from './data';
  18 +
  19 + export default defineComponent({
  20 + components: { BasicForm },
  21 + emits: ['next', 'prev'],
  22 + setup(_, { emit }) {
  23 + const [register, { validate, setProps }] = useForm({
  24 + labelWidth: 80,
  25 + schemas: step2Schemas,
  26 + actionColOptions: {
  27 + span: 14,
  28 + },
  29 + resetButtonOptions: {
  30 + text: '上一步',
  31 + },
  32 + submitButtonOptions: {
  33 + text: '提交',
  34 + },
  35 + resetFunc: customResetFunc,
  36 + submitFunc: customSubmitFunc,
  37 + });
  38 +
  39 + async function customResetFunc() {
  40 + emit('prev');
  41 + }
  42 +
  43 + async function customSubmitFunc() {
  44 + try {
  45 + const values = await validate();
  46 + setProps({
  47 + submitButtonOptions: {
  48 + loading: true,
  49 + },
  50 + });
  51 + setTimeout(() => {
  52 + setProps({
  53 + submitButtonOptions: {
  54 + loading: false,
  55 + },
  56 + });
  57 + emit('next', values);
  58 + }, 1500);
  59 + } catch (error) {}
  60 + }
  61 +
  62 + return { register };
  63 + },
  64 + });
  65 +</script>
  66 +<style lang="less" scoped>
  67 + .step2 {
  68 + width: 450px;
  69 + margin: 0 auto;
  70 + }
  71 +</style>
... ...
src/views/demo/page/form/step/Step3.vue 0 → 100644
  1 +<template>
  2 + <div class="step3">
  3 + <a-result status="success" title="操作成功" sub-title="预计两小时内到账">
  4 + <template #extra>
  5 + <a-button type="primary" @click="redo">再转一笔 </a-button>
  6 + <a-button> 查看账单 </a-button>
  7 + </template>
  8 + </a-result>
  9 + <div class="desc-wrap">
  10 + <a-descriptions :column="1" class="mt-5">
  11 + <a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
  12 + <a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
  13 + <a-descriptions-item label="收款人姓名"> Vben </a-descriptions-item>
  14 + <a-descriptions-item label="转账金额"> 500元 </a-descriptions-item>
  15 + </a-descriptions>
  16 + </div>
  17 + </div>
  18 +</template>
  19 +<script lang="ts">
  20 + import { defineComponent } from 'vue';
  21 +
  22 + export default defineComponent({
  23 + components: {},
  24 + emits: ['redo'],
  25 + setup(_, { emit }) {
  26 + return {
  27 + redo: () => {
  28 + emit('redo');
  29 + },
  30 + };
  31 + },
  32 + });
  33 +</script>
  34 +<style lang="less" scoped>
  35 + .step3 {
  36 + width: 600px;
  37 + margin: 0 auto;
  38 + }
  39 +
  40 + .desc-wrap {
  41 + padding: 24px 40px;
  42 + margin-top: 24px;
  43 + background: #fafafa;
  44 + }
  45 +</style>
... ...
src/views/demo/page/form/step/data.tsx 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +
  3 +export const step1Schemas: FormSchema[] = [
  4 + {
  5 + field: 'account',
  6 + component: 'Select',
  7 + label: '付款账户',
  8 + required: true,
  9 + defaultValue: '1',
  10 + componentProps: {
  11 + options: [
  12 + {
  13 + label: 'anncwb@126.com',
  14 + value: '1',
  15 + },
  16 + ],
  17 + },
  18 + },
  19 + {
  20 + field: 'fac',
  21 + component: 'InputGroup',
  22 + label: '收款账户',
  23 + required: true,
  24 + defaultValue: 'test@example.com',
  25 + slot: 'fac',
  26 + },
  27 + {
  28 + field: 'pay',
  29 + component: 'Input',
  30 + label: '',
  31 + defaultValue: 'zfb',
  32 + show: false,
  33 + },
  34 + {
  35 + field: 'payeeName',
  36 + component: 'Input',
  37 + label: '收款人姓名',
  38 + defaultValue: 'Vben',
  39 + required: true,
  40 + },
  41 + {
  42 + field: 'money',
  43 + component: 'Input',
  44 + label: '转账金额',
  45 + defaultValue: '500',
  46 + required: true,
  47 + renderComponentContent: () => {
  48 + return {
  49 + prefix: () => '¥',
  50 + };
  51 + },
  52 + },
  53 +];
  54 +
  55 +export const step2Schemas: FormSchema[] = [
  56 + {
  57 + field: 'pwd',
  58 + component: 'InputPassword',
  59 + label: '支付密码',
  60 + required: true,
  61 + defaultValue: '123456',
  62 + },
  63 +];
... ...
src/views/demo/page/form/step/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <a-page-header title="分步表单" :ghost="false">
  4 + 将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。
  5 + </a-page-header>
  6 +
  7 + <div class="m-5 step-form-content">
  8 + <div class="step-form-form">
  9 + <a-steps :current="current">
  10 + <a-step title="填写转账信息"> </a-step>
  11 + <a-step title="确认转账信息"> </a-step>
  12 + <a-step title="完成"> </a-step>
  13 + </a-steps>
  14 + </div>
  15 + <div class="mt-5">
  16 + <Step1 @next="handleStep1Next" v-show="current === 0" />
  17 + <Step2
  18 + @prev="handleStepPrev"
  19 + @next="handleStep2Next"
  20 + v-show="current === 1"
  21 + v-if="initSetp2"
  22 + />
  23 + <Step3 v-show="current === 2" @redo="handleRedo" v-if="initSetp3" />
  24 + </div>
  25 + </div>
  26 + </div>
  27 +</template>
  28 +<script lang="ts">
  29 + import { defineComponent, ref, reactive, toRefs } from 'vue';
  30 + import Step1 from './Step1.vue';
  31 + import Step2 from './Step2.vue';
  32 + import Step3 from './Step3.vue';
  33 + export default defineComponent({
  34 + components: { Step1, Step2, Step3 },
  35 + setup() {
  36 + const current = ref(0);
  37 +
  38 + const state = reactive({
  39 + initSetp2: false,
  40 + initSetp3: false,
  41 + });
  42 +
  43 + function handleStep1Next(step1Values: any) {
  44 + current.value++;
  45 + state.initSetp2 = true;
  46 + console.log(step1Values);
  47 + }
  48 +
  49 + function handleStepPrev() {
  50 + current.value--;
  51 + }
  52 +
  53 + function handleStep2Next(step2Values: any) {
  54 + current.value++;
  55 + state.initSetp3 = true;
  56 + console.log(step2Values);
  57 + }
  58 +
  59 + function handleRedo() {
  60 + current.value = 0;
  61 + state.initSetp2 = false;
  62 + state.initSetp3 = false;
  63 + }
  64 +
  65 + return {
  66 + current,
  67 + handleStep1Next,
  68 + handleStep2Next,
  69 + handleRedo,
  70 + handleStepPrev,
  71 + ...toRefs(state),
  72 + };
  73 + },
  74 + });
  75 +</script>
  76 +<style lang="less" scoped>
  77 + .step-form-content {
  78 + padding: 24px;
  79 + background: #fff;
  80 + }
  81 +
  82 + .step-form-form {
  83 + width: 750px;
  84 + margin: 0 auto;
  85 + }
  86 +</style>
... ...
src/views/demo/table/EditRowTable.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4">
  3 + <BasicTable @register="registerTable">
  4 + <template #action="{ record, column }">
  5 + <TableAction :actions="createActions(record, column)" />
  6 + </template>
  7 + </BasicTable>
  8 + </div>
  9 +</template>
  10 +<script lang="ts">
  11 + import { defineComponent, ref } from 'vue';
  12 + import {
  13 + BasicTable,
  14 + useTable,
  15 + TableAction,
  16 + BasicColumn,
  17 + ActionItem,
  18 + renderEditableRow,
  19 + EditTableHeaderIcon,
  20 + EditRecordRow,
  21 + } from '/@/components/Table';
  22 +
  23 + import { demoListApi } from '/@/api/demo/table';
  24 + const columns: BasicColumn[] = [
  25 + {
  26 + title: 'ID',
  27 + dataIndex: 'id',
  28 + customRender: renderEditableRow({ dataIndex: 'id' }),
  29 + },
  30 + {
  31 + title: '姓名',
  32 + dataIndex: 'name',
  33 + customRender: renderEditableRow({
  34 + dataIndex: 'name',
  35 + }),
  36 + },
  37 + ];
  38 + export default defineComponent({
  39 + components: { BasicTable, EditTableHeaderIcon, TableAction },
  40 + setup() {
  41 + const currentEditKeyRef = ref('');
  42 +
  43 + const [registerTable] = useTable({
  44 + title: '可编辑行示例',
  45 + api: demoListApi,
  46 + columns: columns,
  47 + showIndexColumn: false,
  48 + actionColumn: {
  49 + width: 160,
  50 + title: 'Action',
  51 + dataIndex: 'action',
  52 + slots: { customRender: 'action' },
  53 + },
  54 + });
  55 +
  56 + function handleEdit(record: EditRecordRow) {
  57 + currentEditKeyRef.value = record.key;
  58 + record.editable = true;
  59 + }
  60 +
  61 + function handleCancel(record: EditRecordRow) {
  62 + currentEditKeyRef.value = '';
  63 + record.editable = false;
  64 + record.onCancel && record.onCancel();
  65 + }
  66 +
  67 + function handleSave(record: EditRecordRow) {
  68 + currentEditKeyRef.value = '';
  69 + record.editable = false;
  70 + record.onSubmit && record.onSubmit();
  71 + }
  72 +
  73 + function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
  74 + if (!record.editable) {
  75 + return [
  76 + {
  77 + label: '编辑',
  78 + disabled: currentEditKeyRef.value ? currentEditKeyRef.value !== record.key : false,
  79 + onClick: handleEdit.bind(null, record),
  80 + },
  81 + ];
  82 + }
  83 + return [
  84 + {
  85 + label: '保存',
  86 + onClick: handleSave.bind(null, record, column),
  87 + },
  88 + {
  89 + label: '取消',
  90 + popConfirm: {
  91 + title: '是否取消编辑',
  92 + confirm: handleCancel.bind(null, record, column),
  93 + },
  94 + },
  95 + ];
  96 + }
  97 +
  98 + return {
  99 + registerTable,
  100 + handleEdit,
  101 + createActions,
  102 + };
  103 + },
  104 + });
  105 +</script>
... ...
src/views/demo/table/FixedColumn.vue
1 1 <template>
2 2 <div class="p-4">
3 3 <BasicTable @register="registerTable">
4   - <template #action>
  4 + <template #action="{ record }">
5 5 <TableAction
6 6 :actions="[
7 7 {
8 8 label: '删除',
9   - onClick: handleDelete,
  9 + onClick: handleDelete.bind(null, record),
10 10 },
11 11 ]"
12 12 :dropDownActions="[
13 13 {
14 14 label: '启用',
15   - onClick: handleOpen,
  15 + onClick: handleOpen.bind(null, record),
16 16 },
17 17 ]"
18 18 />
... ... @@ -73,11 +73,11 @@
73 73 slots: { customRender: 'action' },
74 74 },
75 75 });
76   - function handleDelete() {
77   - console.log('点击了删除');
  76 + function handleDelete(record: any) {
  77 + console.log('点击了删除', record);
78 78 }
79   - function handleOpen() {
80   - console.log('点击了启用');
  79 + function handleOpen(record: any) {
  80 + console.log('点击了启用', record);
81 81 }
82 82 return {
83 83 registerTable,
... ...
yarn.lock
... ... @@ -1051,9 +1051,9 @@
1051 1051 integrity sha512-BybEHU5/I9EQ0CcwKAqmreZ2bMnAXrqLCTptAc6vPetHMbrXdZfejP5mt57e/8PNSt/qE7BHniU5PCYA+PGIHw==
1052 1052  
1053 1053 "@iconify/json@^1.1.258":
1054   - version "1.1.258"
1055   - resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.258.tgz#392064ae8fd4c6d542c21bb4d0d57d5860f38abb"
1056   - integrity sha512-x5DKhRrg8v1NWmClWa8zA80gWQ9xevivsUAF4s8CyAl/ZplBsEE1funKuuVcIKjexyE1UXb7uFWrUKt1fB5n1A==
  1054 + version "1.1.259"
  1055 + resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.259.tgz#433ccff8572e42c3abab1cdbac872af0e8340419"
  1056 + integrity sha512-tDL4IgKtj3LA2lI+IoZfylBtKWNpV5I9BLj7WGMI/SvGkkYo+9DUap3Ho6iUbQLtu9GmHwpE/cA8mwEBkj/otw==
1057 1057  
1058 1058 "@koa/cors@^3.1.0":
1059 1059 version "3.1.0"
... ... @@ -1236,9 +1236,9 @@
1236 1236 unist-util-find-all-after "^3.0.1"
1237 1237  
1238 1238 "@surma/rollup-plugin-off-main-thread@^1.1.1":
1239   - version "1.4.1"
1240   - resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.1.tgz#bf1343e5a926e5a1da55e3affd761dda4ce143ef"
1241   - integrity sha512-ZPBWYQDdO4JZiTmTP3DABsHhIPA7bEJk9Znk7tZsrbPGanoGo8YxMv//WLx5Cvb+lRgS42+6yiOIYYHCKDmkpQ==
  1239 + version "1.4.2"
  1240 + resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz#e6786b6af5799f82f7ab3a82e53f6182d2b91a58"
  1241 + integrity sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==
1242 1242 dependencies:
1243 1243 ejs "^2.6.1"
1244 1244 magic-string "^0.25.0"
... ... @@ -1850,7 +1850,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
1850 1850 dependencies:
1851 1851 color-convert "^2.0.1"
1852 1852  
1853   -ant-design-vue@^2.0.0-rc.1:
  1853 +ant-design-vue@^2.0.0-beta.15:
1854 1854 version "2.0.0-rc.1"
1855 1855 resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-rc.1.tgz#2ef02475f3aa4c1474f2fe3cf44a52c34787be02"
1856 1856 integrity sha512-iKXkFtTHarvLHV7LWmYh6g/Cmkv+xK+vS621A1Qvg37Z6lCGg3K9BGAizmklAYzOTiPz0Ltt63eSiNqYMGh52g==
... ... @@ -1982,9 +1982,9 @@ astral-regex@^2.0.0:
1982 1982 integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
1983 1983  
1984 1984 async-validator@^3.3.0, async-validator@^3.4.0:
1985   - version "3.4.0"
1986   - resolved "https://registry.npmjs.org/async-validator/-/async-validator-3.4.0.tgz#871b3e594124bf4c4eb7bcd1a9e78b44f3b09cae"
1987   - integrity sha512-VrFk4eYiJAWKskEz115iiuCf9O0ftnMMPXrOFMqyzGH2KxO7YwncKyn/FgOOP+0MDHMfXL7gLExagCutaZGigA==
  1985 + version "3.5.0"
  1986 + resolved "https://registry.npmjs.org/async-validator/-/async-validator-3.5.0.tgz#f6791ee7217cde8036941591bc3754f7c26bbf89"
  1987 + integrity sha512-jMDcDHrH618eznoO4/3afJG5+I4HE/ipQd7y4mhPJmCaoHCSPOJfjpWgjFoxma2h8irL+zGe+qwyptDrR37Vhg==
1988 1988  
1989 1989 async@^2.6.2:
1990 1990 version "2.6.3"
... ... @@ -2079,9 +2079,9 @@ balanced-match@^1.0.0:
2079 2079 integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
2080 2080  
2081 2081 base64-js@^1.3.1:
2082   - version "1.5.0"
2083   - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.0.tgz#2d03045876d9e2b68a7a0f87d6bd163595e3b6af"
2084   - integrity sha512-Jrdy04F2EKcNggUDfubMUPNAZg2vMquLQSm8sKLYJvz40ClFL1S8GKyDshGkNsbNNE5Z+fQavzU7nSK1I9JUGA==
  2082 + version "1.5.1"
  2083 + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
  2084 + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
2085 2085  
2086 2086 base@^0.11.1:
2087 2087 version "0.11.2"
... ... @@ -2297,9 +2297,9 @@ camelcase@^5.0.0, camelcase@^5.3.1:
2297 2297 integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
2298 2298  
2299 2299 caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157:
2300   - version "1.0.30001157"
2301   - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz#2d11aaeb239b340bc1aa730eca18a37fdb07a9ab"
2302   - integrity sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==
  2300 + version "1.0.30001158"
  2301 + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001158.tgz#fce86d321369603c2bc855ee0e901a7f49f8310b"
  2302 + integrity sha512-s5loVYY+yKpuVA3HyW8BarzrtJvwHReuzugQXlv1iR3LKSReoFXRm86mT6hT7PEF5RxW+XQZg+6nYjlywYzQ+g==
2303 2303  
2304 2304 ccount@^1.0.0:
2305 2305 version "1.1.0"
... ... @@ -2940,9 +2940,9 @@ cssesc@^3.0.0:
2940 2940 integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
2941 2941  
2942 2942 csstype@^2.6.8:
2943   - version "2.6.13"
2944   - resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f"
2945   - integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==
  2943 + version "2.6.14"
  2944 + resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.14.tgz#004822a4050345b55ad4dcc00be1d9cf2f4296de"
  2945 + integrity sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A==
2946 2946  
2947 2947 currently-unhandled@^0.4.1:
2948 2948 version "0.4.1"
... ... @@ -3263,9 +3263,9 @@ ejs@^2.6.1:
3263 3263 integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
3264 3264  
3265 3265 electron-to-chromium@^1.3.591:
3266   - version "1.3.592"
3267   - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.592.tgz#4621521b223bf6e5469373528321e185d3c24670"
3268   - integrity sha512-kGNowksvqQiPb1pUSQKpd8JFoGPLxYOwduNRCqCxGh/2Q1qE2JdmwouCW41lUzDxOb/2RIV4lR0tVIfboWlO9A==
  3266 + version "1.3.596"
  3267 + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.596.tgz#c7ed98512c7ff36ddcbfed9e54e6355335c35257"
  3268 + integrity sha512-nLO2Wd2yU42eSoNJVQKNf89CcEGqeFZd++QsnN2XIgje1s/19AgctfjLIbPORlvcCO8sYjLwX4iUgDdusOY8Sg==
3269 3269  
3270 3270 emoji-regex@^7.0.1:
3271 3271 version "7.0.3"
... ... @@ -6931,9 +6931,9 @@ rollup@^1.31.1:
6931 6931 acorn "^7.1.0"
6932 6932  
6933 6933 rollup@^2.32.1:
6934   - version "2.33.1"
6935   - resolved "https://registry.npmjs.org/rollup/-/rollup-2.33.1.tgz#802795164164ee63cd47769d8879c33ec8ae0c40"
6936   - integrity sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==
  6934 + version "2.33.2"
  6935 + resolved "https://registry.npmjs.org/rollup/-/rollup-2.33.2.tgz#c4c76cd405a7605e6ebe90976398c46d4c2ea166"
  6936 + integrity sha512-QPQ6/fWCrzHtSXkI269rhKaC7qXGghYBwXU04b1JsDZ6ibZa3DJ9D1SFAYRMgx1inDg0DaTbb3N4Z1NK/r3fhw==
6937 6937 optionalDependencies:
6938 6938 fsevents "~2.1.2"
6939 6939  
... ... @@ -7874,9 +7874,9 @@ type-fest@^0.13.1:
7874 7874 integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
7875 7875  
7876 7876 type-fest@^0.18.0:
7877   - version "0.18.0"
7878   - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.18.0.tgz#2edfa6382d48653707344f7fccdb0443d460e8d6"
7879   - integrity sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ==
  7877 + version "0.18.1"
  7878 + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
  7879 + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
7880 7880  
7881 7881 type-fest@^0.3.1:
7882 7882 version "0.3.1"
... ... @@ -7919,9 +7919,9 @@ typescript@^4.0.5:
7919 7919 integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
7920 7920  
7921 7921 uglify-js@^3.1.4:
7922   - version "3.11.5"
7923   - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz#d6788bc83cf35ff18ea78a65763e480803409bc6"
7924   - integrity sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w==
  7922 + version "3.11.6"
  7923 + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.6.tgz#144b50d3e05eadd3ad4dd047c60ca541a8cd4e9c"
  7924 + integrity sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g==
7925 7925  
7926 7926 unherit@^1.0.4:
7927 7927 version "1.1.3"
... ... @@ -8581,7 +8581,7 @@ y18n@^4.0.0:
8581 8581 resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
8582 8582 integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
8583 8583  
8584   -y18n@^5.0.2:
  8584 +y18n@^5.0.5:
8585 8585 version "5.0.5"
8586 8586 resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
8587 8587 integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==
... ... @@ -8656,16 +8656,16 @@ yargs@^15.0.0, yargs@^15.1.0:
8656 8656 yargs-parser "^18.1.2"
8657 8657  
8658 8658 yargs@^16.0.3, yargs@^16.1.0:
8659   - version "16.1.0"
8660   - resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz#fc333fe4791660eace5a894b39d42f851cd48f2a"
8661   - integrity sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==
  8659 + version "16.1.1"
  8660 + resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1"
  8661 + integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==
8662 8662 dependencies:
8663 8663 cliui "^7.0.2"
8664 8664 escalade "^3.1.1"
8665 8665 get-caller-file "^2.0.5"
8666 8666 require-directory "^2.1.1"
8667 8667 string-width "^4.2.0"
8668   - y18n "^5.0.2"
  8668 + y18n "^5.0.5"
8669 8669 yargs-parser "^20.2.2"
8670 8670  
8671 8671 ylru@^1.2.0:
... ...