Browse Source

🚨 简化地图任务处理

master
wangxiang 3 years ago
parent
commit
ed424af3d1
  1. 19
      src/components/AMap/src/amap.data.tsx
  2. 53
      src/components/AMap/src/components/MapTaskModal.vue
  3. 9
      src/components/AMap/src/components/MapTaskPresetModal.vue
  4. 200
      src/components/Table/src/components/editable/EditableCell.vue
  5. 30
      src/components/Table/src/types/table.ts

19
src/components/AMap/src/amap.data.tsx

@ -1,5 +1,4 @@
import { BasicColumn } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table';
import { listHospital } from '/@/api/platform/common/controller/hospital';
import { listOrg } from '/@/api/platform/common/controller/org'; import { listOrg } from '/@/api/platform/common/controller/org';
import { commonUpload } from '/@/api/platform/core/controller/upload'; import { commonUpload } from '/@/api/platform/core/controller/upload';
import { h } from 'vue'; import { h } from 'vue';
@ -50,7 +49,7 @@ export const operatePanelColumns: BasicColumn[] = [
]; ];
/** 普通任务表格列 */ /** 普通任务表格列 */
export const taskColumns: BasicColumn[] = [ export const taskOrdinaryColumns: BasicColumn[] = [
{ {
title: '任务名称', title: '任务名称',
dataIndex: 'name', dataIndex: 'name',
@ -63,14 +62,6 @@ export const taskColumns: BasicColumn[] = [
editRow: true, editRow: true,
editRule: true, editRule: true,
editComponent: 'ApiSelect', editComponent: 'ApiSelect',
editComponentProps: {
style: { width:'100%' },
api: listHospital,
params: { size: 40, mapNotify: '1' },
labelField: 'name',
valueField: 'id',
resultField: 'data'
}
}, },
{ {
title: '医检', title: '医检',
@ -129,14 +120,6 @@ export const taskPresetColumns: BasicColumn[] = [
editRow: true, editRow: true,
editRule: true, editRule: true,
editComponent: 'ApiSelect', editComponent: 'ApiSelect',
editComponentProps: {
style: { width:'100%' },
api: listHospital,
params: { size: 40, mapNotify: '1' },
labelField: 'name',
valueField: 'id',
resultField: 'data'
}
}, },
{ {
title: '目的地预设点', title: '目的地预设点',

53
src/components/AMap/src/components/MapTaskModal.vue

@ -61,13 +61,14 @@
import { reactive, toRaw } from 'vue'; import { reactive, toRaw } from 'vue';
import {BasicModal, ModalProps, useModal, useModalInner} from '/@/components/Modal'; import {BasicModal, ModalProps, useModal, useModalInner} from '/@/components/Modal';
import { BasicTable, useTable, EditRecordRow, BasicColumn, ActionItem, TableAction } from '/@/components/Table'; import { BasicTable, useTable, EditRecordRow, BasicColumn, ActionItem, TableAction } from '/@/components/Table';
import { taskColumns, taskPresetColumns } from '../amap.data'; import { taskOrdinaryColumns, taskPresetColumns } from '../amap.data';
import TaskPresetModal from './MapTaskPresetModal.vue'; import TaskPresetModal from './MapTaskPresetModal.vue';
import { buildUUID } from '/@/utils/uuid'; import { buildUUID } from '/@/utils/uuid';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import {add, cloneDeep} from 'lodash-es'; import {add, cloneDeep} from 'lodash-es';
import { defaultMapData } from '/@/enums/amapEnum'; import { defaultMapData } from '/@/enums/amapEnum';
import { MapLogistic } from '/@/api/platform/common/entity/mapLogistic'; import { MapLogistic } from '/@/api/platform/common/entity/mapLogistic';
import { listHospital } from '/@/api/platform/common/controller/hospital';
/** 类型规范统一声明定义区域 */ /** 类型规范统一声明定义区域 */
interface WindowState { interface WindowState {
@ -88,21 +89,64 @@
state.mapData = data.mapData; state.mapData = data.mapData;
const props: Partial<ModalProps> = { confirmLoading: false }; const props: Partial<ModalProps> = { confirmLoading: false };
props.title = '任务配置'; props.title = '任务配置';
const taskOrdinaryUpdateColumns: BasicColumn[] = [
{
title: '医院',
dataIndex: 'hospitalId',
editRow: true,
editRule: true,
editComponent: 'ApiSelect',
editComponentProps: ({ text, record, column, index }) => ({
style: { width:'100%' },
api: listHospital,
params: { size: 40, mapNotify: '1' },
disabled: record.hospitalId == state.mapData.sendOrderId,
labelField: 'name',
valueField: 'id',
resultField: 'data'
})
},
],
taskPresetUpdateColumns: BasicColumn[] = [
{
title: '医院',
dataIndex: 'hospitalId',
editRow: true,
editRule: true,
editComponent: 'ApiSelect',
editComponentProps: ({ text, record, column, index }) => ({
style: { width:'100%' },
api: listHospital,
params: { size: 40, mapNotify: '1' },
disabled: record.hospitalId == state.mapData.sendOrderId,
labelField: 'name',
valueField: 'id',
resultField: 'data'
})
},
];
const mapTask = cloneDeep(state.mapData?.mapTask || []); const mapTask = cloneDeep(state.mapData?.mapTask || []);
setTaskOrdinaryTableData(mapTask.filter(item => ~~item.taskType == 0)); setTaskOrdinaryTableData(mapTask.filter(item => ~~item.taskType == 0));
setTaskPresetTableData(mapTask.filter(item => ~~item.taskType == 1)); setTaskPresetTableData(mapTask.filter(item => ~~item.taskType == 1));
// : // :
setTaskOrdinaryColumns(taskOrdinaryColumns.map(item =>
taskOrdinaryUpdateColumns.find(e => e.dataIndex == item.dataIndex) || item
));
setTaskPresetColumns(taskPresetColumns.map(item =>
taskPresetUpdateColumns.find(e => e.dataIndex == item.dataIndex) || item
));
setModalProps(props); setModalProps(props);
}); });
const { notification } = useMessage(); const { notification } = useMessage();
const [taskPresetRegisterModal, { openModal }] = useModal(); const [taskPresetRegisterModal, { openModal }] = useModal();
const [taskOrdinaryRegisterTable, { const [taskOrdinaryRegisterTable, {
getDataSource: getTaskOrdinaryDataSource, getDataSource: getTaskOrdinaryDataSource,
setTableData: setTaskOrdinaryTableData setTableData: setTaskOrdinaryTableData,
setColumns: setTaskOrdinaryColumns
}] = useTable({ }] = useTable({
rowKey: 'id', rowKey: 'id',
title: '普通任务', title: '普通任务',
columns: taskColumns, columns: taskOrdinaryColumns,
pagination: { pagination: {
pageSize: 4, pageSize: 4,
showSizeChanger: false showSizeChanger: false
@ -122,7 +166,8 @@
}); });
const [taskPresetRegisterTable, { const [taskPresetRegisterTable, {
getDataSource: getTaskPresetDataSource, getDataSource: getTaskPresetDataSource,
setTableData: setTaskPresetTableData setTableData: setTaskPresetTableData,
setColumns: setTaskPresetColumns
}] = useTable({ }] = useTable({
rowKey: 'id', rowKey: 'id',
title: '交接任务', title: '交接任务',

9
src/components/AMap/src/components/MapTaskPresetModal.vue

@ -115,15 +115,14 @@
})); }));
}); });
await listUser({ size: 40, userType: '1' }).then(res => { await listUser({ size: 40, userType: '1' }).then(res => {
columns[0].editComponentProps!.options = res.data?.map(item => ({ columns[0].editComponentProps.options = res.data?.map(item => ({
value: item.id, value: item.id,
label: item.nickName, label: item.nickName,
})).filter(item => item.value != state.courierUserId); })).filter(item => item.value != state.courierUserId);
}); });
setColumns(taskPresetChildColumns.map(item => { setColumns(taskPresetChildColumns.map(item =>
const column = columns.find(e => e.dataIndex == item.dataIndex); columns.find(e => e.dataIndex == item.dataIndex) || item
return column ? column : item; ));
}));
const mapTaskPresetData = cloneDeep(state.taskPresetRow?.mapTaskPreset || []); const mapTaskPresetData = cloneDeep(state.taskPresetRow?.mapTaskPreset || []);
// //
const lastElement = mapTaskPresetData[mapTaskPresetData.length - 1]; const lastElement = mapTaskPresetData[mapTaskPresetData.length - 1];

200
src/components/Table/src/components/editable/EditableCell.vue

@ -1,57 +1,26 @@
<template> <script lang="tsx">
<div :class="prefixCls">
<div
v-show="!isEdit"
:class="{ [`${prefixCls}__normal`]: true, 'ellipsis-cell': column.ellipsis }"
@click="handleEdit"
>
<div class="cell-content" :title="column.ellipsis ? getValues ?? '' : ''">{{
getValues ?? '&nbsp;'
}}</div>
<FormOutlined v-if="!column.editRow" :class="`${prefixCls}__normal-icon`"/>
</div>
<div v-if="isEdit" v-click-outside="onClickOutside" :class="`${prefixCls}__wrapper`">
<CellComponent
v-bind="getComponentProps"
ref="elRef"
:component="getComponent"
:style="getWrapperStyle"
:popoverVisible="getRuleVisible"
:rule="getRule"
:ruleMessage="ruleMessage"
:class="getWrapperClass"
size="small"
@change="handleChange"
@options-change="handleOptionsChange"
@pressEnter="handleEnter"
/>
<div v-if="!getRowEditable" :class="`${prefixCls}__action`">
<CheckOutlined :class="[`${prefixCls}__icon`, 'mx-2']" @click="handleSubmit"/>
<CloseOutlined :class="`${prefixCls}__icon `" @click="handleCancel"/>
</div>
</div>
</div>
</template>
<script lang="ts">
import type { CSSProperties, PropType } from 'vue'; import type { CSSProperties, PropType } from 'vue';
import { computed, defineComponent, nextTick, ref, toRaw, unref, watchEffect } from 'vue'; import { computed, defineComponent, nextTick, ref, toRaw, unref, watchEffect } from 'vue';
import type { BasicColumn } from '../../types/table'; import type { BasicColumn } from '../../types/table';
import type { EditRecordRow } from './index'; import type { EditRecordRow } from './index';
import { CheckOutlined, CloseOutlined, FormOutlined } from '@ant-design/icons-vue'; import { CheckOutlined, CloseOutlined, FormOutlined } from '@ant-design/icons-vue';
import { CellComponent } from './CellComponent'; import { CellComponent } from './CellComponent';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useTableContext } from '../../hooks/useTableContext'; import { useTableContext } from '../../hooks/useTableContext';
import clickOutside from '/@/directives/clickOutside'; import clickOutside from '/@/directives/clickOutside';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { isArray, isBoolean, isFunction, isNumber, isString } from '/@/utils/is'; import { isArray, isBoolean, isFunction, isNumber, isString } from '/@/utils/is';
import { createPlaceholderMessage } from './helper'; import { createPlaceholderMessage } from './helper';
import { omit, set } from 'lodash-es'; import { omit, pick, set } from 'lodash-es';
import { treeToList } from '/@/utils/helper/treeHelper'; import { treeToList } from '/@/utils/helper/treeHelper';
import { Spin } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'EditableCell', name: 'EditableCell',
components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent }, components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent, Spin },
directives: { directives: {
clickOutside, clickOutside,
}, },
@ -78,6 +47,7 @@
const optionsRef = ref<LabelValueOptions>([]); const optionsRef = ref<LabelValueOptions>([]);
const currentValueRef = ref<any>(props.value); const currentValueRef = ref<any>(props.value);
const defaultValueRef = ref<any>(props.value); const defaultValueRef = ref<any>(props.value);
const spinning = ref<boolean>(false);
const { prefixCls } = useDesign('editable-cell'); const { prefixCls } = useDesign('editable-cell');
@ -94,13 +64,6 @@
}); });
const getComponentProps = computed(() => { const getComponentProps = computed(() => {
const compProps = props.column?.editComponentProps ?? {};
const component = unref(getComponent);
const apiSelectProps: Recordable = {};
if (component === 'ApiSelect') {
apiSelectProps.cache = true;
}
const isCheckValue = unref(getIsCheckComp); const isCheckValue = unref(getIsCheckComp);
const valueField = isCheckValue ? 'checked' : 'value'; const valueField = isCheckValue ? 'checked' : 'value';
@ -108,18 +71,49 @@
const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val; const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val;
let compProps = props.column?.editComponentProps ?? {};
const { record, column, index } = props;
if (isFunction(compProps)) {
compProps = compProps({ text: val, record, column, index }) ?? {};
}
const component = unref(getComponent);
const apiSelectProps: Recordable = {};
if (component === 'ApiSelect') {
apiSelectProps.cache = true;
}
upEditDynamicDisabled(record, column, value);
return { return {
size: 'small',
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body, getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
getCalendarContainer: () => unref(table?.wrapRef.value) ?? document.body,
placeholder: createPlaceholderMessage(unref(getComponent)), placeholder: createPlaceholderMessage(unref(getComponent)),
...apiSelectProps, ...apiSelectProps,
...omit(compProps, 'onChange'), ...compProps,
[valueField]: value, [valueField]: value,
}; disabled: unref(getDisable),
} as any;
});
function upEditDynamicDisabled(record, column, value) {
if (!record) return false;
const { key, dataIndex } = column;
if (!key && !dataIndex) return;
const dataKey = (dataIndex || key) as string;
set(record, dataKey, value);
}
const getDisable = computed(() => {
const { editDynamicDisabled } = props.column;
let disabled = false;
if (isBoolean(editDynamicDisabled)) {
disabled = editDynamicDisabled;
}
if (isFunction(editDynamicDisabled)) {
const { record } = props;
disabled = editDynamicDisabled({ record });
}
return disabled;
}); });
const getValues = computed(() => { const getValues = computed(() => {
const { editComponentProps, editValueMap } = props.column; const { editValueMap } = props.column;
const value = unref(currentValueRef); const value = unref(currentValueRef);
@ -132,7 +126,8 @@
return value; return value;
} }
const options: LabelValueOptions = editComponentProps?.options ?? (unref(optionsRef) || []); const options: LabelValueOptions =
unref(getComponentProps)?.options ?? (unref(optionsRef) || []);
const option = options.find((item) => `${item.value}` === `${value}`); const option = options.find((item) => `${item.value}` === `${value}`);
return option?.label ?? value; return option?.label ?? value;
@ -183,14 +178,16 @@
const component = unref(getComponent); const component = unref(getComponent);
if (!e) { if (!e) {
currentValueRef.value = e; currentValueRef.value = e;
} else if (e?.target && Reflect.has(e.target, 'value')) {
currentValueRef.value = (e as ChangeEvent).target.value;
} else if (component === 'Checkbox') { } else if (component === 'Checkbox') {
currentValueRef.value = (e as ChangeEvent).target.checked; currentValueRef.value = (e as ChangeEvent).target.checked;
} else if (component === 'Switch') {
currentValueRef.value = e;
} else if (e?.target && Reflect.has(e.target, 'value')) {
currentValueRef.value = (e as ChangeEvent).target.value;
} else if (isString(e) || isBoolean(e) || isNumber(e) || isArray(e)) { } else if (isString(e) || isBoolean(e) || isNumber(e) || isArray(e)) {
currentValueRef.value = e; currentValueRef.value = e;
} }
const onChange = props.column?.editComponentProps?.onChange; const onChange = unref(getComponentProps)?.onChange;
if (onChange && isFunction(onChange)) onChange(...arguments); if (onChange && isFunction(onChange)) onChange(...arguments);
table.emit?.('edit-change', { table.emit?.('edit-change', {
@ -243,9 +240,38 @@
const dataKey = (dataIndex || key) as string; const dataKey = (dataIndex || key) as string;
if (!record.editable) {
const { getBindValues } = table;
const { beforeEditSubmit, columns } = unref(getBindValues);
if (beforeEditSubmit && isFunction(beforeEditSubmit)) {
spinning.value = true;
const keys: string[] = columns
.map((_column) => _column.dataIndex)
.filter((field) => !!field) as string[];
let result: any = true;
try {
result = await beforeEditSubmit({
record: pick(record, keys),
index,
key: dataKey as string,
value,
});
} catch (e) {
result = false;
} finally {
spinning.value = false;
}
if (result === false) {
return;
}
}
}
set(record, dataKey, value); set(record, dataKey, value);
//const record = await table.updateTableData(index, dataKey, value); //const record = await table.updateTableData(index, dataKey, value);
needEmit && table.emit?.('edit-end', { record, index, key, value }); needEmit && table.emit?.('edit-end', { record, index, key: dataKey, value });
isEdit.value = false; isEdit.value = false;
} }
@ -256,6 +282,10 @@
handleSubmit(); handleSubmit();
} }
function handleSubmitClick() {
handleSubmit();
}
function handleCancel() { function handleCancel() {
isEdit.value = false; isEdit.value = false;
currentValueRef.value = defaultValueRef.value; currentValueRef.value = defaultValueRef.value;
@ -282,7 +312,7 @@
// only ApiSelect or TreeSelect // only ApiSelect or TreeSelect
function handleOptionsChange(options: LabelValueOptions) { function handleOptionsChange(options: LabelValueOptions) {
const { replaceFields } = props.column?.editComponentProps ?? {}; const { replaceFields } = unref(getComponentProps);
const component = unref(getComponent); const component = unref(getComponent);
if (component === 'ApiTreeSelect') { if (component === 'ApiTreeSelect') {
const { title = 'title', value = 'value', children = 'children' } = replaceFields || {}; const { title = 'title', value = 'value', children = 'children' } = replaceFields || {};
@ -315,7 +345,7 @@
if (props.column.dataIndex) { if (props.column.dataIndex) {
if (!props.record.editValueRefs) props.record.editValueRefs = {}; if (!props.record.editValueRefs) props.record.editValueRefs = {};
props.record.editValueRefs[props.column.dataIndex] = currentValueRef; props.record.editValueRefs[props.column.dataIndex as any] = currentValueRef;
} }
/* eslint-disable */ /* eslint-disable */
props.record.onCancelEdit = () => { props.record.onCancelEdit = () => {
@ -354,9 +384,63 @@
getRowEditable, getRowEditable,
getValues, getValues,
handleEnter, handleEnter,
// getSize, handleSubmitClick,
spinning,
}; };
}, },
render() {
return (
<div class={this.prefixCls}>
<div
v-show={!this.isEdit}
class={{ [`${this.prefixCls}__normal`]: true, 'ellipsis-cell': this.column.ellipsis }}
onClick={this.handleEdit}
>
<div class="cell-content" title={this.column.ellipsis ? this.getValues ?? '' : ''}>
{this.column.editRender
? this.column.editRender({
text: this.value,
record: this.record as Recordable,
column: this.column,
index: this.index,
})
: this.getValues
? this.getValues
: '\u00A0'}
</div>
{!this.column.editRow && <FormOutlined class={`${this.prefixCls}__normal-icon`} />}
</div>
{this.isEdit && (
<Spin spinning={this.spinning}>
<div class={`${this.prefixCls}__wrapper`} v-click-outside={this.onClickOutside}>
<CellComponent
{...this.getComponentProps}
component={this.getComponent}
style={this.getWrapperStyle}
popoverVisible={this.getRuleVisible}
rule={this.getRule}
ruleMessage={this.ruleMessage}
class={this.getWrapperClass}
ref="elRef"
onChange={this.handleChange}
onOptionsChange={this.handleOptionsChange}
onPressEnter={this.handleEnter}
/>
{!this.getRowEditable && (
<div class={`${this.prefixCls}__action`}>
<CheckOutlined
class={[`${this.prefixCls}__icon`, 'mx-2']}
onClick={this.handleSubmitClick}
/>
<CloseOutlined class={`${this.prefixCls}__icon `} onClick={this.handleCancel} />
</div>
)}
</div>
</Spin>
)}
</div>
);
},
}); });
</script> </script>
<style lang="less"> <style lang="less">

30
src/components/Table/src/types/table.ts

@ -362,6 +362,18 @@ export interface BasicTableProps<T = any> {
*/ */
transformCellText?: Function; transformCellText?: Function;
/**
* Callback executed before editable cell submit value, not for row-editor
*
* The cell will not submit data while callback return false
*/
beforeEditSubmit?: (data: {
record: Recordable;
index: number;
key: string | number;
value: any;
}) => Promise<any>;
/** /**
* Callback executed when pagination, filters or sorter is changed * Callback executed when pagination, filters or sorter is changed
* @param pagination * @param pagination
@ -423,7 +435,14 @@ export interface BasicColumn extends ColumnProps {
editRow?: boolean; editRow?: boolean;
editable?: boolean; editable?: boolean;
editComponent?: ComponentType; editComponent?: ComponentType;
editComponentProps?: Recordable; editComponentProps?:
| ((opt: {
text: string | number | boolean | Recordable;
record: Recordable;
column: BasicColumn;
index: number;
}) => Recordable)
| Recordable;
editRule?: boolean | ((text: string, record: Recordable) => Promise<string>); editRule?: boolean | ((text: string, record: Recordable) => Promise<string>);
editValueMap?: (value: any) => string; editValueMap?: (value: any) => string;
onEditRow?: () => void; onEditRow?: () => void;
@ -431,6 +450,15 @@ export interface BasicColumn extends ColumnProps {
auth?: string | string[]; auth?: string | string[];
// 业务控制是否显示 // 业务控制是否显示
ifShow?: boolean | ((column: BasicColumn) => boolean); ifShow?: boolean | ((column: BasicColumn) => boolean);
// 自定义修改后显示的内容
editRender?: (opt: {
text: string | number | boolean | Recordable;
record: Recordable;
column: BasicColumn;
index: number;
}) => VNodeChild | JSX.Element;
// 动态 Disabled
editDynamicDisabled?: boolean | ((record: Recordable) => boolean);
} }
export type ColumnChangeParam = { export type ColumnChangeParam = {

Loading…
Cancel
Save