fix: 第一版普遍修复完成。
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# 线上环境接口地址
|
# 线上环境接口地址
|
||||||
VITE_API_URL = "/pro"
|
VITE_API_URL = "/api"
|
||||||
|
|
||||||
# 静态文件获取根路径
|
# 静态文件获取根路径
|
||||||
VITE_PUBLIC_PATH = "/"
|
VITE_PUBLIC_PATH = "/"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "teek-design-vue3-template",
|
"name": "erp-frontend",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "牛安后台管理系统",
|
"description": "牛安后台管理系统",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const UserService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
checkIsLogined() {
|
checkIsLogined() {
|
||||||
return get("/open/check-login");
|
return get("/auth/check-login");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,12 +29,12 @@ export const UserService = {
|
|||||||
* 用于前端页面刷新后检测当前token是否有效
|
* 用于前端页面刷新后检测当前token是否有效
|
||||||
*/
|
*/
|
||||||
checkLogin() {
|
checkLogin() {
|
||||||
return get("/open/check-login");
|
return get("/auth/check-login");
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
getUserInfo() {
|
getUserInfo() {
|
||||||
return get("/auth/getUserInfo");
|
return get("/auth/check-login");
|
||||||
},
|
},
|
||||||
|
|
||||||
getDynamicRouter() {
|
getDynamicRouter() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useUserStore } from "@/pinia";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import type { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
|
import type { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
import { $t } from "@/common/languages";
|
||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service: AxiosInstance = axios.create({
|
const service: AxiosInstance = axios.create({
|
||||||
@@ -24,7 +25,7 @@ service.interceptors.request.use(
|
|||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
ElMessage.error("请求发送失败");
|
ElMessage.error($t("_http.request_failed"));
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -38,31 +39,34 @@ service.interceptors.response.use(
|
|||||||
// 通常 code === 0 表示成功
|
// 通常 code === 0 表示成功
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res as any; // 直接返回业务数据
|
return res as any; // 直接返回业务数据
|
||||||
|
} else if (res.code === 3) {
|
||||||
|
ElMessage.error(res.msg || $t("_http.invalid_credentials"));
|
||||||
|
return Promise.reject(new Error(res.msg || $t("_http.invalid_credentials")));
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.msg || "请求失败");
|
ElMessage.error(res.msg || $t("_http.request_error"));
|
||||||
return Promise.reject(new Error(res.msg || "Error"));
|
return Promise.reject(new Error(res.msg || "Error"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
// 处理网络错误或 HTTP 状态码非 2xx 的情况
|
// 处理网络错误或 HTTP 状态码非 2xx 的情况
|
||||||
let message = "网络异常";
|
let message = $t("_http.network_error");
|
||||||
const { isLogined } = storeToRefs(useUserStore());
|
const { isLogined } = storeToRefs(useUserStore());
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
const status = error.response.status;
|
const status = error.response.status;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 401:
|
case 401:
|
||||||
message = "未登录或会话已过期,请重新登录";
|
message = $t("_http.unauthorized");
|
||||||
isLogined.value = false;
|
isLogined.value = false;
|
||||||
useRouter().push("/login");
|
useRouter().push("/login");
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
message = "权限不足";
|
message = $t("_http.forbidden");
|
||||||
break;
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
message = "服务器内部错误";
|
message = $t("_http.server_error");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
message = `请求失败 ( $ {status})`;
|
message = $t("_http.request_failed_status", { status });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElMessage.error(message);
|
ElMessage.error(message);
|
||||||
|
|||||||
@@ -729,6 +729,12 @@ export default {
|
|||||||
generate_order_error: "Generate Failed",
|
generate_order_error: "Generate Failed",
|
||||||
vendor_priority_tip: "Priority",
|
vendor_priority_tip: "Priority",
|
||||||
},
|
},
|
||||||
|
purchase_plan_item: {
|
||||||
|
input_partNumber: "Please enter part number",
|
||||||
|
input_purchaseCount: "Please enter plan count",
|
||||||
|
input_price: "Please enter price",
|
||||||
|
input_currentCount: "Please enter current count",
|
||||||
|
},
|
||||||
purchaseorder: {
|
purchaseorder: {
|
||||||
delete_message: "Delete Order",
|
delete_message: "Delete Order",
|
||||||
part_number_not_exists: "Part number does not exist",
|
part_number_not_exists: "Part number does not exist",
|
||||||
@@ -917,9 +923,11 @@ export default {
|
|||||||
tableTitle: "Purchase Details",
|
tableTitle: "Purchase Details",
|
||||||
templateFileName: "Purchase Plan Template",
|
templateFileName: "Purchase Plan Template",
|
||||||
},
|
},
|
||||||
purchaseorder: {
|
purchase_order: {
|
||||||
add: "Add Purchase Order",
|
add: "Add Purchase Order",
|
||||||
edit: "Edit Purchase Order",
|
edit: "Edit Purchase Order",
|
||||||
|
inbound: "Purchase Inbound",
|
||||||
|
qrcode: "Print QR Code",
|
||||||
showItem: "Order Items",
|
showItem: "Order Items",
|
||||||
baseTitle: "Purchase Order Basic Info",
|
baseTitle: "Purchase Order Basic Info",
|
||||||
tableTitle: "Order Details",
|
tableTitle: "Order Details",
|
||||||
@@ -1235,5 +1243,16 @@ export default {
|
|||||||
_status: {
|
_status: {
|
||||||
in_progress: "In Progress",
|
in_progress: "In Progress",
|
||||||
completed: "Completed",
|
completed: "Completed",
|
||||||
|
receipting: "Receipting",
|
||||||
|
},
|
||||||
|
_http: {
|
||||||
|
request_failed: "Request failed",
|
||||||
|
invalid_credentials: "Invalid username or password",
|
||||||
|
request_error: "Request error",
|
||||||
|
network_error: "Network error",
|
||||||
|
unauthorized: "Not logged in or session expired, please log in again",
|
||||||
|
forbidden: "Permission denied",
|
||||||
|
server_error: "Server internal error",
|
||||||
|
request_failed_status: "Request failed ({status})",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -760,6 +760,12 @@ export default {
|
|||||||
generate_order_error: "生成采购订单失败",
|
generate_order_error: "生成采购订单失败",
|
||||||
vendor_priority_tip: "优先",
|
vendor_priority_tip: "优先",
|
||||||
},
|
},
|
||||||
|
purchase_plan_item: {
|
||||||
|
input_partNumber: "请输入物料编号",
|
||||||
|
input_purchaseCount: "请输入计划数量",
|
||||||
|
input_price: "请输入单价",
|
||||||
|
input_currentCount: "请输入本次采购数量",
|
||||||
|
},
|
||||||
purchase_order: {
|
purchase_order: {
|
||||||
delete_message: "删除采购订单",
|
delete_message: "删除采购订单",
|
||||||
input_vendorName: "请选择供应商",
|
input_vendorName: "请选择供应商",
|
||||||
@@ -1008,6 +1014,9 @@ export default {
|
|||||||
add: "新建采购计划",
|
add: "新建采购计划",
|
||||||
edit: "编辑采购计划",
|
edit: "编辑采购计划",
|
||||||
generateOrder: "生成采购订单",
|
generateOrder: "生成采购订单",
|
||||||
|
showItem: "采购明细",
|
||||||
|
baseTitle: "采购计划基本信息",
|
||||||
|
tableTitle: "采购明细",
|
||||||
model: "型号",
|
model: "型号",
|
||||||
defaultVendor: "默认供应商",
|
defaultVendor: "默认供应商",
|
||||||
demandQuantity: "需求量",
|
demandQuantity: "需求量",
|
||||||
@@ -1023,6 +1032,7 @@ export default {
|
|||||||
edit: "编辑采购订单",
|
edit: "编辑采购订单",
|
||||||
inbound: "采购入库",
|
inbound: "采购入库",
|
||||||
qrcode: "二维码打印",
|
qrcode: "二维码打印",
|
||||||
|
showItem: "采购明细",
|
||||||
baseTitle: "采购订单基本信息",
|
baseTitle: "采购订单基本信息",
|
||||||
tableTitle: "采购明细",
|
tableTitle: "采购明细",
|
||||||
templateFileName: "采购订单模板",
|
templateFileName: "采购订单模板",
|
||||||
@@ -1337,5 +1347,16 @@ export default {
|
|||||||
_status: {
|
_status: {
|
||||||
in_progress: "入库中",
|
in_progress: "入库中",
|
||||||
completed: "已完成",
|
completed: "已完成",
|
||||||
|
receipting: "入库中",
|
||||||
|
},
|
||||||
|
_http: {
|
||||||
|
request_failed: "请求发送失败",
|
||||||
|
invalid_credentials: "用户名或密码错误",
|
||||||
|
request_error: "请求失败",
|
||||||
|
network_error: "网络异常",
|
||||||
|
unauthorized: "未登录或会话已过期,请重新登录",
|
||||||
|
forbidden: "权限不足",
|
||||||
|
server_error: "服务器内部错误",
|
||||||
|
request_failed_status: "请求失败 ({status})",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ watch(visible, newVal => {
|
|||||||
width="450px"
|
width="450px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:close-on-press-escape="false"
|
:close-on-press-escape="false"
|
||||||
|
:lock-scroll="false"
|
||||||
>
|
>
|
||||||
<div v-loading="loading" class="qrcode-container">
|
<div v-loading="loading" class="qrcode-container">
|
||||||
<div v-if="props.qrCodeList.length > 0" class="qrcode-list-container">
|
<div v-if="props.qrCodeList.length > 0" class="qrcode-list-container">
|
||||||
|
|||||||
@@ -59,33 +59,34 @@ export const useUserStore = defineStore(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getUserInfo = async () => {
|
const getUserInfo = async () => {
|
||||||
// 模拟获取用户信息
|
return await UserService.getUserInfo().then(res => {
|
||||||
// return await UserService.getUserInfo().then(res => {
|
setRoles(res.data.roles);
|
||||||
// setRoles(res.data.roles);
|
setUserInfo(res.data.userInfo);
|
||||||
// setUserInfo(res.data);
|
return res.data.userInfo;
|
||||||
// return res.data;
|
});
|
||||||
|
|
||||||
|
// return {};
|
||||||
|
|
||||||
|
// const userInfo = await new Promise<UserInfo>(resolve => {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// resolve({
|
||||||
|
// userId: "v10001",
|
||||||
|
// username: "Admin",
|
||||||
|
// sex: "保密",
|
||||||
|
// signature: "这个人很懒,什么都没有写",
|
||||||
|
// email: "1234567890@qq.com",
|
||||||
|
// phone: "1234567890",
|
||||||
|
// avatar: "https://cdn.jsdelivr.net/gh/Kele-Bingtang/static/user/avatar1.png",
|
||||||
|
// roles: ["admin"],
|
||||||
|
// job: "开发工程师",
|
||||||
|
// dept: "Teek 云科技技术部 - 智能全栈科",
|
||||||
|
// registerTime: "2022-10-01 19:07:27",
|
||||||
|
// });
|
||||||
|
// }, 500);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
const userInfo = await new Promise<UserInfo>(resolve => {
|
// setUserInfo(userInfo);
|
||||||
setTimeout(() => {
|
// return userInfo;
|
||||||
resolve({
|
|
||||||
userId: "v10001",
|
|
||||||
username: "Admin",
|
|
||||||
sex: "保密",
|
|
||||||
signature: "这个人很懒,什么都没有写",
|
|
||||||
email: "1234567890@qq.com",
|
|
||||||
phone: "1234567890",
|
|
||||||
avatar: "https://cdn.jsdelivr.net/gh/Kele-Bingtang/static/user/avatar1.png",
|
|
||||||
roles: ["admin"],
|
|
||||||
job: "开发工程师",
|
|
||||||
dept: "Teek 云科技技术部 - 智能全栈科",
|
|
||||||
registerTime: "2022-10-01 19:07:27",
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
setUserInfo(userInfo);
|
|
||||||
return userInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -53,16 +53,16 @@ const login = () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
// 执行登录
|
// 执行登录
|
||||||
await userStore.login({ ...loginForm });
|
const result = await userStore.login({ ...loginForm });
|
||||||
// if (!result) {
|
if (!result) {
|
||||||
// ElNotification({
|
ElNotification({
|
||||||
// title: getTimeState(),
|
title: getTimeState(),
|
||||||
// message: "登录失败,用户名或密码错误",
|
message: "登录失败,用户名或密码错误",
|
||||||
// type: "success",
|
type: "success",
|
||||||
// duration: 3000,
|
duration: 3000,
|
||||||
// });
|
});
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 跳转到首页或者 URL 携带的 redirect 页(优先级高)
|
// 跳转到首页或者 URL 携带的 redirect 页(优先级高)
|
||||||
let path = HOME_URL;
|
let path = HOME_URL;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ const operateButtonClick = (eventName: string, row: any) => {
|
|||||||
|
|
||||||
const mappingConfig: FieldMappingConfig = {
|
const mappingConfig: FieldMappingConfig = {
|
||||||
partNumber: {
|
partNumber: {
|
||||||
sourceKey: ["商品编号", "partNumber"],
|
sourceKey: ["编号", "物料编号", "商品编号", "partNumber"],
|
||||||
header: $t("_prop.production.bom_item.partNumber"),
|
header: $t("_prop.production.bom_item.partNumber"),
|
||||||
width: 20,
|
width: 20,
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
|
|||||||
@@ -238,6 +238,8 @@ const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
|
|||||||
if (row.status === 1 && button.eventName === "approve") return false;
|
if (row.status === 1 && button.eventName === "approve") return false;
|
||||||
// 已审核后不能编辑和删除
|
// 已审核后不能编辑和删除
|
||||||
if (row.status === 1 && (button.eventName === "edit" || button.eventName === "remove")) return false;
|
if (row.status === 1 && (button.eventName === "edit" || button.eventName === "remove")) return false;
|
||||||
|
// 退料按钮只在已审核状态下展示
|
||||||
|
if (button.eventName === "productionReturn" && row.status !== 1) return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { $t } from "@/common/languages";
|
|||||||
import { ElMessage, ElMessageBox, type FormInstance, type FormItemRule, type FormRules } from "element-plus";
|
import { ElMessage, ElMessageBox, type FormInstance, type FormItemRule, type FormRules } from "element-plus";
|
||||||
import BaseFormWithTable from "@/components/base/base-form-with-table/BaseFormWithTable.vue";
|
import BaseFormWithTable from "@/components/base/base-form-with-table/BaseFormWithTable.vue";
|
||||||
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
|
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
|
||||||
|
import BaseItemDialog from "@/components/base/base-item-dialog/BaseItemDialog.vue";
|
||||||
import ExpandablePageableTable from "@/components/base/expandable-pageable-table/ExpandablePageableTable.vue";
|
import ExpandablePageableTable from "@/components/base/expandable-pageable-table/ExpandablePageableTable.vue";
|
||||||
import BaseSelect from "@/components/base/base-select/BaseSelect.vue";
|
import BaseSelect from "@/components/base/base-select/BaseSelect.vue";
|
||||||
import QrCodeDialog from "@/components/base/base-qrcode/QrCodeDialog.vue";
|
import QrCodeDialog from "@/components/base/base-qrcode/QrCodeDialog.vue";
|
||||||
@@ -29,12 +30,14 @@ const partNumberExistsUrl = "/warehouse/warehouseitem/existsWarehouseItem";
|
|||||||
|
|
||||||
const searchers = [
|
const searchers = [
|
||||||
{ name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_order.searchCode") },
|
{ name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_order.searchCode") },
|
||||||
|
{ name: "partNumber", type: "text" as const, placeholder: $t("_prop.purchase.purchase_order_item.partNumber") },
|
||||||
];
|
];
|
||||||
|
|
||||||
const getFormStatusLabel = (status: number) => {
|
const getFormStatusLabel = (status: number) => {
|
||||||
const labels: Record<number, string> = {
|
const labels: Record<number, string> = {
|
||||||
0: $t("_status.in_progress"),
|
0: $t("_status.in_progress"),
|
||||||
4: $t("_status.completed"),
|
4: $t("_status.completed"),
|
||||||
|
5: $t("_status.receipting"),
|
||||||
};
|
};
|
||||||
return labels[status] ?? String(status);
|
return labels[status] ?? String(status);
|
||||||
};
|
};
|
||||||
@@ -60,7 +63,7 @@ const validatePartNumber = (rule: any, value: string, callback: (error?: Error)
|
|||||||
};
|
};
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
vendorName: [{ required: true, message: $t("_message.purchase.purchase_order.input_vendorName"), trigger: "blur" }],
|
vendorNo: [{ required: true, message: $t("_message.purchase.purchase_order.select_vendor"), trigger: "change" }],
|
||||||
partNumber: [
|
partNumber: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -97,7 +100,7 @@ const inboundForm = reactive({
|
|||||||
orderCode: "",
|
orderCode: "",
|
||||||
vendorName: "",
|
vendorName: "",
|
||||||
formCode: "",
|
formCode: "",
|
||||||
storeNo: null as number,
|
storeNo: null as number | null,
|
||||||
storeName: "",
|
storeName: "",
|
||||||
formMark: "",
|
formMark: "",
|
||||||
items: [] as any[],
|
items: [] as any[],
|
||||||
@@ -106,6 +109,10 @@ const inboundForm = reactive({
|
|||||||
const qrCodeVisible = ref(false);
|
const qrCodeVisible = ref(false);
|
||||||
const qrCodeData = ref<any[]>([]);
|
const qrCodeData = ref<any[]>([]);
|
||||||
|
|
||||||
|
const showItemVisible = ref(false);
|
||||||
|
const showItemData = ref<any[]>([]);
|
||||||
|
const showItemRow = ref<any>(null);
|
||||||
|
|
||||||
const mappingConfig: FieldMappingConfig = {
|
const mappingConfig: FieldMappingConfig = {
|
||||||
partNumber: {
|
partNumber: {
|
||||||
sourceKey: "物料编号",
|
sourceKey: "物料编号",
|
||||||
@@ -266,6 +273,11 @@ const showQrCode = async (row: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showItem = (row: any) => {
|
||||||
|
showItemRow.value = row;
|
||||||
|
showItemVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
const submit = (formData: any, formRef: FormInstance | undefined) => {
|
const submit = (formData: any, formRef: FormInstance | undefined) => {
|
||||||
if (formRef !== undefined) {
|
if (formRef !== undefined) {
|
||||||
formRef.validate(valid => {
|
formRef.validate(valid => {
|
||||||
@@ -307,6 +319,9 @@ const operateButtonClick = (eventName: string, row: any) => {
|
|||||||
case "printQrCode":
|
case "printQrCode":
|
||||||
showQrCode(row);
|
showQrCode(row);
|
||||||
break;
|
break;
|
||||||
|
case "showItem":
|
||||||
|
showItem(row);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -368,6 +383,7 @@ const getFormStatusTagType = (code: number | null): string => {
|
|||||||
:item-url="getItemsUrl"
|
:item-url="getItemsUrl"
|
||||||
item-id-key="id"
|
item-id-key="id"
|
||||||
item-id-name="orderId"
|
item-id-name="orderId"
|
||||||
|
item-field-name="items"
|
||||||
>
|
>
|
||||||
<template #tool-button>
|
<template #tool-button>
|
||||||
<DefaultToolButton @top-button-click="topButtonClick" />
|
<DefaultToolButton @top-button-click="topButtonClick" />
|
||||||
@@ -434,9 +450,9 @@ const getFormStatusTagType = (code: number | null): string => {
|
|||||||
<el-form-item prop="id" v-if="false"><el-input v-model="form.id" /></el-form-item>
|
<el-form-item prop="id" v-if="false"><el-input v-model="form.id" /></el-form-item>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item :label="$t('_prop.purchase.purchase_order.vendorName')" prop="vendorName">
|
<el-form-item :label="$t('_prop.purchase.purchase_order.vendorName')" prop="vendorNo">
|
||||||
<BaseSelect
|
<BaseSelect
|
||||||
v-model="form.vendorName"
|
v-model="form.vendorNo"
|
||||||
:url="getVendorSelectListUrl"
|
:url="getVendorSelectListUrl"
|
||||||
ref="vendorSelectRef"
|
ref="vendorSelectRef"
|
||||||
:placeholder="$t('_message.purchase.purchase_order.select_vendor')"
|
:placeholder="$t('_message.purchase.purchase_order.select_vendor')"
|
||||||
@@ -580,4 +596,39 @@ const getFormStatusTagType = (code: number | null): string => {
|
|||||||
:qr-code-list="qrCodeData"
|
:qr-code-list="qrCodeData"
|
||||||
:qr-code-size="200"
|
:qr-code-size="200"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<BaseItemDialog
|
||||||
|
:title="$t('_title.purchase.purchase_order.showItem')"
|
||||||
|
v-model:visible="showItemVisible"
|
||||||
|
:url="getItemsUrl"
|
||||||
|
parent-param-name="orderId"
|
||||||
|
:parent-param-value="showItemRow?.id"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.partNumber')" prop="partNumber" width="150" />
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.productSpecs')" prop="productSpecs" width="150" />
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('_prop.purchase.purchase_order_item.purchaseCount')"
|
||||||
|
prop="purchaseCount"
|
||||||
|
width="100"
|
||||||
|
/>
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.receiptCount')" prop="receiptCount" width="100" />
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('_prop.purchase.purchase_order_item.remainingCount')"
|
||||||
|
prop="remainingCount"
|
||||||
|
width="100"
|
||||||
|
/>
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.price')" prop="price" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ new Decimal(row.price ?? 0).toFixed(2) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.totalPrice')" prop="totalPrice" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ new Decimal(row.totalPrice ?? 0).toFixed(2) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('_prop.purchase.purchase_order_item.purchaseMark')" prop="purchaseMark" />
|
||||||
|
</template>
|
||||||
|
</BaseItemDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const removeUrl = "/purchase/purchaseplan/deletePurchasePlan";
|
|||||||
const getItemsUrl = "/purchase/purchaseplan/getPurchasePlanItemsWithVendorSuggestions";
|
const getItemsUrl = "/purchase/purchaseplan/getPurchasePlanItemsWithVendorSuggestions";
|
||||||
const generateOrderUrl = "/purchase/purchaseplan/generatePurchaseOrder";
|
const generateOrderUrl = "/purchase/purchaseplan/generatePurchaseOrder";
|
||||||
const getItemUrl = "/purchase/purchaseplan/getPurchasePlanItems";
|
const getItemUrl = "/purchase/purchaseplan/getPurchasePlanItems";
|
||||||
|
const partNumberExistsUrl = "/warehouse/warehouseitem/existsWarehouseItem";
|
||||||
const searchers = [
|
const searchers = [
|
||||||
{ name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_plan.searchCode") },
|
{ name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_plan.searchCode") },
|
||||||
];
|
];
|
||||||
@@ -53,6 +54,28 @@ const rules = reactive<FormRules>({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
const itemArrayName = "planItems";
|
const itemArrayName = "planItems";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证物料编号是否存在
|
||||||
|
*/
|
||||||
|
const validatePartNumber = (rule: any, value: string, callback: (error?: Error) => void) => {
|
||||||
|
if (!value) {
|
||||||
|
callback(new Error($t("_message.purchase.purchase_plan_item.input_partNumber")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get(partNumberExistsUrl, { partNumber: value })
|
||||||
|
.then(res => {
|
||||||
|
if (res.data === true) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
callback(new Error($t("_message.warehouse.warehouse_item.not_exist_partNumber")));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基本不变通用变量
|
* 基本不变通用变量
|
||||||
*/
|
*/
|
||||||
@@ -445,8 +468,6 @@ const mappingConfig: FieldMappingConfig = {
|
|||||||
<BaseSelect
|
<BaseSelect
|
||||||
v-model="form.vendorId"
|
v-model="form.vendorId"
|
||||||
:url="'/sys/vendor/getVendorList'"
|
:url="'/sys/vendor/getVendorList'"
|
||||||
name="id"
|
|
||||||
label="vendorName"
|
|
||||||
:placeholder="$t('_message.purchase.purchase_plan.select_vendor')"
|
:placeholder="$t('_message.purchase.purchase_plan.select_vendor')"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -455,9 +476,7 @@ const mappingConfig: FieldMappingConfig = {
|
|||||||
<el-form-item :label="$t('_prop.purchase.purchase_plan.storeName')" prop="storeNo">
|
<el-form-item :label="$t('_prop.purchase.purchase_plan.storeName')" prop="storeNo">
|
||||||
<BaseSelect
|
<BaseSelect
|
||||||
v-model="form.storeNo"
|
v-model="form.storeNo"
|
||||||
:url="'/warehouse/store/getStoreList'"
|
:url="'/warehouse/warehouse/getWarehouseSelectList'"
|
||||||
name="storeNo"
|
|
||||||
label="storeName"
|
|
||||||
:placeholder="$t('_message.purchase.purchase_plan.select_store')"
|
:placeholder="$t('_message.purchase.purchase_plan.select_store')"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -477,9 +496,7 @@ const mappingConfig: FieldMappingConfig = {
|
|||||||
<template #default="{ row, $index }">
|
<template #default="{ row, $index }">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:prop="`${itemArrayName}.${$index}.partNumber`"
|
:prop="`${itemArrayName}.${$index}.partNumber`"
|
||||||
:rules="[
|
:rules="[{ required: true, validator: validatePartNumber, trigger: 'blur' }]"
|
||||||
{ required: true, message: $t('_message.purchase.purchase_plan_item.input_partNumber'), trigger: 'blur' },
|
|
||||||
]"
|
|
||||||
>
|
>
|
||||||
<el-input v-model="row.partNumber" size="small" />
|
<el-input v-model="row.partNumber" size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -294,6 +294,8 @@ const operateButtonClick = (eventName: string, row: any) => {
|
|||||||
const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
|
const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
|
||||||
if (row.status === 0 && button.eventName === "reject") return false;
|
if (row.status === 0 && button.eventName === "reject") return false;
|
||||||
if (row.status === 1 && button.eventName === "approve") return false;
|
if (row.status === 1 && button.eventName === "approve") return false;
|
||||||
|
if (row.status === 1 && button.eventName === "edit") return false;
|
||||||
|
if (row.status === 1 && button.eventName === "remove") return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -311,12 +313,12 @@ const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
|
|||||||
<DefaultToolButton @top-button-click="topButtonClick" />
|
<DefaultToolButton @top-button-click="topButtonClick" />
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formCode')" prop="formCode" />
|
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formCode')" prop="formCode" width="175" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formName')" prop="formName" />
|
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formName')" prop="formName" width="250" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.storeName')" prop="storeName" />
|
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.storeName')" prop="storeName" width="100" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.outStoreName')" prop="outStoreName" />
|
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.outStoreName')" prop="outStoreName" width="100" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formMark')" prop="formMark" />
|
<el-table-column :label="$t('_prop.warehouse.stocktransferorder.formMark')" prop="formMark" width="250" />
|
||||||
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" />
|
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" width="150" />
|
||||||
<DefaultStatusSwitchColumn
|
<DefaultStatusSwitchColumn
|
||||||
status-param-name="status"
|
status-param-name="status"
|
||||||
:status-label-mapping="getFormStatusLabel"
|
:status-label-mapping="getFormStatusLabel"
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { $t } from "@/common/languages";
|
|||||||
import { ElMessage, type FormInstance, type FormRules } from "element-plus";
|
import { ElMessage, type FormInstance, type FormRules } from "element-plus";
|
||||||
import { formatDate } from "@/common/utils/format-utils";
|
import { formatDate } from "@/common/utils/format-utils";
|
||||||
import { get, post } from "@/common/http/request";
|
import { get, post } from "@/common/http/request";
|
||||||
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
|
|
||||||
import QrCodeDialog from "@/components/base/base-qrcode/QrCodeDialog.vue";
|
import QrCodeDialog from "@/components/base/base-qrcode/QrCodeDialog.vue";
|
||||||
import { Delete, Edit, Plus } from "@element-plus/icons-vue";
|
import { Delete, Edit, Plus } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
@@ -169,10 +168,6 @@ const saveVendorList = async () => {
|
|||||||
|
|
||||||
const validVendors = dialogTableData.value.filter(v => v.vendorId !== null && v.vendorId !== undefined);
|
const validVendors = dialogTableData.value.filter(v => v.vendorId !== null && v.vendorId !== undefined);
|
||||||
|
|
||||||
if (validVendors.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vendorList = validVendors.map(v => ({
|
const vendorList = validVendors.map(v => ({
|
||||||
vendorId: v.vendorId,
|
vendorId: v.vendorId,
|
||||||
costPrice: v.costPrice,
|
costPrice: v.costPrice,
|
||||||
@@ -244,14 +239,18 @@ const cancelVendorEdit = (row: any, originalRow: any) => {
|
|||||||
<DefaultToolButton @top-button-click="topButtonClick" />
|
<DefaultToolButton @top-button-click="topButtonClick" />
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.partNumber')" prop="partNumber" width="150" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.partNumber')" prop="partNumber" width="125" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productType')" prop="productType" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productType')" prop="productType" width="200" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productSpecs')" prop="productSpecs" width="150" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productSpecs')" prop="productSpecs" width="200" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productBrand')" prop="productBrand" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productBrand')" prop="productBrand" width="100" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productPacking')" prop="productPacking" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productPacking')" prop="productPacking" width="100" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productPackSize')" prop="productPackSize" />
|
<el-table-column
|
||||||
|
:label="$t('_prop.warehouse.warehouse_item.productPackSize')"
|
||||||
|
prop="productPackSize"
|
||||||
|
width="125"
|
||||||
|
/>
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productPrice')" prop="productPrice" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.productPrice')" prop="productPrice" />
|
||||||
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" />
|
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" width="200" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.createUserName')" prop="createUserName" />
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.createUserName')" prop="createUserName" />
|
||||||
<DefaultOperateButtonColumn @operate-button-click="operateButtonClick" />
|
<DefaultOperateButtonColumn @operate-button-click="operateButtonClick" />
|
||||||
</template>
|
</template>
|
||||||
@@ -325,7 +324,14 @@ const cancelVendorEdit = (row: any, originalRow: any) => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</BaseForm>
|
</BaseForm>
|
||||||
<el-dialog v-model="vendorDialogVisible" :title="vendorDialogTitle" width="80%" :close-on-click-modal="false">
|
<el-dialog
|
||||||
|
class="vendor-dialog"
|
||||||
|
v-model="vendorDialogVisible"
|
||||||
|
:title="vendorDialogTitle"
|
||||||
|
width="80%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:lock-scroll="false"
|
||||||
|
>
|
||||||
<el-form ref="vendorFormRef" :model="{ dialogTableData }" :rules="vendorFormRules">
|
<el-form ref="vendorFormRef" :model="{ dialogTableData }" :rules="vendorFormRules">
|
||||||
<el-table :data="dialogTableData" border stripe style="width: 100%" max-height="50vh">
|
<el-table :data="dialogTableData" border stripe style="width: 100%" max-height="50vh">
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehouse_item.vendorName')" width="250" show-overflow-tooltip>
|
<el-table-column :label="$t('_prop.warehouse.warehouse_item.vendorName')" width="250" show-overflow-tooltip>
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
|
|||||||
if (row.status === 0 && button.eventName === "reject") return false;
|
if (row.status === 0 && button.eventName === "reject") return false;
|
||||||
if (row.status === 1 && button.eventName === "approve") return false;
|
if (row.status === 1 && button.eventName === "approve") return false;
|
||||||
if (row.status === 1 && button.eventName === "edit") return false;
|
if (row.status === 1 && button.eventName === "edit") return false;
|
||||||
|
if (row.status === 1 && button.eventName === "remove") return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -212,11 +213,11 @@ const submit = (form: any, formRef: FormInstance | undefined) => {
|
|||||||
<DefaultToolButton @top-button-click="topButtonClick" />
|
<DefaultToolButton @top-button-click="topButtonClick" />
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formCode')" prop="formCode" />
|
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formCode')" prop="formCode" width="175" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.storeName')" prop="storeName" />
|
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.storeName')" prop="storeName" width="125" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formName')" prop="formName" />
|
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formName')" prop="formName" width="350" />
|
||||||
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formMark')" prop="formMark" />
|
<el-table-column :label="$t('_prop.warehouse.warehousereceipt.formMark')" prop="formMark" width="200" />
|
||||||
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" />
|
<el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" width="150" />
|
||||||
<DefaultStatusSwitchColumn
|
<DefaultStatusSwitchColumn
|
||||||
status-param-name="status"
|
status-param-name="status"
|
||||||
:status-label-mapping="getFormStatusLabel"
|
:status-label-mapping="getFormStatusLabel"
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
|
|||||||
open: viteEnv.VITE_OPEN,
|
open: viteEnv.VITE_OPEN,
|
||||||
cors: true,
|
cors: true,
|
||||||
// 跨域代理配置
|
// 跨域代理配置
|
||||||
proxy: {
|
// proxy: {
|
||||||
"/api": {
|
// "/api": {
|
||||||
target: "https://vue3-design.teek.top",
|
// target: "https://vue3-design.teek.top",
|
||||||
changeOrigin: true,
|
// changeOrigin: true,
|
||||||
secure: true, // 是否忽略 https 安全证书问题,true 不忽略,false 忽略
|
// secure: true, // 是否忽略 https 安全证书问题,true 不忽略,false 忽略
|
||||||
rewrite: path => path.replace(/^\/api/, ""),
|
// rewrite: path => path.replace(/^\/api/, ""),
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
// 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
|
// 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
|
||||||
warmup: {
|
warmup: {
|
||||||
clientFiles: ["./index.html", "./src/{views,components}/*"],
|
clientFiles: ["./index.html", "./src/{views,components}/*"],
|
||||||
|
|||||||
Reference in New Issue
Block a user