放舱通道配置

main
张同海 3 months ago
parent 10f92a1a8b
commit 40c0fc7746

@ -54,6 +54,10 @@ enum Api {
getEnum = '/adminApi/Common/GetSysEnumSelect',
getInfoClientSelect = '/adminApi/Common/GetInfoClientSelect',
// 港口下拉数据
GetClientPortSelectList = '/adminApi/Common/GetPortSelectList',
// 船公司下拉数据
GetCarrierSelectList = '/adminApi/Common/GetCarrierSelectList',
}
export function getInfoClientSelect(query: { code: string }) {
return request<DataResult>({
@ -142,9 +146,9 @@ export function UserRefreshToken(data) {
return request<DataResult<CurrentUserViewModel>>({
url: Api.UserRefreshToken,
method: 'get',
headers:{
RefreshToken:data.refreshToken
}
headers: {
RefreshToken: data.refreshToken,
},
})
}
export function userLogout() {
@ -284,7 +288,20 @@ export function changePassword(data: any) {
data,
})
}
// 港口下拉数据列表
export function GetClientPortSelectList() {
return request<DataResult>({
url: Api.GetClientPortSelectList,
method: 'get',
})
}
// 船公司下拉
export function GetCarrierSelectList() {
return request<DataResult>({
url: Api.GetCarrierSelectList,
method: 'get',
})
}
/**
* api
*/

@ -1,18 +1,18 @@
<script lang="tsx">
import type { PropType, Ref } from 'vue';
import { computed, defineComponent, toRefs, unref } from 'vue';
import type { FormActionType, FormProps, FormSchema } from '../types/form';
import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
import type { TableActionType } from '/@/components/Table';
import { Col, Divider, Form } from 'ant-design-vue';
import { componentMap } from '../componentMap';
import { BasicHelp } from '/@/components/Basic';
import { isBoolean, isFunction, isNull } from '/@/utils/is';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { createPlaceholderMessage, setComponentRuleType } from '../helper';
import { cloneDeep, upperFirst } from 'lodash-es';
import { useItemLabelWidth } from '../hooks/useLabelWidth';
import { useI18n } from '/@/hooks/web/useI18n';
import type { PropType, Ref } from 'vue'
import { computed, defineComponent, toRefs, unref } from 'vue'
import type { FormActionType, FormProps, FormSchema } from '../types/form'
import type { ValidationRule } from 'ant-design-vue/lib/form/Form'
import type { TableActionType } from '/@/components/Table'
import { Col, Divider, Form } from 'ant-design-vue'
import { componentMap } from '../componentMap'
import { BasicHelp } from '/@/components/Basic'
import { isBoolean, isFunction, isNull } from '/@/utils/is'
import { getSlot } from '/@/utils/helper/tsxHelper'
import { createPlaceholderMessage, setComponentRuleType } from '../helper'
import { cloneDeep, upperFirst } from 'lodash-es'
import { useItemLabelWidth } from '../hooks/useLabelWidth'
import { useI18n } from '/@/hooks/web/useI18n'
export default defineComponent({
name: 'BasicFormItem',
@ -49,18 +49,18 @@
},
},
setup(props, { slots }) {
const { t } = useI18n();
const { t } = useI18n()
const { schema, formProps } = toRefs(props) as {
schema: Ref<FormSchema>;
formProps: Ref<FormProps>;
};
schema: Ref<FormSchema>
formProps: Ref<FormProps>
}
const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
const itemLabelWidthProp = useItemLabelWidth(schema, formProps)
const getValues = computed(() => {
const { allDefaultValues, formModel, schema } = props;
const { mergeDynamicData } = props.formProps;
const { allDefaultValues, formModel, schema } = props
const { mergeDynamicData } = props.formProps
return {
field: schema.field,
model: formModel,
@ -70,64 +70,64 @@
...formModel,
} as Recordable,
schema: schema,
};
});
}
})
const getComponentsProps = computed(() => {
const { schema, tableAction, formModel, formActionType } = props;
let { componentProps = {} } = schema;
const { schema, tableAction, formModel, formActionType } = props
let { componentProps = {} } = schema
if (isFunction(componentProps)) {
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {}
}
if (schema.component === 'Divider') {
componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
orientation: 'left',
plain: true,
});
})
}
return componentProps as Recordable;
});
return componentProps as Recordable
})
const getDisable = computed(() => {
const { disabled: globDisabled } = props.formProps;
const { dynamicDisabled } = props.schema;
const { disabled: itemDisabled = false } = unref(getComponentsProps);
let disabled = !!globDisabled || itemDisabled;
const { disabled: globDisabled } = props.formProps
const { dynamicDisabled } = props.schema
const { disabled: itemDisabled = false } = unref(getComponentsProps)
let disabled = !!globDisabled || itemDisabled
if (isBoolean(dynamicDisabled)) {
disabled = dynamicDisabled;
disabled = dynamicDisabled
}
if (isFunction(dynamicDisabled)) {
disabled = dynamicDisabled(unref(getValues));
disabled = dynamicDisabled(unref(getValues))
}
return disabled;
});
return disabled
})
function getShow(): { isShow: boolean; isIfShow: boolean } {
const { show, ifShow } = props.schema;
const { showAdvancedButton } = props.formProps;
const { show, ifShow } = props.schema
const { showAdvancedButton } = props.formProps
const itemIsAdvanced = showAdvancedButton
? isBoolean(props.isAdvanced)
? props.isAdvanced
: true
: true;
: true
let isShow = true;
let isIfShow = true;
let isShow = true
let isIfShow = true
if (isBoolean(show)) {
isShow = show;
isShow = show
}
if (isBoolean(ifShow)) {
isIfShow = ifShow;
isIfShow = ifShow
}
if (isFunction(show)) {
isShow = show(unref(getValues));
isShow = show(unref(getValues))
}
if (isFunction(ifShow)) {
isIfShow = ifShow(unref(getValues));
isIfShow = ifShow(unref(getValues))
}
isShow = isShow && itemIsAdvanced;
return { isShow, isIfShow };
isShow = isShow && itemIsAdvanced
return { isShow, isIfShow }
}
function handleRules(): ValidationRule[] {
@ -138,31 +138,31 @@
label,
dynamicRules,
required,
} = props.schema;
} = props.schema
if (isFunction(dynamicRules)) {
return dynamicRules(unref(getValues)) as ValidationRule[];
return dynamicRules(unref(getValues)) as ValidationRule[]
}
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]
const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps
const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
? rulesMessageJoinLabel
: globalRulesMessageJoinLabel;
const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
: globalRulesMessageJoinLabel
const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`
function validator(rule: any, value: any) {
const msg = rule.message || defaultMsg;
const msg = rule.message || defaultMsg
if (value === undefined || isNull(value)) {
//
return Promise.reject(msg);
return Promise.reject(msg)
} else if (Array.isArray(value) && value.length === 0) {
//
return Promise.reject(msg);
return Promise.reject(msg)
} else if (typeof value === 'string' && value.trim() === '') {
//
return Promise.reject(msg);
return Promise.reject(msg)
} else if (
typeof value === 'object' &&
Reflect.has(value, 'checked') &&
@ -173,12 +173,12 @@
value.halfChecked.length === 0
) {
// tree
return Promise.reject(msg);
return Promise.reject(msg)
}
return Promise.resolve();
return Promise.resolve()
}
const getRequired = isFunction(required) ? required(unref(getValues)) : required;
const getRequired = isFunction(required) ? required(unref(getValues)) : required
/*
* 1若设置了required属性又没有其他的rules就创建一个验证规则
@ -187,49 +187,49 @@
*/
if (getRequired) {
if (!rules || rules.length === 0) {
rules = [{ required: getRequired, validator }];
rules = [{ required: getRequired, validator }]
} else {
const requiredIndex: number = rules.findIndex((rule) => Reflect.has(rule, 'required'));
const requiredIndex: number = rules.findIndex((rule) => Reflect.has(rule, 'required'))
if (requiredIndex === -1) {
rules.push({ required: getRequired, validator });
rules.push({ required: getRequired, validator })
}
}
}
const requiredRuleIndex: number = rules.findIndex(
(rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator'),
);
)
if (requiredRuleIndex !== -1) {
const rule = rules[requiredRuleIndex];
const { isShow } = getShow();
const rule = rules[requiredRuleIndex]
const { isShow } = getShow()
if (!isShow) {
rule.required = false;
rule.required = false
}
if (component) {
if (!Reflect.has(rule, 'type')) {
rule.type = component === 'InputNumber' ? 'number' : 'string';
rule.type = component === 'InputNumber' ? 'number' : 'string'
}
rule.message = rule.message || defaultMsg;
rule.message = rule.message || defaultMsg
if (component.includes('Input') || component.includes('Textarea')) {
rule.whitespace = true;
rule.whitespace = true
}
const valueFormat = unref(getComponentsProps)?.valueFormat;
setComponentRuleType(rule, component, valueFormat);
const valueFormat = unref(getComponentsProps)?.valueFormat
setComponentRuleType(rule, component, valueFormat)
}
}
// Maximum input length rule check
const characterInx = rules.findIndex((val) => val.max);
const characterInx = rules.findIndex((val) => val.max)
if (characterInx !== -1 && !rules[characterInx].validator) {
rules[characterInx].message =
rules[characterInx].message ||
t('component.form.maxTip', [rules[characterInx].max] as Recordable);
t('component.form.maxTip', [rules[characterInx].max] as Recordable)
}
return rules;
return rules
}
function renderComponent() {
@ -239,109 +239,112 @@
field,
changeEvent = 'change',
valueField,
} = props.schema;
} = props.schema
const isCheck = component && ['Switch', 'Checkbox'].includes(component);
const isCheck = component && ['Switch', 'Checkbox'].includes(component)
const eventKey = `on${upperFirst(changeEvent)}`;
const eventKey = `on${upperFirst(changeEvent)}`
const on = {
[eventKey]: (...args: Nullable<Recordable>[]) => {
const [e] = args;
const [e] = args
if (propsData[eventKey]) {
propsData[eventKey](...args);
propsData[eventKey](...args)
}
const target = e ? e.target : null;
const value = target ? (isCheck ? target.checked : target.value) : e;
props.setFormModel(field, value, props.schema);
const target = e ? e.target : null
const value = target ? (isCheck ? target.checked : target.value) : e
props.setFormModel(field, value, props.schema)
},
};
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;
}
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>
const { autoSetPlaceHolder, size } = props.formProps;
const { autoSetPlaceHolder, size } = props.formProps
const propsData: Recordable = {
allowClear: true,
getPopupContainer: (trigger: Element) => trigger.parentNode,
size,
...unref(getComponentsProps),
disabled: unref(getDisable),
};
}
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder
// RangePicker place is an array
if (isCreatePlaceholder && component !== 'RangePicker' && component) {
propsData.placeholder =
unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component)
}
propsData.codeField = field;
propsData.formValues = unref(getValues);
propsData.codeField = field
propsData.formValues = unref(getValues)
const bindValue: Recordable = {
[valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
};
}
const compAttr: Recordable = {
...propsData,
...on,
...bindValue,
};
...props.schema,
}
if (!renderComponentContent) {
return <Comp {...compAttr} />;
return <Comp {...compAttr} />
}
const compSlot = isFunction(renderComponentContent)
? { ...renderComponentContent(unref(getValues)) }
: {
default: () => renderComponentContent,
};
return <Comp {...compAttr}>{compSlot}</Comp>;
}
return <Comp {...compAttr}>{compSlot}</Comp>
}
function renderLabelHelpMessage() {
const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
const { label, helpMessage, helpComponentProps, subLabel, labelSlot } = props.schema
const renderLabel = subLabel ? (
<span>
{label} <span class="text-secondary">{subLabel}</span>
</span>
) : labelSlot ? (
<span>
{label} {getSlot(slots, labelSlot, unref(getValues))}
</span>
) : (
label
);
const getHelpMessage = isFunction(helpMessage)
? helpMessage(unref(getValues))
: helpMessage;
)
const getHelpMessage = isFunction(helpMessage) ? helpMessage(unref(getValues)) : helpMessage
if (!getHelpMessage || (Array.isArray(getHelpMessage) && getHelpMessage.length === 0)) {
return renderLabel;
return renderLabel
}
return (
<span>
{renderLabel}
<BasicHelp placement="top" class="mx-1" text={getHelpMessage} {...helpComponentProps} />
</span>
);
)
}
function renderItem() {
const { itemProps, slot, render, field, suffix, component } = props.schema;
const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
const { colon } = props.formProps;
const { itemProps, slot, render, field, suffix, component } = props.schema
const { labelCol, wrapperCol } = unref(itemLabelWidthProp)
const { colon } = props.formProps
if (component === 'Divider') {
return (
<Col span={24}>
<Divider {...unref(getComponentsProps)}>{renderLabelHelpMessage()}</Divider>
</Col>
);
)
} else {
const getContent = () => {
return slot
? getSlot(slots, slot, unref(getValues))
: render
? render(unref(getValues))
: renderComponent();
};
: renderComponent()
}
const showSuffix = !!suffix;
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
const showSuffix = !!suffix
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix
return (
<Form.Item
@ -359,28 +362,28 @@
{showSuffix && <span class="suffix">{getSuffix}</span>}
</div>
</Form.Item>
);
)
}
}
return () => {
const { colProps = {}, colSlot, renderColContent, component } = props.schema;
const { colProps = {}, colSlot, renderColContent, component } = props.schema
if (!componentMap.has(component)) {
return null;
return null
}
const { baseColProps = {} } = props.formProps;
const realColProps = { ...baseColProps, ...colProps };
const { isIfShow, isShow } = getShow();
const values = unref(getValues);
const { baseColProps = {} } = props.formProps
const realColProps = { ...baseColProps, ...colProps }
const { isIfShow, isShow } = getShow()
const values = unref(getValues)
const getContent = () => {
return colSlot
? getSlot(slots, colSlot, values)
: renderColContent
? renderColContent(values)
: renderItem();
};
: renderItem()
}
return (
isIfShow && (
@ -388,8 +391,8 @@
{getContent()}
</Col>
)
);
};
)
}
},
});
})
</script>

@ -1,227 +1,235 @@
import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface';
import type { VNode } from 'vue';
import type { ButtonProps as AntdButtonProps } from '/@/components/Button';
import type { FormItem } from './formItem';
import type { ColEx, ComponentType } from './index';
import type { TableActionType } from '/@/components/Table/src/types/table';
import type { CSSProperties } from 'vue';
import type { RowProps } from 'ant-design-vue/lib/grid/Row';
import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface'
import type { VNode } from 'vue'
import type { ButtonProps as AntdButtonProps } from '/@/components/Button'
import type { FormItem } from './formItem'
import type { ColEx, ComponentType } from './index'
import type { TableActionType } from '/@/components/Table/src/types/table'
import type { CSSProperties } from 'vue'
import type { RowProps } from 'ant-design-vue/lib/grid/Row'
export type FieldMapToTime = [string, [string, string], (string | [string, string])?][];
export type FieldMapToTime = [string, [string, string], (string | [string, string])?][]
export type Rule = RuleObject & {
trigger?: 'blur' | 'change' | ['change', 'blur'];
};
trigger?: 'blur' | 'change' | ['change', 'blur']
}
export interface RenderCallbackParams {
schema: FormSchema;
values: Recordable;
model: Recordable;
field: string;
schema: FormSchema
values: Recordable
model: Recordable
field: string
}
export interface ButtonProps extends AntdButtonProps {
text?: string;
text?: string
}
export interface FormActionType {
submit: () => Promise<void>;
setFieldsValue: <T>(values: T) => Promise<void>;
resetFields: () => Promise<void>;
getFieldsValue: () => Recordable;
clearValidate: (name?: string | string[]) => Promise<void>;
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
setProps: (formProps: Partial<FormProps>) => Promise<void>;
removeSchemaByField: (field: string | string[]) => Promise<void>;
submit: () => Promise<void>
setFieldsValue: <T>(values: T) => Promise<void>
resetFields: () => Promise<void>
getFieldsValue: () => Recordable
clearValidate: (name?: string | string[]) => Promise<void>
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>
setProps: (formProps: Partial<FormProps>) => Promise<void>
removeSchemaByField: (field: string | string[]) => Promise<void>
appendSchemaByField: (
schema: FormSchema | FormSchema[],
prefixField: string | undefined,
first?: boolean | undefined,
) => Promise<void>;
validateFields: (nameList?: NamePath[]) => Promise<any>;
validate: (nameList?: NamePath[]) => Promise<any>;
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>;
) => Promise<void>
validateFields: (nameList?: NamePath[]) => Promise<any>
validate: (nameList?: NamePath[]) => Promise<any>
getFieldList: (nameList?: NamePath[]) => Promise<any>
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>
linkageForm: () => Promise<void>
}
export type RegisterFn = (formInstance: FormActionType) => void;
export type RegisterFn = (formInstance: FormActionType) => void
export type UseFormReturnType = [RegisterFn, FormActionType];
export type UseFormReturnType = [RegisterFn, FormActionType]
export interface FormProps {
name?: string;
layout?: 'vertical' | 'inline' | 'horizontal';
name?: string
layout?: 'vertical' | 'inline' | 'horizontal'
// Form value
model?: Recordable;
model?: Recordable
// The width of all items in the entire form
labelWidth?: number | string;
labelWidth?: number | string
// alignment
labelAlign?: 'left' | 'right';
labelAlign?: 'left' | 'right'
// Row configuration for the entire form
rowProps?: RowProps;
rowProps?: RowProps
// Submit form on reset
submitOnReset?: boolean;
submitOnReset?: boolean
// Submit form on form changing
submitOnChange?: boolean;
submitOnChange?: boolean
// Col configuration for the entire form
labelCol?: Partial<ColEx>;
labelCol?: Partial<ColEx>
// Col configuration for the entire form
wrapperCol?: Partial<ColEx>;
wrapperCol?: Partial<ColEx>
// General row style
baseRowStyle?: CSSProperties;
baseRowStyle?: CSSProperties
// General col configuration
baseColProps?: Partial<ColEx>;
baseColProps?: Partial<ColEx>
// Form configuration rules
schemas?: FormSchema[];
schemas?: FormSchema[]
// Function values used to merge into dynamic control form items
mergeDynamicData?: Recordable;
mergeDynamicData?: Recordable
// Compact mode for search forms
compact?: boolean;
compact?: boolean
// Blank line span
emptySpan?: number | Partial<ColEx>;
emptySpan?: number | Partial<ColEx>
// Internal component size of the form
size?: 'default' | 'small' | 'large';
size?: 'default' | 'small' | 'large'
// Whether to disable
disabled?: boolean;
disabled?: boolean
// Time interval fields are mapped into multiple
fieldMapToTime?: FieldMapToTime;
fieldMapToTime?: FieldMapToTime
// Placeholder is set automatically
autoSetPlaceHolder?: boolean;
autoSetPlaceHolder?: boolean
// Auto submit on press enter on input
autoSubmitOnEnter?: boolean;
autoSubmitOnEnter?: boolean
// Check whether the information is added to the label
rulesMessageJoinLabel?: boolean;
rulesMessageJoinLabel?: boolean
// Whether to show collapse and expand buttons
showAdvancedButton?: boolean;
showAdvancedButton?: boolean
// Whether to focus on the first input box, only works when the first form item is input
autoFocusFirstItem?: boolean;
autoFocusFirstItem?: boolean
// Automatically collapse over the specified number of rows
autoAdvancedLine?: number;
autoAdvancedLine?: number
// Always show lines
alwaysShowLines?: number;
alwaysShowLines?: number
// Whether to show the operation button
showActionButtonGroup?: boolean;
showActionButtonGroup?: boolean
// 是否使用高级查询
useAdvancedSearch?: boolean
// 是否使用多单号查询
useNumbersSearch?: boolean
// Reset button configuration
resetButtonOptions?: Partial<ButtonProps>;
resetButtonOptions?: Partial<ButtonProps>
// Confirm button configuration
submitButtonOptions?: Partial<ButtonProps>;
submitButtonOptions?: Partial<ButtonProps>
// Operation column configuration
actionColOptions?: Partial<ColEx>;
actionColOptions?: Partial<ColEx>
// Show reset button
showResetButton?: boolean;
showResetButton?: boolean
// Show confirmation button
showSubmitButton?: boolean;
showSubmitButton?: boolean
resetFunc?: () => Promise<void>;
submitFunc?: () => Promise<void>;
transformDateFunc?: (date: any) => string;
colon?: boolean;
resetFunc?: () => Promise<void>
submitFunc?: () => Promise<void>
transformDateFunc?: (date: any) => string
colon?: boolean
}
export interface FormSchema {
// Field name
field: string;
field: string
// Event name triggered by internal value change, default change
changeEvent?: string;
changeEvent?: string
// Variable name bound to v-model Default value
valueField?: string;
valueField?: string
// Label name
label: string | VNode;
label?: string | VNode
enLabel?: string | VNode
// Auxiliary text
subLabel?: string;
subLabel?: string
// Help text on the right side of the text
helpMessage?:
| string
| string[]
| ((renderCallbackParams: RenderCallbackParams) => string | string[]);
| ((renderCallbackParams: RenderCallbackParams) => string | string[])
// BaseHelp component props
helpComponentProps?: Partial<HelpComponentProps>;
helpComponentProps?: Partial<HelpComponentProps>
// Label width, if it is passed, the labelCol and WrapperCol configured by itemProps will be invalid
labelWidth?: string | number;
labelWidth?: string | number
// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
disabledLabelWidth?: boolean;
disabledLabelWidth?: boolean
// render component
component: ComponentType;
component: ComponentType
// Component parameters
componentProps?:
| ((opt: {
schema: FormSchema;
tableAction: TableActionType;
formActionType: FormActionType;
formModel: Recordable;
schema: FormSchema
tableAction: TableActionType
formActionType: FormActionType
formModel: Recordable
}) => Recordable)
| object;
| object
// Required
required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
suffix?: string | number | ((values: RenderCallbackParams) => string | number);
suffix?: string | number | ((values: RenderCallbackParams) => string | number)
// Validation rules
rules?: Rule[];
rules?: Rule[]
// Check whether the information is added to the label
rulesMessageJoinLabel?: boolean;
rulesMessageJoinLabel?: boolean
// Reference formModelItem
itemProps?: Partial<FormItem>;
itemProps?: Partial<FormItem>
// col configuration outside formModelItem
colProps?: Partial<ColEx>;
colProps?: Partial<ColEx>
// 默认值
defaultValue?: any;
defaultValue?: any
// 是否自动处理与时间相关组件的默认值
isHandleDateDefaultValue?: boolean;
isHandleDateDefaultValue?: boolean
isAdvanced?: boolean;
isAdvanced?: boolean
// Matching details components
span?: number;
span?: number
ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
// Render the content in the form-item tag
render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string
// Rendering col content requires outer wrapper form-item
renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string
renderComponentContent?:
| ((renderCallbackParams: RenderCallbackParams) => any)
| VNode
| VNode[]
| string;
| string
// Custom slot, in from-item
slot?: string;
slot?: string
// Custom slot, similar to renderColContent
colSlot?: string;
colSlot?: string
// label上的插槽
labelSlot?: string
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[]
}
export interface HelpComponentProps {
maxWidth: string;
maxWidth: string
// Whether to display the serial number
showIndex: boolean;
showIndex: boolean
// Text list
text: any;
text: any
// colour
color: string;
color: string
// font size
fontSize: string;
icon: string;
absolute: boolean;
fontSize: string
icon: string
absolute: boolean
// Positioning
position: any;
position: any
}

@ -0,0 +1,7 @@
import { intersection } from 'lodash-es'
import { usePermissionStore } from '/@/store/modules/permission'
export function checkPermissions(key) {
const permissionStore = usePermissionStore()
const allCodeList = permissionStore.getPermCodeList as string[]
return !((intersection([key], allCodeList) as string[]).length > 0)
}

@ -0,0 +1,224 @@
import { router } from "/@/router"
import { useMultipleTabStore } from '/@/store/modules/multipleTab'
import { useMessage } from '/@/hooks/web/useMessage'
// 获取表单更改过的字段接口
import { getFormSetInfoByModule } from '/@/views/baseinfo/formset/api'
// 引入表格权限信息包含id和name
import { permissionsInfo } from '/@/hooks/web/usePermission'
import * as XLSX from 'xlsx'
const { createMessage } = useMessage()
// 格式表格时间
export function formatTableData(v) {
if (v) {
v = v.split(' ')[0]
if (v.includes('1900')) v = ''
return v
} else {
return ''
}
}
/* ()
* topath: path
*/
export function closePage(topath) {
const tabStore = useMultipleTabStore()
tabStore.closeTab(router.currentRoute._value, router)
// 有目标路径则跳转
if (topath) {
router.push(topath)
} else {
// 父级路由
const parent = router?.options?.history?.state?.back
// 如果存在父级路由,直接返回父级
if (parent) {
router.push(parent)
} else {
// 否则返回上一级路由
router.back()
}
}
}
/* excel()
* api: params: columes: name: excel
*/
export function exportExcel(api, params = {}, columns = [], name = '未命名') {
if (!api) return createMessage.warning('缺少api')
params['pageCondition']['isExport'] = true
// 过滤出需要显示的列
const cols = columns.filter(item => {
return !item.defaultHidden || item.visible
})
api(params).then(res => {
const { data } = res
const fileData = data.map(row => {
const obj = {}
cols.forEach(item => {
for (var key in row) {
if (item.dataIndex === key) {
obj[item.title] = row[key]
}
}
})
return obj
})
toBlob(fileData, name)
})
}
// 将字符串转换为ArrayBuffer
function s2ab(s) {
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
}
/* excel()
* data: columes: name: excel
*/
export function exportExcelByData(data = [], columns = [], name = '未命名') {
// 过滤出需要显示的列
const cols = columns.filter(item => {
return !item.defaultHidden || item.visible
})
const fileData = data.map(row => {
const obj = {}
cols.forEach(item => {
for (var key in row) {
if (item.dataIndex === key) {
obj[item.title] = row[key]
}
}
})
return obj
})
toBlob(fileData, name)
}
function toBlob(fileData, name) {
// 创建工作簿
const workbook = XLSX.utils.book_new()
// 将数据转换为工作表
const worksheet = XLSX.utils.json_to_sheet(fileData)
// 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
// 生成Excel的配置
const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' })
// 创建二进制对象并创建url
const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
const url = URL.createObjectURL(blob)
// 创建a标签模拟点击进行下载
const a = document.createElement('a')
a.href = url
a.download = name + '.xlsx'
document.body.appendChild(a)
a.click()
// 清除对象URL
setTimeout(() => {
URL.revokeObjectURL(url)
document.body.removeChild(a)
}, 0)
}
// 更新表单数据
export function updateFormItem(updateSchema, formNo) {
getFormSetInfoByModule({ permissionId: permissionsInfo().permissionId, formNo }).then(res => {
if (res?.data?.content) {
const content = JSON.parse(res.data.content)
console.log(content)
updateSchema(content.columns)
}
})
}
// 返回表格查询的参数 multipleList(需要多选查询的字段名数组)
export function formatParams(params = {}) {
const postData = {
queryCondition: '',
pageCondition: {
pageIndex: params?.page,
pageSize: params?.pageSize,
sortConditions: []
}
}
const conditions = [] as any
for (let key in params) {
// 排除不是分页排序等字段
if (key != 'page' && key != 'pageSize' && key != 'order' && key != 'field') {
if (key == 'advancedSearchParams') {
// 高级查询
conditions.push(params[key])
} else {
// 其他查询
if (Array.isArray(params[key])) {
const isDate = new Date(params[key][0]) as any
// 判定为日期
if (isDate != 'Invalid Date' && isDate.getFullYear() > 1000) {
//替换时分秒 查询用
params[key][0] = params[key][0].substring(0, 11) + "00:00:00";
params[key][1] = params[key][1].substring(0, 11) + "23:59:59";
conditions.push({
FieldName: key,
FieldValue: params[key][0],
ConditionalType: 3
})
conditions.push({
FieldName: key,
FieldValue: params[key][1],
ConditionalType: 5
})
} else {
// 判定为筛选
params[key].forEach(item => {
conditions.push({
FieldName: key,
FieldValue: item,
ConditionalType: 1
})
})
}
} else if (key.includes(':')) {
// or 多个字段查询
const orKeys = key.split(':')
const ConditionalList = { ConditionalList: [] }
if (params[key]) {
orKeys.forEach(item => {
let obj = {
Key: 1,
Value: {
FieldName: item,
FieldValue: params[key],
ConditionalType: 1
}
}
ConditionalList.ConditionalList.push(obj)
})
conditions.push(ConditionalList)
}
} else {
// 其他普通查询
if (params[key] || params[key] === 0) {
conditions.push({
FieldName: key,
FieldValue: params[key],
ConditionalType: 1
})
}
}
}
}
}
// 排序
if (params?.field) {
postData.pageCondition.sortConditions = [{
sortField: params.field,
listSortDirection: params.order == "ascend" ? 0 : 1
}]
} else {
postData.pageCondition.sortConditions = []
}
postData.queryCondition = JSON.stringify(conditions)
return postData
}

@ -0,0 +1,123 @@
<template>
<BasicModal
v-bind="$attrs"
:use-wrapper="true"
:title="getTitle"
width="30%"
@register="registerModal"
@ok="handleSave"
>
<BasicForm @register="registerForm" />
<!--右下角按钮-->
<template #footer>
<a-button
pre-icon="ant-design:close-outlined"
type="warning"
:loading="loading"
ghost
style="margin-right: 0.8rem"
@click="closeModal"
>取消</a-button
>
<a-button
type="success"
:loading="loading"
pre-icon="ant-design:check-outlined"
style="margin-right: 0.8rem"
@click="handleSave(false)"
>仅保存</a-button
>
<a-button
pre-icon="ant-design:check-circle-outlined"
type="primary"
:loading="loading"
@click="handleSave(true)"
>保存并关闭</a-button
>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue'
import { BasicModal, useModalInner } from '/@/components/Modal'
import { BasicForm, useForm } from '/@/components/Form/index'
import { formSchema } from './columns'
import { ApiEdit, ApiInfo } from './api'
import { useMessage } from '/@/hooks/web/useMessage'
// Emits
const emit = defineEmits(['success', 'register'])
const isUpdate = ref(true)
const loading = ref(false)
const rowId = ref('')
const { createMessage } = useMessage()
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
})
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields()
setModalProps({ confirmLoading: false, loading: true })
isUpdate.value = !!data?.isUpdate
if (unref(isUpdate)) {
// setModalProps({ confirmLoading: true });
rowId.value = data.record.id
const res: API.DataResult = await ApiInfo({ id: unref(rowId) })
if (res.succeeded) {
setFieldsValue({
...res.data,
})
// console.log('Form', getFieldsValue());
// setFieldsValue({ trainId: unref(res.data.trainId) });
}
// setModalProps({ confirmLoading: false });
} else {
setFieldsValue({ permissionIdentity: unref(2) })
}
setModalProps({ loading: false })
})
const getTitle = computed(() => (!unref(isUpdate) ? '新增放舱通道配置' : '编辑放舱通道配置'))
async function handleSave(exit) {
try {
const values = await validate()
setModalProps({ confirmLoading: true, loading: true })
// TODO custom api
console.log(values)
// loading.value = true;
const res: API.DataResult = await ApiEdit(values)
console.log(res)
if (res.succeeded) {
createMessage.success(res.message)
emit('success')
//
if (!exit) {
if (unref(isUpdate)) {
await refresh()
} else {
rowId.value = res.data
isUpdate.value = true
await refresh()
}
}
} else {
createMessage.error(res.message)
}
exit && closeModal()
} finally {
// loading.value = false;
setModalProps({ confirmLoading: false, loading: false })
}
}
async function refresh() {
const res: API.DataResult = await ApiInfo({ id: unref(rowId) })
if (res.succeeded) {
await setFieldsValue({
...res.data,
})
}
}
</script>

@ -0,0 +1,40 @@
// @ts-ignore
import { request } from '/@/utils/request'
import { DataResult, PageRequest } from '/@/api/model/baseModel'
enum Api {
list = '/adminApi/ReleaseType/GetList',
editORinfo = '/adminApi/ReleaseType/Edit',
del = '/adminApi/ReleaseType/Delete',
}
// 列表 (Auth)
export function ApiList(data: PageRequest) {
return request<DataResult>({
url: Api.list,
method: 'post',
data,
})
}
// 编辑 (Auth)
export function ApiEdit(data: PageRequest) {
return request<DataResult>({
url: Api.editORinfo,
method: 'post',
data,
})
}
// 详情 (Auth)
export function ApiInfo(query) {
return request<DataResult>({
url: Api.editORinfo,
method: 'get',
params: query,
})
}
// 批量删除 (Auth)
export function ApiDel(data: PageRequest) {
return request<DataResult>({
url: Api.del,
method: 'post',
data,
})
}

@ -0,0 +1,170 @@
import { BasicColumn, FormSchema } from '/@/components/Table'
import { GetCarrierSelectList, GetClientPortSelectList } from '/@/api/common'
export const columns: BasicColumn[] = [
{
title: '承运商',
dataIndex: 'carrier',
sorter: true,
width: 150,
},
{
title: '起运港代码',
dataIndex: 'loadingPort',
sorter: true,
width: 200,
},
{
title: '放舱方式名称',
dataIndex: 'releaseTypeName',
sorter: true,
width: 200,
},
]
export const searchFormSchema: FormSchema[] = [
{
label: '承运商',
field: 'carrier',
labelSlot: 'carrierId',
component: 'ApiSelect',
colProps: { span: 6 },
componentProps: ({ formModel }) => {
return {
api: GetCarrierSelectList,
labelField: 'pinYinCode',
showName: 'cnName',
valueField: 'code',
resultField: 'data',
immediate: false,
onChange: (e, obj) => {
console.log(obj)
if (e && obj) {
formModel.carrierId = obj.id
}
if (!e && !obj) {
formModel.carrierId = ''
}
},
}
},
},
{
label: '起运港',
field: 'loadingPort',
component: 'ApiSelect',
colProps: { span: 6 },
componentProps: () => {
return {
api: GetClientPortSelectList,
resultField: 'data',
allowClear: true,
showSearch: true,
labelField: 'portName',
showName: 'portName',
valueField: 'ediCode',
immediate: true,
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
}
},
},
{
field: 'releaseType',
label: '放舱方式',
component: 'Select',
colProps: { span: 6 },
componentProps: {
options: [
{ label: '入货通知', value: 1 },
{ label: '转发BC', value: 2 },
],
},
},
]
export const formSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
defaultValue: '',
show: false,
},
{
label: '承运商',
field: 'carrier',
labelSlot: 'carrierId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
colProps: { span: 20 },
componentProps: ({ formModel }) => {
return {
api: GetCarrierSelectList,
labelField: 'pinYinCode',
showName: 'cnName',
valueField: 'code',
resultField: 'data',
immediate: false,
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
console.log(obj)
if (e && obj) {
formModel.carrierId = obj.id
}
if (!e && !obj) {
formModel.carrierId = ''
}
},
}
},
},
{
label: '委托单位',
field: 'customerId',
component: 'Input',
defaultValue: null,
show: false,
},
{
label: '起运港',
field: 'loadingPort',
component: 'ApiSelect',
required: true,
dynamicDisabled: false,
colProps: { span: 20 },
componentProps: () => {
return {
api: GetClientPortSelectList,
resultField: 'data',
allowClear: true,
showSearch: true,
labelField: 'portName',
showName: 'portName',
valueField: 'ediCode',
immediate: true,
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
}
},
},
{
field: 'releaseType',
label: '放舱方式',
component: 'Select',
required: true,
colProps: { span: 20 },
componentProps: {
options: [
{ label: '入货通知', value: 1 },
{ label: '转发BC', value: 2 },
],
},
},
]

@ -0,0 +1,150 @@
<template>
<div>
<BasicTable class="ds-table" @register="registerTable" @row-dbClick="handleAudit">
<template #toolbar>
<a-button type="primary" @click="handleCreate"> </a-button>
<a-popconfirm
title="确定删除当前选中数据?"
ok-text="是"
cancel-text="否"
@confirm="handleDel"
>
<a-button type="primary" @click="handleCreate"> </a-button>
</a-popconfirm>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
icon: 'clarity:note-edit-line',
tooltip: '编辑',
onClick: handleAudit.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<TenantAuditStepModal @register="registerModal" @success="handleSuccess" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Divider } from 'ant-design-vue'
import { BasicTable, useTable, TableAction, SorterResult } from '/@/components/Table'
import { ApiList, ApiDel } from './api'
import { useModal } from '/@/components/Modal'
import TenantAuditStepModal from './TenantAuditStepModal.vue'
import { columns, searchFormSchema } from './columns'
import { useMessage } from '/@/hooks/web/useMessage'
const { notification } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerTable, { reload, getForm, getSelectRows, getPaginationRef }] = useTable({
title: '放舱通道配置列表',
api: async (p) => {
const res: API.DataResult = await ApiList(p)
return new Promise((resolve) => {
resolve({ data: [...res.data], total: res.count })
})
},
beforeFetch: () => {
var currentPageInfo: any = getPaginationRef()
var data = getForm().getFieldsValue()
const postParam: API.PageRequest = {
queryCondition: '',
pageCondition: {
pageIndex: currentPageInfo.current,
pageSize: currentPageInfo.pageSize,
sortConditions: [],
},
}
let condition: API.ConditionItem[] = []
if (!!data.carrier) {
condition.push({
FieldName: 'carrier',
FieldValue: data.carrier,
ConditionalType: 1,
})
}
if (!!data.loadingPort) {
condition.push({
FieldName: 'loadingPort',
FieldValue: data.loadingPort,
ConditionalType: 1,
})
}
if (!!data.releaseType) {
condition.push({
FieldName: 'releaseType',
FieldValue: data.releaseType,
ConditionalType: 1,
})
}
postParam.queryCondition = JSON.stringify(condition)
// console.log(postParam);
return postParam
},
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
isTreeTable: false,
pagination: true,
striped: true,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: true,
indexColumnProps: {
width: 60,
},
canResize: true,
resizeHeightOffset: 35,
immediate: true,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
fixed: 'right',
},
})
function handleDel() {
const select = getSelectRows()
let ApiData: any = {
ids: [],
}
if (select.length === 0) {
notification.warning({ message: '请至少选择一条数据', duration: 3 })
return false
} else {
ApiData.ids = select.map((item) => {
return item.id
})
}
ApiDel(ApiData).then((res) => {
console.log(res)
notification.success({ message: res.message, duration: 3 })
reload()
})
}
function handleCreate() {
openModal(true, {
isParent: false,
isUpdate: false,
})
}
function handleAudit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
})
}
function handleSuccess() {
reload()
}
</script>
Loading…
Cancel
Save