no message
parent
9300da4988
commit
63224c8786
|
|
@ -1,18 +1,20 @@
|
||||||
import { defHttp } from '/@/utils/http/axios';
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
import { useMessage } from "/@/hooks/web/useMessage";
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
|
||||||
const { createConfirm } = useMessage();
|
const { createConfirm } = useMessage();
|
||||||
|
|
||||||
enum Api {
|
enum Api {
|
||||||
list = '/agvTask/list',
|
list = '/agvTask/list',
|
||||||
save='/agvTask/add',
|
save = '/agvTask/add',
|
||||||
edit='/agvTask/edit',
|
edit = '/agvTask/edit',
|
||||||
deleteOne = '/agvTask/delete',
|
deleteOne = '/agvTask/delete',
|
||||||
deleteBatch = '/agvTask/deleteBatch',
|
deleteBatch = '/agvTask/deleteBatch',
|
||||||
importExcel = '/agvTask/importExcel',
|
importExcel = '/agvTask/importExcel',
|
||||||
exportXls = '/agvTask/exportXls',
|
exportXls = '/agvTask/exportXls',
|
||||||
taskReporter = '/api/robot/reporter/task',
|
taskReporter = '/api/robot/reporter/task',
|
||||||
callBackTask='/tes/apiv2/callBackTask',
|
callBackTask = '/tes/apiv2/callBackTask',
|
||||||
|
cancelTask = '/tes/apiv2/cancelTask',
|
||||||
|
resendTesTask = '/tes/apiv2/resendTesTask',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -37,11 +39,11 @@ export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||||
* @param params
|
* @param params
|
||||||
* @param handleSuccess
|
* @param handleSuccess
|
||||||
*/
|
*/
|
||||||
export const deleteOne = (params,handleSuccess) => {
|
export const deleteOne = (params, handleSuccess) => {
|
||||||
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
|
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
|
||||||
handleSuccess();
|
handleSuccess();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除
|
* 批量删除
|
||||||
|
|
@ -56,12 +58,20 @@ export const batchDelete = (params, handleSuccess) => {
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
|
return defHttp
|
||||||
handleSuccess();
|
.delete(
|
||||||
});
|
{
|
||||||
}
|
url: Api.deleteBatch,
|
||||||
|
data: params,
|
||||||
|
},
|
||||||
|
{ joinParamsToUrl: true }
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
handleSuccess();
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存或者更新
|
* 保存或者更新
|
||||||
|
|
@ -71,26 +81,53 @@ export const batchDelete = (params, handleSuccess) => {
|
||||||
export const saveOrUpdate = (params, isUpdate) => {
|
export const saveOrUpdate = (params, isUpdate) => {
|
||||||
let url = isUpdate ? Api.edit : Api.save;
|
let url = isUpdate ? Api.edit : Api.save;
|
||||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AGV任务上报
|
* AGV任务上报
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const taskReporter = (params) => {
|
export const taskReporter = (params) => {
|
||||||
return defHttp.post({url: Api.taskReporter, params}, {
|
return defHttp.post(
|
||||||
joinParamsToUrl: false,
|
{ url: Api.taskReporter, params },
|
||||||
isTransformResponse: false
|
{
|
||||||
});
|
isTransformResponse: false,
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TES任务上报
|
* TES任务上报
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const callBackTask = (params) => {
|
export const callBackTask = (params) => {
|
||||||
return defHttp.post({url: Api.callBackTask, params}, {
|
return defHttp.post(
|
||||||
joinParamsToUrl: false,
|
{ url: Api.callBackTask, params },
|
||||||
isTransformResponse: false
|
{
|
||||||
|
isTransformResponse: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务取消
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const cancelTask = (params) => {
|
||||||
|
return defHttp.post(
|
||||||
|
{ url: Api.cancelTask, params },
|
||||||
|
{
|
||||||
|
isTransformResponse: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务重送
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const resendTesTask = (params) => {
|
||||||
|
return defHttp.post({ url: Api.resendTesTask, params },{
|
||||||
|
isTransformResponse: false,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
</BasicTable>
|
</BasicTable>
|
||||||
<!-- 表单区域 -->
|
<!-- 表单区域 -->
|
||||||
<TesAgvModal ref="registerModal" @success="handleSuccess"></TesAgvModal>
|
<TesAgvModal ref="registerModal" @success="handleSuccess"></TesAgvModal>
|
||||||
|
<ResendTesAgvModal ref="registerResendModal" @success="handleSuccess"></ResendTesAgvModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -53,9 +54,9 @@
|
||||||
import { BasicTable, TableAction } from '/@/components/Table';
|
import { BasicTable, TableAction } from '/@/components/Table';
|
||||||
import { useListPage } from '/@/hooks/system/useListPage';
|
import { useListPage } from '/@/hooks/system/useListPage';
|
||||||
import { columns } from './TesAgv.data';
|
import { columns } from './TesAgv.data';
|
||||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, callBackTask } from './AgvTask.api';
|
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, callBackTask, cancelTask } from './AgvTask.api';
|
||||||
import TesAgvModal from './components/TesAgvModal.vue';
|
import TesAgvModal from './components/TesAgvModal.vue';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import ResendTesAgvModal from './components/ResendTesAgvModal.vue';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { getDateByPicker } from '/@/utils';
|
import { getDateByPicker } from '/@/utils';
|
||||||
|
|
||||||
|
|
@ -65,12 +66,11 @@
|
||||||
const queryParam = reactive<any>({
|
const queryParam = reactive<any>({
|
||||||
agvVendor: 'TES',
|
agvVendor: 'TES',
|
||||||
});
|
});
|
||||||
const toggleSearchStatus = ref<boolean>(false);
|
|
||||||
const registerModal = ref();
|
const registerModal = ref();
|
||||||
const userStore = useUserStore();
|
const registerResendModal = ref();
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage();
|
||||||
//注册table数据
|
//注册table数据
|
||||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
const { tableContext, onExportXls, onImportXls } = useListPage({
|
||||||
tableProps: {
|
tableProps: {
|
||||||
title: 'TES任务表',
|
title: 'TES任务表',
|
||||||
api: list,
|
api: list,
|
||||||
|
|
@ -100,8 +100,7 @@
|
||||||
success: handleSuccess,
|
success: handleSuccess,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
|
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||||
tableContext;
|
|
||||||
const labelCol = reactive({
|
const labelCol = reactive({
|
||||||
xs: 24,
|
xs: 24,
|
||||||
sm: 4,
|
sm: 4,
|
||||||
|
|
@ -168,15 +167,45 @@
|
||||||
const res = await callBackTask(params);
|
const res = await callBackTask(params);
|
||||||
if (res && res.returnCode === 0) {
|
if (res && res.returnCode === 0) {
|
||||||
createMessage.success('操作成功');
|
createMessage.success('操作成功');
|
||||||
handleSuccess();
|
|
||||||
} else {
|
} else {
|
||||||
createMessage.error(res.message || '任务处理失败');
|
createMessage.error(res.returnMsg || '任务处理失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createMessage.error('请求异常: ' + error.message);
|
createMessage.error('请求异常: ' + error.message);
|
||||||
|
} finally {
|
||||||
|
handleSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务取消事件
|
||||||
|
*/
|
||||||
|
async function hanndleCancel(record) {
|
||||||
|
const params = {
|
||||||
|
taskID: record.id,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const res = await cancelTask(params);
|
||||||
|
if (res && res.returnCode === 0) {
|
||||||
|
createMessage.success('操作成功');
|
||||||
|
} else {
|
||||||
|
createMessage.error(res.returnMsg || '任务处理失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
createMessage.error('请求异常: ' + error.message);
|
||||||
|
} finally {
|
||||||
|
handleSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务重发
|
||||||
|
*/
|
||||||
|
function hanndleResend(record) {
|
||||||
|
registerResendModal.value.disableSubmit = false;
|
||||||
|
registerResendModal.value.resend(record);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成功回调
|
* 成功回调
|
||||||
*/
|
*/
|
||||||
|
|
@ -214,10 +243,26 @@
|
||||||
placement: 'topLeft',
|
placement: 'topLeft',
|
||||||
},
|
},
|
||||||
auth: 'agvTask:data_agv_task:edit',
|
auth: 'agvTask:data_agv_task:edit',
|
||||||
disabled: record.status === 4 || record.status === 1,
|
disabled: record.status === 4 || record.status === 1 || record.status === 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '删除任务',
|
label: '任务取消',
|
||||||
|
popConfirm: {
|
||||||
|
title: '是否确认取消?',
|
||||||
|
confirm: hanndleCancel.bind(null, record),
|
||||||
|
placement: 'topLeft',
|
||||||
|
},
|
||||||
|
auth: 'agvTask:data_agv_task:edit',
|
||||||
|
disabled: record.status != 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '任务重送',
|
||||||
|
onClick: hanndleResend.bind(null, record),
|
||||||
|
auth: 'agvTask:data_agv_task:edit',
|
||||||
|
disabled: record.status != 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '任务删除',
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '是否确认删除?',
|
title: '是否确认删除?',
|
||||||
confirm: handleDelete.bind(null, record),
|
confirm: handleDelete.bind(null, record),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<template>
|
||||||
|
<a-spin :spinning="confirmLoading">
|
||||||
|
<JFormContainer>
|
||||||
|
<template #detail>
|
||||||
|
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="AgvTaskForm">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="容器" v-bind="validateInfos.carrierCode" id="AgvTaskForm-carrierCode" name="carrierCode">
|
||||||
|
<JDictSelectTag
|
||||||
|
v-model:value="formData.carrierCode"
|
||||||
|
placeholder="请选择容器"
|
||||||
|
dictCode="base_stock where iz_active=1 and del_flag=0,stock_code,stock_code"
|
||||||
|
allowClear
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<!-- <a-col :span="24">
|
||||||
|
<a-form-item label="任务类型" v-bind="validateInfos.taskType" id="AgvTaskForm-taskType" name="taskType">
|
||||||
|
<a-input v-model:value="formData.taskType" placeholder="请输入任务类型" allow-clear ></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>-->
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="业务类型" v-bind="validateInfos.type" id="AgvTaskForm-type" name="type">
|
||||||
|
<JDictSelectTag type="select" v-model:value="formData.type" dictCode="business_type" placeholder="请选择业务类型" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="任务状态" v-bind="validateInfos.status" id="AgvTaskForm-status" name="status">
|
||||||
|
<JDictSelectTag
|
||||||
|
type="select"
|
||||||
|
v-model:value="formData.status"
|
||||||
|
dictCode="agv_task_status"
|
||||||
|
placeholder="请选择任务状态"
|
||||||
|
:string-to-number="true"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="优先级" v-bind="validateInfos.priority" id="AgvTaskForm-priority" name="priority">
|
||||||
|
<a-input-number v-model:value="formData.priority" placeholder="请输入优先级" style="width: 100%" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="目标库位" v-bind="validateInfos.endCode" id="AgvTaskForm-endCode" name="endCode">
|
||||||
|
<JSearchSelect
|
||||||
|
v-model:value="formData.endCode"
|
||||||
|
placeholder="请选择目标库位"
|
||||||
|
dict="base_point where iz_active=1 and del_flag=0 ,point_code,point_code"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
</JFormContainer>
|
||||||
|
</a-spin>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, defineExpose, nextTick } from 'vue';
|
||||||
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { getTenantId } from '@/utils/auth';
|
||||||
|
import { cancelTask, resendTesTask } from '../AgvTask.api';
|
||||||
|
import { Form } from 'ant-design-vue';
|
||||||
|
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
||||||
|
import { JSearchSelect, JDictSelectTag } from '@/components/Form';
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
const emit = defineEmits(['register', 'ok']);
|
||||||
|
//仓库 ID
|
||||||
|
let tenantId = getTenantId();
|
||||||
|
const formData = reactive<Record<string, any>>({
|
||||||
|
id: '',
|
||||||
|
carrierCode: '',
|
||||||
|
carrierType: 'TRAY',
|
||||||
|
taskType: '',
|
||||||
|
type: '',
|
||||||
|
status: 'CREATED',
|
||||||
|
priority: 3,
|
||||||
|
startCode: '',
|
||||||
|
endCode: '',
|
||||||
|
agvVendor: 'TES',
|
||||||
|
tenantId: tenantId,
|
||||||
|
});
|
||||||
|
const { createMessage } = useMessage();
|
||||||
|
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
|
||||||
|
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||||
|
const confirmLoading = ref<boolean>(false);
|
||||||
|
//表单验证
|
||||||
|
const validatorRules = reactive({
|
||||||
|
carrierCode: [{ required: true, message: '请选择容器!' }],
|
||||||
|
type: [{ required: true, message: '请选择业务类型!' }],
|
||||||
|
priority: [{ required: true, message: '请输入优先级!' }],
|
||||||
|
endCode: [{ required: true, message: '请选择目标库位!' }],
|
||||||
|
status: [{ required: true, message: '请选择任务状态!' }],
|
||||||
|
});
|
||||||
|
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*/
|
||||||
|
function edit(record) {
|
||||||
|
nextTick(() => {
|
||||||
|
resetFields();
|
||||||
|
const tmpData = {};
|
||||||
|
Object.keys(formData).forEach((key) => {
|
||||||
|
if (record.hasOwnProperty(key)) {
|
||||||
|
tmpData[key] = record[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//赋值
|
||||||
|
Object.assign(formData, tmpData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交数据
|
||||||
|
*/
|
||||||
|
async function submitForm() {
|
||||||
|
try {
|
||||||
|
// 触发表单验证
|
||||||
|
await validate();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
confirmLoading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await resendTesTask(formData);
|
||||||
|
if (res && res.returnCode === 0) {
|
||||||
|
createMessage.success('操作成功');
|
||||||
|
emit('ok');
|
||||||
|
} else {
|
||||||
|
createMessage.error(res.returnMsg || '任务处理失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
createMessage.error('请求异常: ' + error.message);
|
||||||
|
} finally {
|
||||||
|
confirmLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
edit,
|
||||||
|
submitForm,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.antd-modal-form {
|
||||||
|
padding: 14px 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<template>
|
||||||
|
<j-modal
|
||||||
|
:title="title"
|
||||||
|
:maxHeight="400"
|
||||||
|
:width="600"
|
||||||
|
:visible="visible"
|
||||||
|
@ok="handleOk"
|
||||||
|
:okButtonProps="{ class: { 'jee-hidden': disableSubmit } }"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
cancelText="关闭"
|
||||||
|
>
|
||||||
|
<ResendTesAgvForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ResendTesAgvForm>
|
||||||
|
<template #footer>
|
||||||
|
<a-button @click="handleCancel">取消</a-button>
|
||||||
|
<a-button :class="{ 'jee-hidden': disableSubmit }" type="primary" @click="handleOk">确认 </a-button>
|
||||||
|
</template>
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, nextTick, defineExpose } from 'vue';
|
||||||
|
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
||||||
|
import ResendTesAgvForm from '@/views/agvTask/components/ResendTesAgvForm.vue';
|
||||||
|
|
||||||
|
const title = ref<string>('');
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const disableSubmit = ref<boolean>(false);
|
||||||
|
const registerForm = ref();
|
||||||
|
const emit = defineEmits(['register', 'success']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重送
|
||||||
|
*/
|
||||||
|
function resend(record) {
|
||||||
|
title.value = 'TES任务重送';
|
||||||
|
visible.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
registerForm.value.edit(record);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确定按钮点击事件
|
||||||
|
*/
|
||||||
|
function handleOk() {
|
||||||
|
registerForm.value.submitForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* form保存回调事件
|
||||||
|
*/
|
||||||
|
function submitCallback() {
|
||||||
|
handleCancel();
|
||||||
|
emit('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消按钮回调事件
|
||||||
|
*/
|
||||||
|
function handleCancel() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
resend,
|
||||||
|
disableSubmit,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
/**隐藏样式-modal确定按钮 */
|
||||||
|
.jee-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less" scoped></style>
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="24">
|
<a-col :span="24">
|
||||||
<a-form-item label="任务状态" v-bind="validateInfos.status" id="AgvTaskForm-status" name="status">
|
<a-form-item label="任务状态" v-bind="validateInfos.status" id="AgvTaskForm-status" name="status">
|
||||||
<JDictSelectTag type="select" v-model:value="formData.status" dictCode="agv_task_status" placeholder="请选择任务状态" />
|
<JDictSelectTag type="select" v-model:value="formData.status" dictCode="agv_task_status" placeholder="请选择任务状态" :string-to-number="true" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="24">
|
<a-col :span="24">
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,8 @@
|
||||||
import { ref, nextTick, defineExpose } from 'vue';
|
import { ref, nextTick, defineExpose } from 'vue';
|
||||||
import TesAgvForm from './TesAgvForm.vue';
|
import TesAgvForm from './TesAgvForm.vue';
|
||||||
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
|
||||||
|
|
||||||
const { createMessage } = useMessage();
|
|
||||||
const title = ref<string>('');
|
const title = ref<string>('');
|
||||||
const width = ref<number>(800);
|
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const disableSubmit = ref<boolean>(false);
|
const disableSubmit = ref<boolean>(false);
|
||||||
const registerForm = ref();
|
const registerForm = ref();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
|
|
||||||
|
enum Api {
|
||||||
|
showConveyorLine = '/api/conveyorLine/showConveyorLine',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showConveyorLine = (conveyorLine) => {
|
||||||
|
return defHttp.get(
|
||||||
|
{
|
||||||
|
url: Api.showConveyorLine,
|
||||||
|
params: { conveyorLine },
|
||||||
|
},
|
||||||
|
{ joinParamsToUrl: true }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,438 @@
|
||||||
|
<template>
|
||||||
|
<div class="monitor-container">
|
||||||
|
<header class="header">
|
||||||
|
<div class="header-left">
|
||||||
|
<div class="logo-box">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="logo-icon">
|
||||||
|
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
|
||||||
|
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="title-group">
|
||||||
|
<h1 class="system-title">WCS 输送线监控大屏</h1>
|
||||||
|
<div class="system-sub">CONVEYOR LINE MONITORING SYSTEM V4.2</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-right">
|
||||||
|
<div class="status-group">
|
||||||
|
<span class="status-dot online"></span>
|
||||||
|
<span class="status-text">SYSTEM ONLINE</span>
|
||||||
|
</div>
|
||||||
|
<div class="divider">|</div>
|
||||||
|
<div class="node-info">Node: CN-SH-01</div>
|
||||||
|
<div class="time-display">
|
||||||
|
<span class="time-big">{{ timeOnly }}</span>
|
||||||
|
<span class="date-small">{{ dateOnly }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="dashboard-card">
|
||||||
|
<section class="scan-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<span class="label-cn">当前扫描</span>
|
||||||
|
<span class="label-en">CURRENT SCAN</span>
|
||||||
|
</div>
|
||||||
|
<div class="scan-content">
|
||||||
|
<div class="scan-code">{{ scanData.stockCode }}</div>
|
||||||
|
<button class="pallet-btn">
|
||||||
|
<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" stroke-width="2" fill="none">
|
||||||
|
<path
|
||||||
|
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
{{ scanData.izAll }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="info-grid">
|
||||||
|
<div class="info-card type-card">
|
||||||
|
<div class="card-label">
|
||||||
|
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M17 1l4 4-4 4"></path>
|
||||||
|
<path d="M3 11V9a4 4 0 0 1 4-4h14"></path>
|
||||||
|
<path d="M7 23l-4-4 4-4"></path>
|
||||||
|
<path d="M21 13v2a4 4 0 0 1-4 4H3"></path>
|
||||||
|
</svg>
|
||||||
|
<span>任务类型 TASK TYPE</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-value value-purple">{{ scanData.taskType }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card dest-card">
|
||||||
|
<div class="card-label">
|
||||||
|
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
<path d="M12 21.7C17.3 17 20 13 20 10a8 8 0 1 0-16 0c0 3 2.7 7 8 11.7z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>目的站 DESTINATION</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-value value-pink">{{ scanData.endCode }}</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="remark-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<svg class="icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||||
|
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||||
|
</svg>
|
||||||
|
<span class="label-mix">特殊描述 / REMARKS</span>
|
||||||
|
</div>
|
||||||
|
<div class="remark-text">{{ scanData.description===''?'无到站任务!!!':scanData.description }}</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { showConveyorLine } from '@/views/conveyorLine/ConveyorLine.api';
|
||||||
|
|
||||||
|
// 模拟数据 (您可以替换为真实 Props 或 API 数据)
|
||||||
|
const scanData = ref({
|
||||||
|
stockCode: '',
|
||||||
|
taskType: '',
|
||||||
|
endCode: '',
|
||||||
|
izAll: '',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 时间处理
|
||||||
|
const now = ref(dayjs());
|
||||||
|
const updateTime = () => {
|
||||||
|
now.value = dayjs();
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeOnly = computed(() => now.value.format('HH:mm:ss'));
|
||||||
|
const dateOnly = computed(() => {
|
||||||
|
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||||
|
return `${now.value.format('YYYY/MM/DD')} ${weekDays[now.value.day()]}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
let timer;
|
||||||
|
onMounted(() => {
|
||||||
|
timer = setInterval(updateTime, 1000);
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(timer);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function queryData() {
|
||||||
|
const conveyorLine = 'CKJBK01';
|
||||||
|
const res = await showConveyorLine(conveyorLine);
|
||||||
|
scanData.value = {
|
||||||
|
stockCode: res.stockCode,
|
||||||
|
taskType: res.taskType,
|
||||||
|
endCode: res.endCode,
|
||||||
|
izAll: res.izAll,
|
||||||
|
description: res.description,
|
||||||
|
};
|
||||||
|
console.log('数据:' , res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定时更新查询数据
|
||||||
|
setInterval(() => {
|
||||||
|
console.log('更新数据');
|
||||||
|
queryData();
|
||||||
|
}, 3000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 引入等宽字体 (可选,如果有本地字体更好) */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@500;700&family=Inter:wght@400;600;800&display=swap');
|
||||||
|
|
||||||
|
/* --- 全局容器 --- */
|
||||||
|
.monitor-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #02050e; /* 极深黑背景 */
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 20px 32px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family:
|
||||||
|
'Inter',
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
'Helvetica Neue',
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- 1. Header 样式 --- */
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-box {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
background: linear-gradient(135deg, #007bff, #00d4ff);
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
stroke: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 800;
|
||||||
|
margin: 0;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-sub {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #8b9bb4; /* 稍微偏蓝灰 */
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #00e676;
|
||||||
|
box-shadow: 0 0 8px #00e676;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
color: #00e676;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-info {
|
||||||
|
color: #5d6e82;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-display {
|
||||||
|
text-align: right;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-big {
|
||||||
|
display: block;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-small {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #8b9bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- 2. 主卡片样式 (深蓝框) --- */
|
||||||
|
.dashboard-card {
|
||||||
|
background-color: #101524;
|
||||||
|
background-image: radial-gradient(circle at 100% 0%, rgba(56, 96, 246, 0.12) 0%, transparent 40%);
|
||||||
|
border: 1px solid rgba(47, 54, 77, 0.5);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 36px 48px;
|
||||||
|
height: calc(100vh - 110px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start; /* 内容上对齐 */
|
||||||
|
gap: 30px; /* 模块间距 */
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 当前扫描 */
|
||||||
|
.section-header {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #495057;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-cn {
|
||||||
|
color: #8b9bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scan-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #1f2029;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scan-code {
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
font-size: 80px; /* 超大字体 */
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
line-height: 1;
|
||||||
|
text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pallet-btn {
|
||||||
|
background: rgba(30, 36, 56, 0.6);
|
||||||
|
border: 1px solid #3d5afe;
|
||||||
|
color: #536dfe;
|
||||||
|
padding: 10px 24px;
|
||||||
|
border-radius: 30px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pallet-btn:hover {
|
||||||
|
background: #3d5afe;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 任务卡片栅格 */
|
||||||
|
.info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
background-color: rgba(255, 255, 255, 0.02);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px 32px;
|
||||||
|
height: 160px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* !* 增加一点微弱的渐变光晕背景 *!
|
||||||
|
.type-card {
|
||||||
|
background: radial-gradient(circle at 100% 0%, rgba(111, 66, 193, 0.1) 0%, transparent 50%), #11111a;
|
||||||
|
}
|
||||||
|
.dest-card {
|
||||||
|
background: radial-gradient(circle at 100% 0%, rgba(232, 62, 140, 0.1) 0%, transparent 50%), #11111a;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
.card-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
color: #6c7a92;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-label .icon {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 高亮颜色 */
|
||||||
|
|
||||||
|
.value-purple {
|
||||||
|
color: #00d2ff;
|
||||||
|
text-shadow: 0 0 15px rgba(0, 210, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-pink {
|
||||||
|
color: #c780ff; /* 浅紫 */
|
||||||
|
text-shadow: 0 0 15px rgba(199, 128, 255, 0.15);
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部备注 */
|
||||||
|
.remark-section {
|
||||||
|
background-color: rgba(255, 255, 255, 0.02);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px 32px;
|
||||||
|
flex: 1; /* 占满剩余高度 */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-mix {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6c757d;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-sm {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
color: #6c7a92;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remark-text {
|
||||||
|
font-size: 30px;
|
||||||
|
color: #d1d5db; /* 灰白色,不刺眼 */
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -137,6 +137,10 @@
|
||||||
width: 120,
|
width: 120,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
},
|
},
|
||||||
|
defSort: {
|
||||||
|
column: 'id',
|
||||||
|
order: 'desc',
|
||||||
|
},
|
||||||
showActionColumn: false,
|
showActionColumn: false,
|
||||||
beforeFetch: async (params) => {
|
beforeFetch: async (params) => {
|
||||||
for (let key in fieldPickers) {
|
for (let key in fieldPickers) {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
import {defHttp} from '/@/utils/http/axios';
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
import { useMessage } from "/@/hooks/web/useMessage";
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
|
||||||
const { createConfirm } = useMessage();
|
const { createConfirm } = useMessage();
|
||||||
|
|
||||||
enum Api {
|
enum Api {
|
||||||
list = '/shipping/pick/list',
|
list = '/shipping/pick/list',
|
||||||
save='/shipping/pick/add',
|
save = '/shipping/pick/add',
|
||||||
edit='/shipping/pick/edit',
|
edit = '/shipping/pick/edit',
|
||||||
deleteOne = '/shipping/pick/delete',
|
deleteOne = '/shipping/pick/delete',
|
||||||
deleteBatch = '/shipping/pick/deleteBatch',
|
deleteBatch = '/shipping/pick/deleteBatch',
|
||||||
importExcel = '/shipping/pick/importExcel',
|
importExcel = '/shipping/pick/importExcel',
|
||||||
exportXls = '/shipping/pick/exportXls',
|
exportXls = '/shipping/pick/exportXls',
|
||||||
queryDataById = '/shipping/pick/queryById',
|
queryDataById = '/shipping/pick/queryById',
|
||||||
pickDetailList = '/shipping/pick/queryPickDetailByMainId',
|
pickDetailList = '/shipping/pick/queryPickDetailByMainId',
|
||||||
|
allocatePick = '/shipping/pick/allocatePick',
|
||||||
|
cancelAllocate = '/shipping/pick/cancelAllocate',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出api
|
* 导出api
|
||||||
* @param params
|
* @param params
|
||||||
|
|
@ -29,23 +32,26 @@ export const getImportUrl = Api.importExcel;
|
||||||
* 查询子表数据
|
* 查询子表数据
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const queryPickDetailListByMainId = (id) => defHttp.get({url: Api.pickDetailList, params:{ id }});
|
export const queryPickDetailListByMainId = (id) =>
|
||||||
|
defHttp.get({
|
||||||
|
url: Api.pickDetailList,
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 列表接口
|
* 列表接口
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const list = (params) =>
|
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||||
defHttp.get({url: Api.list, params});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除单个
|
* 删除单个
|
||||||
*/
|
*/
|
||||||
export const deleteOne = (params,handleSuccess) => {
|
export const deleteOne = (params, handleSuccess) => {
|
||||||
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
|
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
|
||||||
handleSuccess();
|
handleSuccess();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 批量删除
|
* 批量删除
|
||||||
* @param params
|
* @param params
|
||||||
|
|
@ -58,24 +64,51 @@ export const batchDelete = (params, handleSuccess) => {
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
|
return defHttp
|
||||||
handleSuccess();
|
.delete(
|
||||||
});
|
{
|
||||||
}
|
url: Api.deleteBatch,
|
||||||
|
data: params,
|
||||||
|
},
|
||||||
|
{ joinParamsToUrl: true }
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
handleSuccess();
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 保存或者更新
|
* 保存或者更新
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const saveOrUpdate = (params, isUpdate) => {
|
export const saveOrUpdate = (params, isUpdate) => {
|
||||||
let url = isUpdate ? Api.edit : Api.save;
|
let url = isUpdate ? Api.edit : Api.save;
|
||||||
return defHttp.post({url: url, params});
|
return defHttp.post({ url: url, params });
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据id查询数据
|
* 根据id查询数据
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const queryDataById = (id) => defHttp.get({url: Api.queryDataById, params:{ id }});
|
export const queryDataById = (id) => defHttp.get({ url: Api.queryDataById, params: { id } });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配出库单
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const allocatePick = (ids,handleSuccess) => {
|
||||||
|
return defHttp.get({ url: Api.allocatePick, params: { ids } }, { joinParamsToUrl: true }).then(() => {
|
||||||
|
handleSuccess();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消分配
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const cancelAllocate = (ids,handleSuccess) => {
|
||||||
|
return defHttp.get({ url: Api.cancelAllocate, params: { ids } }, { joinParamsToUrl: true }).then(() => {
|
||||||
|
handleSuccess();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,25 @@ export const columns: BasicColumn[] = [
|
||||||
title: '系统单号',
|
title: '系统单号',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'orderNo',
|
dataIndex: 'orderNo',
|
||||||
|
width: '130px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '外部单号',
|
title: '外部单号',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'thirdOrderNo',
|
dataIndex: 'thirdOrderNo',
|
||||||
|
width: '130px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '任务号',
|
title: '任务号',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'no',
|
dataIndex: 'no',
|
||||||
|
width: '130px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '订单状态',
|
title: '订单状态',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'status_dictText',
|
dataIndex: 'status_dictText',
|
||||||
|
width: '100px',
|
||||||
customRender: ({ text }) => {
|
customRender: ({ text }) => {
|
||||||
//出库状态:1.已创建;2.部分分配;3.已分配;4.拣货中;5.拣货完成;6.已关闭;7.已取消。
|
//出库状态:1.已创建;2.部分分配;3.已分配;4.拣货中;5.拣货完成;6.已关闭;7.已取消。
|
||||||
const statusColorMap = {
|
const statusColorMap = {
|
||||||
|
|
@ -41,38 +45,38 @@ export const columns: BasicColumn[] = [
|
||||||
title: '单据类型',
|
title: '单据类型',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'orderType_dictText',
|
dataIndex: 'orderType_dictText',
|
||||||
|
width: '100px',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '需求数量',
|
title: '需求数量',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'orderQty',
|
dataIndex: 'orderQty',
|
||||||
|
width: '80px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分配数量',
|
title: '分配数量',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'allocatedQty',
|
dataIndex: 'allocatedQty',
|
||||||
|
width: '80px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '拣货数量',
|
title: '拣货数量',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'pickedQty',
|
dataIndex: 'pickedQty',
|
||||||
|
width: '80px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '外部仓库',
|
title: '外部仓库',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'whCode',
|
dataIndex: 'whCode',
|
||||||
|
width: '80px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '客户代码',
|
title: '客户',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
dataIndex: 'customerCode',
|
dataIndex: 'customerCode',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '外部仓库',
|
|
||||||
align: 'center',
|
|
||||||
dataIndex: 'whCode',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '订单日期',
|
title: '订单日期',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
|
@ -108,7 +112,7 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
key: 'unit',
|
key: 'unit',
|
||||||
type: JVxeTypes.select,
|
type: JVxeTypes.select,
|
||||||
dictCode: 'package_unit',
|
dictCode: 'package_unit',
|
||||||
width: '130px',
|
width: '80px',
|
||||||
placeholder: '请选择${title}',
|
placeholder: '请选择${title}',
|
||||||
defaultValue: '托',
|
defaultValue: '托',
|
||||||
},
|
},
|
||||||
|
|
@ -116,7 +120,7 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
title: '需求数量',
|
title: '需求数量',
|
||||||
key: 'orderQty',
|
key: 'orderQty',
|
||||||
type: JVxeTypes.inputNumber,
|
type: JVxeTypes.inputNumber,
|
||||||
width: '130px',
|
width: '110px',
|
||||||
validateRules: [
|
validateRules: [
|
||||||
{
|
{
|
||||||
required: true, // 必填
|
required: true, // 必填
|
||||||
|
|
@ -128,7 +132,7 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
title: '分配数量',
|
title: '分配数量',
|
||||||
key: 'allocatedQty',
|
key: 'allocatedQty',
|
||||||
type: JVxeTypes.normal,
|
type: JVxeTypes.normal,
|
||||||
width: '130px',
|
width: '80px',
|
||||||
defaultValue: '0',
|
defaultValue: '0',
|
||||||
disabled: true,
|
disabled: true,
|
||||||
},
|
},
|
||||||
|
|
@ -136,7 +140,7 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
title: '拣货数量',
|
title: '拣货数量',
|
||||||
key: 'pickedQty',
|
key: 'pickedQty',
|
||||||
type: JVxeTypes.normal,
|
type: JVxeTypes.normal,
|
||||||
width: '130px',
|
width: '80px',
|
||||||
placeholder: '请输入${title}',
|
placeholder: '请输入${title}',
|
||||||
defaultValue: '0',
|
defaultValue: '0',
|
||||||
disabled: true,
|
disabled: true,
|
||||||
|
|
@ -145,7 +149,7 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
title: '明细状态',
|
title: '明细状态',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
type: JVxeTypes.normal,
|
type: JVxeTypes.normal,
|
||||||
width: '120px',
|
width: '80px',
|
||||||
defaultValue: '1',
|
defaultValue: '1',
|
||||||
formatter: ({ cellValue }) => {
|
formatter: ({ cellValue }) => {
|
||||||
//入库状态:1.已创建;2.部分收货;3.收货完成;4.已取消。
|
//入库状态:1.已创建;2.部分收货;3.收货完成;4.已取消。
|
||||||
|
|
@ -205,4 +209,10 @@ export const pickDetailColumns: JVxeColumn[] = [
|
||||||
placeholder: '请输入${title}',
|
placeholder: '请输入${title}',
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '返回报文',
|
||||||
|
key: 'resMessage',
|
||||||
|
type: JVxeTypes.normal,
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,25 @@
|
||||||
<!--插槽:table标题-->
|
<!--插槽:table标题-->
|
||||||
<template #tableTitle>
|
<template #tableTitle>
|
||||||
<a-button type="primary" v-auth="'shipping:data_pick:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增 </a-button>
|
<a-button type="primary" v-auth="'shipping:data_pick:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增 </a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
:loading="allocate_loading"
|
||||||
|
v-auth="'shipping:data_pick:allocatePick'"
|
||||||
|
@click="handleAllocatePick"
|
||||||
|
preIcon="ant-design:edit-outlined"
|
||||||
|
>
|
||||||
|
分配
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
:loading="cancel_loading"
|
||||||
|
v-auth="'shipping:data_pick:cancelAllocate'"
|
||||||
|
@click="handleCancelAllocate"
|
||||||
|
preIcon="ant-design:edit-outlined"
|
||||||
|
>
|
||||||
|
取消分配
|
||||||
|
</a-button>
|
||||||
<a-button type="primary" v-auth="'shipping:data_pick:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出 </a-button>
|
<a-button type="primary" v-auth="'shipping:data_pick:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出 </a-button>
|
||||||
<j-upload-button type="primary" v-auth="'shipping:data_pick:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls"
|
<j-upload-button type="primary" v-auth="'shipping:data_pick:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls"
|
||||||
>导入
|
>导入
|
||||||
|
|
@ -94,7 +113,7 @@
|
||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal';
|
||||||
import PickModal from './components/PickModal.vue';
|
import PickModal from './components/PickModal.vue';
|
||||||
import { columns } from './Pick.data';
|
import { columns } from './Pick.data';
|
||||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './Pick.api';
|
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, allocatePick, cancelAllocate } from './Pick.api';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { getDateByPicker } from '/@/utils';
|
import { getDateByPicker } from '/@/utils';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
|
|
@ -102,6 +121,8 @@
|
||||||
import { JInput, JDictSelectTag } from '@/components/Form';
|
import { JInput, JDictSelectTag } from '@/components/Form';
|
||||||
import JRangeDate from '@/components/Form/src/jeecg/components/JRangeDate.vue';
|
import JRangeDate from '@/components/Form/src/jeecg/components/JRangeDate.vue';
|
||||||
|
|
||||||
|
const allocate_loading = ref(false);
|
||||||
|
const cancel_loading = ref(false);
|
||||||
const fieldPickers = reactive({});
|
const fieldPickers = reactive({});
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const queryParam = reactive<any>({});
|
const queryParam = reactive<any>({});
|
||||||
|
|
@ -156,7 +177,7 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增事件
|
* 新增事件
|
||||||
|
|
@ -168,6 +189,67 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配事件
|
||||||
|
*/
|
||||||
|
async function handleAllocatePick() {
|
||||||
|
if (selectedRowKeys.value.length === 0) {
|
||||||
|
return createMessage.error('请选择出库单');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中的数据中状态有1、2、4 返回true,否则返回false
|
||||||
|
const validStatuses = [1, 2, 4];
|
||||||
|
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
|
||||||
|
if (!allValidStatus) {
|
||||||
|
return createMessage.error('【已创建、 部分分配、部分拣货】状态的出库单才允许分配');
|
||||||
|
}
|
||||||
|
if (allocate_loading.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置加载状态,防止重复提交
|
||||||
|
allocate_loading.value = true;
|
||||||
|
try {
|
||||||
|
await allocatePick(selectedRowKeys.value, handleSuccess);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('分配失败:', e);
|
||||||
|
handleSuccess()
|
||||||
|
} finally {
|
||||||
|
// 重置加载状态
|
||||||
|
allocate_loading.value = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消分配
|
||||||
|
*/
|
||||||
|
async function handleCancelAllocate() {
|
||||||
|
if (selectedRowKeys.value.length === 0) {
|
||||||
|
return createMessage.error('请选择出库单');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中的数据中状态有2、3 返回true,否则返回false
|
||||||
|
const validStatuses = [2, 3];
|
||||||
|
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
|
||||||
|
if (!allValidStatus) {
|
||||||
|
return createMessage.error('【部分分配、已分配】状态的出库单才允许取消分配');
|
||||||
|
}
|
||||||
|
if (cancel_loading.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置加载状态,防止重复提交
|
||||||
|
cancel_loading.value = true;
|
||||||
|
try {
|
||||||
|
await cancelAllocate(selectedRowKeys.value, handleSuccess);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('取消失败:', e);
|
||||||
|
handleSuccess()
|
||||||
|
} finally {
|
||||||
|
// 重置加载状态
|
||||||
|
cancel_loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑事件
|
* 编辑事件
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue