first commit

This commit is contained in:
2026-09-02 16:31:50 +08:00
commit a461727193
911 changed files with 692450 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# 配置项文档:https://editorconfig.org/
# 告知 EditorConfig 插件,当前即是根文件
root = true
# 适用全部文件
[*]
## 设置字符集
charset = utf-8
## 缩进风格 space | tab,建议 space
indent_style = space
## 缩进的空格数(修改这里的话需要将 prettier.config.js 和 .vscode -> settings.json 也同步修改)
indent_size = 2
## 换行符类型 lf | cr | crlf,一般都是设置为 lf
end_of_line = lf
## 是否在文件末尾插入空白行
insert_final_newline = true
## 是否删除一行中的前后空格
trim_trailing_whitespace = true
# 适用 .md 文件
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
+10
View File
@@ -0,0 +1,10 @@
# 自定义的环境变量(命名必须以 VITE_ 开头)
## 后端接口公共路径(如果解决跨域问题采用反向代理就只需写公共路径)
VITE_BASE_API = 'http://127.0.0.1:8078'
## 路由模式 hash 或 html5
VITE_ROUTER_HISTORY = 'hash'
## 开发环境地址前缀(一般 '/','./' 都可以)
VITE_PUBLIC_PATH = '/'
+10
View File
@@ -0,0 +1,10 @@
# 自定义的环境变量(命名必须以 VITE_ 开头)
## 后端接口公共路径(如果解决跨域问题采用 CORS 就需要写全路径)
VITE_BASE_API = 'http://localhost:5000/api/'
## 路由模式 hash 或 html5
VITE_ROUTER_HISTORY = 'hash'
## 打包路径(就是网站前缀,例如部署到 https://un-pany.github.io/v3-admin-vite/ 域名下,就需要填写 /v3-admin-vite/)
VITE_PUBLIC_PATH = '/'
+11
View File
@@ -0,0 +1,11 @@
# 自定义的环境变量(命名必须以 VITE_ 开头)
## 后端接口公共路径(如果解决跨域问题采用 CORS 就需要写全路径)
# VITE_BASE_API = 'https://mock.mengxuegu.com/mock/63218b5fb4c53348ed2bc212/api/v1'
VITE_BASE_API = 'http://192.168.2.212:5000/api/'
## 路由模式 hash 或 html5
VITE_ROUTER_HISTORY = 'hash'
## 打包路径(就是网站前缀,例如部署到 https://un-pany.github.io/v3-admin-vite/ 域名下,就需要填写 /v3-admin-vite/)
VITE_PUBLIC_PATH = '/acs-office/'
+8
View File
@@ -0,0 +1,8 @@
# Eslint 会忽略的文件
.DS_Store
node_modules
dist
dist-ssr
*.local
.npmrc
+69
View File
@@ -0,0 +1,69 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true
},
extends: [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/eslint-config-typescript"
],
parser: "vue-eslint-parser",
parserOptions: {
parser: "@typescript-eslint/parser",
ecmaVersion: 2020,
sourceType: "module",
jsxPragma: "React",
ecmaFeatures: {
jsx: true,
tsx: true
}
},
rules: {
// TS
"@typescript-eslint/no-explicit-any": "off",
"no-debugger": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_"
}
],
"no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_"
}
],
// Vue
"vue/no-v-html": "off",
"vue/require-default-prop": "off",
"vue/require-explicit-emits": "off",
"vue/multi-word-component-names": "off",
"vue/html-self-closing": [
"error",
{
html: {
void: "always",
normal: "always",
component: "always"
},
svg: "always",
math: "always"
}
],
// Prettier
"prettier/prettier": "off"
}
}
+37
View File
@@ -0,0 +1,37 @@
# Git 会忽略的文件
.DS_Store
node_modules
dist
dist-ssr
.eslintcache
# Local env files
*.local
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
!.vscode/*.code-snippets
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.zip
# Use the PNPM
package-lock.json
yarn.lock
1013-JSHS-ACS_WEB_dist.zip
+2
View File
@@ -0,0 +1,2 @@
# 通过该配置兜底解决组件没有类型提示的问题
shamefully-hoist = true
+8
View File
@@ -0,0 +1,8 @@
# Prettier 会忽略的文件
.DS_Store
node_modules
dist
dist-ssr
*.local
.npmrc
+6
View File
@@ -0,0 +1,6 @@
{
"editor.defaultFormatter": null,
"[vue]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-present pany <https://github.com/pany-ang>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+3
View File
@@ -0,0 +1,3 @@
# WMS_Front
金世泰WMS二期前端网站
+1
View File
@@ -0,0 +1 @@
No Message
+1
View File
@@ -0,0 +1 @@
declare module 'file-saver'
+16
View File
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="/app-loading.css" />
<title>WMS仓储管理系统</title>
</head>
<body>
<div id="app">
<div id="app-loading" style="height: 100%;"></div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+82
View File
@@ -0,0 +1,82 @@
{
"scripts": {
"dev": "vite",
"build:dev": "vite build",
"build:stage": "vue-tsc --noEmit && vite build --mode staging",
"build:prod": "vue-tsc --noEmit && vite build",
"preview:stage": "pnpm build:stage && vite preview",
"preview:prod": "pnpm build:prod && vite preview",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"",
"lint": "pnpm lint:eslint && pnpm lint:prettier",
"test": "vitest"
},
"dependencies": {
"@dataview/datav-vue3": "^0.0.0-test.1672506674342",
"@element-plus/icons-vue": "^2.1.0",
"@microsoft/signalr": "^7.0.10",
"axios": "1.5.0",
"date-fns": "^4.1.0",
"dayjs": "1.11.9",
"echarts": "^5.4.3",
"element-plus": "^2.11.3",
"file-saver": "^2.0.5",
"js-cookie": "3.0.5",
"lodash": "^4.17.21",
"lodash-es": "4.17.21",
"mitt": "3.0.1",
"normalize.css": "8.0.1",
"nprogress": "0.2.0",
"path-browserify": "1.0.1",
"path-to-regexp": "6.2.1",
"pinia": "2.1.6",
"screenfull": "6.0.2",
"vue": "3.3.4",
"vue-router": "4.2.4",
"vxe-table": "4.4.1",
"vxe-table-plugin-element": "3.0.7",
"xe-utils": "3.5.11",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@types/js-cookie": "3.0.3",
"@types/lodash-es": "4.17.8",
"@types/node": "20.5.7",
"@types/nprogress": "0.2.0",
"@types/path-browserify": "1.0.0",
"@typescript-eslint/eslint-plugin": "6.4.1",
"@typescript-eslint/parser": "6.4.1",
"@vitejs/plugin-vue": "4.3.3",
"@vitejs/plugin-vue-jsx": "3.0.2",
"@vue/eslint-config-prettier": "8.0.0",
"@vue/eslint-config-typescript": "11.0.3",
"@vue/test-utils": "2.4.1",
"eslint": "8.48.0",
"eslint-plugin-prettier": "5.0.0",
"eslint-plugin-vue": "9.17.0",
"jsdom": "22.1.0",
"lint-staged": "14.0.1",
"prettier": "3.0.2",
"sass": "1.66.1",
"typescript": "5.2.2",
"unocss": "0.55.3",
"vite": "4.4.9",
"vite-plugin-svg-icons": "2.0.1",
"vite-svg-loader": "4.0.0",
"vitest": "0.34.3",
"vue-eslint-parser": "9.3.1",
"vue-tsc": "1.8.8"
},
"lint-staged": {
"*.{vue,js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{css,less,scss,html,md}": [
"prettier --write"
],
"package.json": [
"prettier --write"
]
}
}
+5323
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
/** 配置项文档:https://prettier.io/docs/en/configuration.html */
module.exports = {
/** 每一行的宽度 */
printWidth: 120,
/** Tab 键的空格数 */
tabWidth: 2,
/** 在对象中的括号之间是否用空格来间隔 */
bracketSpacing: true,
/** 箭头函数的参数无论有几个,都要括号包裹 */
arrowParens: "always",
/** 换行符的使用 */
endOfLine: "auto",
/** 是否采用单引号 */
singleQuote: false,
/** 对象或者数组的最后一个元素后面不要加逗号 */
trailingComma: "none",
/** 是否加分号 */
semi: false,
/** 是否使用 Tab 格式化 */
useTabs: false
}
+45
View File
@@ -0,0 +1,45 @@
/** 白屏阶段会执行的 CSS 加载动画 */
#app-loading {
position: relative;
top: 45vh;
margin: 0 auto;
color: #409eff;
font-size: 12px;
}
#app-loading,
#app-loading::before,
#app-loading::after {
width: 2em;
height: 2em;
border-radius: 50%;
animation: 2s ease-in-out infinite app-loading-animation;
}
#app-loading::before,
#app-loading::after {
content: "";
position: absolute;
}
#app-loading::before {
left: -4em;
animation-delay: -0.2s;
}
#app-loading::after {
left: 4em;
animation-delay: 0.2s;
}
@keyframes app-loading-animation {
0%,
80%,
100% {
box-shadow: 0 2em 0 -2em;
}
40% {
box-shadow: 0 2em 0 0;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

+3
View File
@@ -0,0 +1,3 @@
{
"baseApiUrl":"http://localhost:8078"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

+31
View File
@@ -0,0 +1,31 @@
<script lang="ts" setup>
// import { h } from "vue"
import { useTheme } from "@/hooks/useTheme"
// import { ElNotification } from "element-plus"
// 将 Element Plus 的语言设置为中文
import zhCn from "element-plus/es/locale/lang/zh-cn"
const { initTheme } = useTheme()
/** 初始化主题 */
initTheme()
/** 作者小心思 */
// ElNotification({
// title: "Hello",
// type: "success",
// message: h(
// "a",
// { style: "color: teal", target: "_blank", href: "https://github.com/un-pany/v3-admin-vite" },
// "小项目获取 star 不易,如果你喜欢这个项目的话,欢迎点击这里支持一个 star !这是作者持续维护的唯一动力(小声:毕竟是免费的)"
// ),
// duration: 0,
// position: "bottom-right"
// })
</script>
<template>
<el-config-provider :locale="zhCn">
<router-view />
</el-config-provider>
</template>
+14
View File
@@ -0,0 +1,14 @@
import { AgvTask } from "@/dto/agvTask/AgvTask"
import { request } from "@/utils/service"
/** 获取erp任务关联的agv任务 */
export function GetAgvTasksRelatedToErpTask(erpTaskId: string) {
return request<GetAgvTasksRelatedToErpTaskResponseData>({
url: "/api/AgvTask/GetAgvTasksRelatedToErpTask?erpTaskId="+erpTaskId,
method: "post"
})
}
export type GetAgvTasksRelatedToErpTaskResponseData = ApiResponseData<AgvTask[]>
+11
View File
@@ -0,0 +1,11 @@
import { request } from "@/utils/service"
/** 获取 班组信息 */
export function GetGroupNames() {
return request<GetGroupNameResponseData>({
url: "Report/GetGroupNames",
method: "get"
})
}
export type GetGroupNameResponseData = ApiResponseDataArray<String>
+26
View File
@@ -0,0 +1,26 @@
import { ErpTask } from "@/dto/erpTask/ErpTask"
import {ErpTaskQueryParam} from '@/dto/erpTask/ErpTaskQueryParam'
import { request } from "@/utils/service"
/** 获取erp任务关联的agv任务 */
export function GetErpTasks(param:ErpTaskQueryParam) {
return request<GetErpTasksResponseData>({
url: "/api/Erp/GetErpTasks",
method: "post",
data:param
})
}
/** 操作erp任务(更改状态)*/
export function OperateTask(id:string,taskStatus:number) {
return request<OperateTaskResponseData>({
url: "/api/Erp/OperateTask?id="+id+'&taskStatus='+taskStatus,
method: "post",
})
}
export type GetErpTasksResponseData = ApiResponseData<ErpTask[]>
export type OperateTaskResponseData = ApiResponseData<boolean>
@@ -0,0 +1,36 @@
/** 模拟接口响应数据 */
const SELECT_RESPONSE_DATA = {
code: 0,
data: [
{
label: "苹果",
value: 1
},
{
label: "香蕉",
value: 2
},
{
label: "橘子",
value: 3,
disabled: true
}
],
message: "获取 Select 数据成功"
}
/** 模拟接口 */
export function getSelectDataApi() {
return new Promise<typeof SELECT_RESPONSE_DATA>((resolve, reject) => {
// 模拟接口响应时间 2s
setTimeout(() => {
// 模拟接口调用成功
if (Math.random() < 0.8) {
resolve(SELECT_RESPONSE_DATA)
} else {
// 模拟接口调用出错
reject(new Error("接口发生错误"))
}
}, 2000)
})
}
@@ -0,0 +1,26 @@
/** 模拟接口响应数据 */
const SUCCESS_RESPONSE_DATA = {
code: 0,
data: {
list: [] as number[]
},
message: "获取成功"
}
/** 模拟请求接口成功 */
export function getSuccessApi(list: number[]) {
return new Promise<typeof SUCCESS_RESPONSE_DATA>((resolve) => {
setTimeout(() => {
resolve({ ...SUCCESS_RESPONSE_DATA, data: { list } })
}, 1000)
})
}
/** 模拟请求接口失败 */
export function getErrorApi() {
return new Promise((_resolve, reject) => {
setTimeout(() => {
reject(new Error("发生错误"))
}, 1000)
})
}
+27
View File
@@ -0,0 +1,27 @@
import { request } from "@/utils/service"
import * as Login from "./types/login"
/** 获取所有用户 Token */
export function getAllUser() {
return request<Login.AllUserInfo>({
url: "/api/UserInfo/GetAll",
method: "get"
})
}
/** 登录并返回 Token */
export function loginApi(data: Login.LoginParam) {
return request<Login.LoginResponseData>({
url: '/api/UserInfo/Login',
method: "post",
data
})
}
/** 获取用户详情 */
export function getUserInfoApi() {
return request<Login.UserInfoResponseData>({
url: "users/info",
method: "get"
})
}
+13
View File
@@ -0,0 +1,13 @@
import { UserPermission } from "@/dto/user/userPermission"
import { UserInfo } from "@/dto/user/userInfo"
export interface LoginParam {
UserId: string
Password: string
}
export type AllUserInfo = ApiResponseData<UserInfo[]>
export type LoginResponseData = ApiResponseData<UserPermission>
export type UserInfoResponseData = ApiResponseData<{ username: string; roles: string[] }>
@@ -0,0 +1,14 @@
import { OperationLog,OperationLogQueryParam } from "@/dto/operationLog/OperationLog"
import { request } from "@/utils/service"
export function GetOperationLogLst(param:OperationLogQueryParam) {
return request<GetOperationLogResponseData>({
url: "/api/OperationLog/QueryByPage",
method: "post",
data:param
})
}
export type GetOperationLogResponseData = ApiResponseData<OperationLog[]>
@@ -0,0 +1,13 @@
import { request } from "@/utils/service"
import * as PaperCostInfo from "../../dto/paperCostInfo/PaperCostInfo"
export type PaperCostInfoData = ApiResponseDataArray<PaperCostInfo.PaperCostInfo>
/** 获取日耗纸统计信息 */
export function QueryPaperReplaceInfo(data: PaperCostInfo.PaperCostInfoQueryParam) {
return request<PaperCostInfoData>({
url: "/api/PaperMesRfid/GetPaperCostByDays",
method: "post",
data
})
}
@@ -0,0 +1,21 @@
import { request } from "@/utils/service"
import * as md from "@/dto/paperfeed/paperFeed"
/** 获取进纸记录列表 */
export function GetPaperReturnList(data: md.PaperFeedSearch) {
return request<PaperFeedResponseData>({
url: "/api/PaperReturn/GetPaperReturnList",
method: "post",
data
})
}
/**补录、编辑进纸信息 */
export function SaveReturnRecord(data: md.PaperFeedModel) {
return request<PaperFeedResponseData>({
url: "/api/PaperReturn/SaveReturnRecord",
method: "post",
data
})
}
export type PaperFeedResponseData = ApiResponseDataArray<md.PaperFeedModel>
@@ -0,0 +1,12 @@
import { request } from "@/utils/service"
import * as PaperUsingRateInfo from "@/dto/paperUsingRate/PaperUsingRateInfo"
export function GetPaperUsingRate(startTime: string, endTime: string) {
return request<PaperUsingRateResponseData>({
url: "/api/Statistic/GetPaperUsingRate",
method: "post",
data: { 'startTime': startTime, 'endTime': endTime }
})
}
export type PaperUsingRateResponseData = ApiResponseDataArray<PaperUsingRateInfo.PaperUsingRateInfo>
@@ -0,0 +1,12 @@
import { request } from "@/utils/service"
import * as PaperWastageStatistic from "../../dto/paperWastageStatistic/PaperWastageStatistic"
export type PaperWastageStatisticData = ApiResponseDataArray<PaperWastageStatistic.PaperWastageStatisticInfo>
/** 获取代纸信息列表 */
export function QueryPaperWastageStatisticInfo(data: PaperWastageStatistic.PaperWastageStatisticQueryParam) {
return request<PaperWastageStatisticData>({
url: "/api/PaperOrderMap/GetPaperWastageStatistic",
method: "post",
data
})
}
@@ -0,0 +1,30 @@
import { request } from "@/utils/service"
import * as PaperOrderMap from "../../dto/paper_order_map/PaperOrderMap"
export type PaperOrderMapInfoData = ApiResponseDataArray<PaperOrderMap.PaperOrderMapInfo>
/** 获取订单用纸信息列表 */
export function QueryPaperOrderMapInfo(data: PaperOrderMap.PaperOrderMapQueryParam) {
return request<PaperOrderMapInfoData>({
url: "/api/PaperOrderMap/QueryByPage",
method: "post",
data
})
}
/** 获取订单信息列表 */
export function GetOrderListByPage(data: PaperOrderMap.PaperOrderMapQueryParam) {
return request<PaperOrderMapInfoData>({
url: "/api/PaperOrderMap/GetOrderListByPage",
method: "post",
data
})
}
export function GetOrderList(data: PaperOrderMap.PaperOrderMapQueryParam) {
return request<PaperOrderMapInfoData>({
url: "/api/PaperOrderMap/GetPaperOrderMaps",
method: "post",
data
})
}
@@ -0,0 +1,12 @@
import { request } from "@/utils/service"
import * as PaperReplace from "../../dto/paper_replace/PaperReplace"
export type PaperReplaceData = ApiResponseDataArray<PaperReplace.PaperReplace>
/** 获取代纸信息列表 */
export function QueryPaperReplaceInfo(data: PaperReplace.PaperReplaceQueryParam) {
return request<PaperReplaceData>({
url: "/api/PaperReplace/QueryByPage",
method: "post",
data
})
}
@@ -0,0 +1,35 @@
import { request } from "@/utils/service"
import * as md from "@/dto/paperfeed/paperFeed"
/**
* 根据原纸卷标,查询原纸信息
* @param paperLable
* @returns
*/
export function QueryPaperInfo(paperLable: string) {
return request<QueryPaperBaseInfoResponseData>({
url: "api/PaperMesRfid/GetPaperByPaperLable?paperLable=" + paperLable,
method: "post"
})
}
/** 获取进纸记录列表 */
export function GetPaperFeedList(data: md.PaperFeedSearch) {
return request<PaperFeedResponseData>({
url: "/api/PaperFeed/GetPaperFeedList",
method: "post",
data
})
}
/**补录、编辑进纸信息 */
export function SaveFeedRecord(data: md.PaperFeedModel) {
return request<PaperFeedResponseData>({
url: "/api/PaperFeed/SaveFeedRecord",
method: "post",
data
})
}
export type QueryPaperBaseInfoResponseData = ApiResponseData<string>
export type PaperFeedResponseData = ApiResponseDataArray<md.PaperFeedModel>
@@ -0,0 +1,25 @@
import { request } from "@/utils/service"
import * as md from "@/dto/report/MonthReportDto"
/** */
export function GetMonthReport(data: md.MonthReportSearch) {
return request<MonthReportResponseData>({
url: "Report/MonthReport",
method: "post",
data
})
}
/** */
export function ExportMonthReport(data: md.MonthReportSearch) {
return request<any>({
url: "Report/ExportMonthReport",
method: "post",
responseType: "blob",
data
})
}
/** */
export type MonthReportResponseData = ApiResponseData<md.MonthReportDto>
@@ -0,0 +1,26 @@
import { request } from "@/utils/service"
import * as md from "@/dto/report/WetPaperReportDto"
/** */
export function GetWetPaperReport(data: md.WetPaperReportSearch) {
return request<WetPaperReportResponseData>({
url: "Report/WetPaperReport",
method: "post",
data
})
}
/** */
export function ExportWetPaperReport(data: md.WetPaperReportSearch) {
return request<any>({
url: "Report/ExportWetPaperReport",
method: "post",
responseType: "blob",
data
})
}
/** */
export type WetPaperReportResponseData = ApiResponseData<md.WetPaperReportDto>
@@ -0,0 +1,52 @@
import { PdaInParam } from "@/dto/simulativeDebugging/pdaInParam"
import { RcsTask } from "@/dto/simulativeDebugging/rcsTask"
import { UploadRcsTaskStatusParam } from "@/dto/simulativeDebugging/uploadRcsTaskStatusParam"
import { request } from "@/utils/service"
/** pda提交入库 */
export function StockInByPda(data: PdaInParam) {
return request<StockInByPdaResponseData>({
url: "/api/Wms/StockInByPda",
method: "post",
data
})
}
/** 获取ecs任务列表 */
export function GetRcsTaskLst() {
return request<GetRcsTaskLstResponseData>({
url: "/api/Test/GetRcsTaskLst",
method: "post",
})
}
/** 向wms上传任务状态 */
export function UploadRcsTaskStatus(data:UploadRcsTaskStatusParam) {
return request<UploadRcsTaskStatusResponseData>({
url: "/api/Wms/PostAgvExcutionStatus",
method: "post",
data
})
}
/** 修改rcs任务信息 */
export function UpdateRcsTask(data:RcsTask) {
return request<UpdateRcsTaskResponseData>({
url: "/api/Test/UpdateRcsTask",
method: "post",
data
})
}
export type StockInByPdaResponseData = ApiResponseData<boolean>
export type UpdateRcsTaskResponseData = ApiResponseData<boolean>
export type GetRcsTaskLstResponseData = ApiResponseData<RcsTask[]>
export type UploadRcsTaskStatusResponseData = ApiResponseData<string>
@@ -0,0 +1,17 @@
import { StockInAndOutStatisticInfo } from "@/dto/statistic/stockInAndOutStatisticInfo"
import { request } from "@/utils/service"
/** 获取当日出入库统计结果 */
export function GetStockInAndOutStatistic() {
return request<GetStockInAndOutStatisticResponseData>({
url: "/api/Statistic/GetStockInAndOutStatistic",
method: "post",
})
}
export type GetStockInAndOutStatisticResponseData = ApiResponseData<StockInAndOutStatisticInfo>
@@ -0,0 +1,11 @@
import * as stockInDetail from '@/dto/stockInDetail/stockInDetail'
import { request } from "@/utils/service"
export function GetStockinDetailToday(elvatorStockinNo:string) {
return request<GetStockinDetailTodayResponseData>({
url: "api/Warehouse/GetStockinDetailToday?elvatorStockinNo=" + elvatorStockinNo,
method: "get",
})
}
export type GetStockinDetailTodayResponseData = ApiResponseDataArray<stockInDetail.stockInDetail>
+13
View File
@@ -0,0 +1,13 @@
import {StockOutParam} from '@/dto/stockOut/stockOutParam'
import { request } from "@/utils/service"
export function StockOut(param: StockOutParam) {
return request<StockOutResponseData>({
url: "/api/Test/StockOut",
method: "post",
data:param
})
}
export type StockOutResponseData = ApiResponseData<boolean>
@@ -0,0 +1,13 @@
import { StorageRackInfo } from "@/dto/wareHouse/wareHouse"
import { request } from "@/utils/service"
export function GetStorageRackLst(floor: number) {
return request<GetStorageRackInfoResponseData>({
url: "/api/Warehouse/GetStorageRackLst?floor="+floor,
method: "post"
})
}
export type GetStorageRackInfoResponseData = ApiResponseData<StorageRackInfo[]>
@@ -0,0 +1,12 @@
import { request } from "@/utils/service"
import * as SupplierPaperStatistic from "../../dto/supplierPaperStatistic/SupplierPaperStatistic"
export type SupplierPaperStatisticData = ApiResponseDataArray<SupplierPaperStatistic.SupplierPaperStatisticInfo>
/** 获取供应商原纸统计信息 */
export function QuerySupplierPaperStatisticInfo(data: SupplierPaperStatistic.SupplierPaperStatisticInfoQueryParam) {
return request<SupplierPaperStatisticData>({
url: "/api/PaperOrderMap/GetSupplierPaperStatistic",
method: "post",
data
})
}
+37
View File
@@ -0,0 +1,37 @@
import { request } from "@/utils/service"
import type * as Table from "./types/table"
/** 增 */
export function createTableDataApi(data: Table.CreateTableRequestData) {
return request({
url: "table",
method: "post",
data
})
}
/** 删 */
export function deleteTableDataApi(id: string) {
return request({
url: `table/${id}`,
method: "delete"
})
}
/** 改 */
export function updateTableDataApi(data: Table.UpdateTableRequestData) {
return request({
url: "table",
method: "put",
data
})
}
/** 查 */
export function getTableDataApi(params: Table.GetTableRequestData) {
return request<Table.GetTableResponseData>({
url: "table",
method: "get",
params
})
}
+36
View File
@@ -0,0 +1,36 @@
export interface CreateTableRequestData {
username: string
password: string
}
export interface UpdateTableRequestData {
id: string
username: string
password?: string
}
export interface GetTableRequestData {
/** 当前页码 */
currentPage: number
/** 查询条数 */
size: number
/** 查询参数:用户名 */
username?: string
/** 查询参数:手机号 */
phone?: string
}
export interface GetTableData {
createTime: string
email: string
id: string
phone: string
roles: string
status: boolean
username: string
}
export type GetTableResponseData = ApiResponseData<{
list: GetTableData[]
total: number
}>
@@ -0,0 +1,36 @@
import { WareHouseAreaInfo,StorageRackInfo } from "@/dto/wareHouse/WareHouse"
import {MaterialQueryParam} from "@/dto/wareHouse/MaterialQueryParam"
import { request } from "@/utils/service"
/** 获取库区信息 */
export function GetWareHouseAreaInfo(floor: number) {
return request<GetWareHouseAreaInfoResponseData>({
url: "/api/Warehouse/GetWareHouseAreaInfo?floor="+floor,
method: "post"
})
}
//更新库位信息
export function UpdateWareHouse(warehouse: StorageRackInfo) {
return request<UpdateWareResponseData>({
url: "/api/Warehouse/Update",
method: "post",
data:warehouse
})
}
//查询物料信息
export function GetMaterialInfo(param: MaterialQueryParam) {
return request<GetMaterialInfoResponseData>({
url: "/api/Warehouse/GetMaterialInfo",
method: "post",
data:param
})
}
export type GetWareHouseAreaInfoResponseData = ApiResponseData<WareHouseAreaInfo[]>
export type UpdateWareResponseData = ApiResponseData<boolean>
export type GetMaterialInfoResponseData = ApiResponseData<StorageRackInfo[]>
Binary file not shown.

After

Width:  |  Height:  |  Size: 953 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+97
View File
@@ -0,0 +1,97 @@
// 颜色
$colors: (
"primary": #db9e3f,
"info-1": #4394e4,
"info": #4b67af,
"white": #ffffff,
"light": #f9f9f9,
"grey-1": #999999,
"grey": #666666,
"dark-1": #5f5f5f,
"dark": #222222,
"black-1": #171823,
"black": #000000,
);
// 字体大小
$base-font-size: 0.2rem;
$font-sizes: (
xxs: 0.1,
//8px
xs: 0.125,
//10px
sm: 0.2875,
//12px
md: 0.1625,
//13px
lg: 0.175,
//14px
xl: 0.2,
//16px
xxl: 0.225,
//18px
xxxl: 0.25 //20px,,,,
);
// 宽高
.w-100 {
width: 100%;
}
.h-100 {
height: 100%;
}
//flex
.d-flex {
display: flex;
}
.flex-column {
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-nowrap {
flex-wrap: nowrap;
}
$flex-jc: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
evenly: space-evenly,
);
$flex-ai: (
start: flex-start,
end: flex-end,
center: center,
stretch: stretch,
);
.flex-1 {
flex: 1;
}
//.mt-1 => margin top
//spacing
$spacing-types: (
m: margin,
p: padding,
);
$spacing-directions: (
t: top,
r: right,
b: bottom,
l: left,
);
$spacing-base-size: 0.2rem;
$spacing-sizes: (
0: 0,
1: 0.25,
2: 0.5,
3: 1,
4: 1.5,
5: 3,
);
+139
View File
@@ -0,0 +1,139 @@
#index {
color: #d3d6dd;
// background-color: black;
width: 100%;
height: 100vh;
// position: absolute;
transform-origin: left top;
overflow: hidden;
.bg {
width: 100%;
height: 100%;
padding: 0.2rem 0.2rem 0 0.2rem;
background-image:url("/img/pageBg.png") ;
background-size: cover;
background-position: center center;
}
.host-body {
.bg{
color: red($color: red);
}
.title {
position: relative;
width: 6.25rem;
text-align: center;
background-size: cover;
background-repeat: no-repeat;
.title-text {
font-size: 0.3rem;
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%);
}
.title-bototm {
position: absolute;
bottom: -0.375rem;
left: 50%;
transform: translate(-50%);
}
}
// 第二行
.aside-width {
width: 40%;
}
.react-r-s,
.react-l-s {
// background-color: #0f1325;
background-color: #1a5cd7;
}
// 平行四边形
.react-right {
&.react-l-s {
text-align: right;
width: 430px;
}
font-size: 18px;
width: 300px;
line-height: 50px;
text-align: center;
transform: skewX(-45deg);
.react-after {
position: absolute;
right: -25px;
top: 0;
height: 50px;
width: 50px;
// background-color: #0f1325;
background-color: #1a5cd7;
transform: skewX(45deg);
}
.text {
display: inline-block;
transform: skewX(45deg);
}
}
.react-left {
&.react-l-s {
width: 500px;
text-align: left;
}
font-size: 18px;
width: 300px;
height: 50px;
line-height: 50px;
text-align: center;
transform: skewX(45deg);
// background-color: #0f1325;
background-color: #1a5cd7;
.react-left {
position: absolute;
left: -25px;
top: 0;
height: 50px;
width: 50px;
// background-color: #0f1325;
background-color: #1a5cd7;
transform: skewX(-45deg);
}
.text {
display: inline-block;
transform: skewX(-45deg);
}
}
.body-box {
margin-top: 0.2rem;
display: flex;
flex-direction: column;
//下方区域的布局
.content-box {
display: grid;
grid-template-columns: 4fr 7fr 4fr;
}
// 底部数据
.bototm-box {
margin-top: 0.125rem;
display: grid;
grid-template-columns: repeat(2, 50%);
}
}
}
}
+185
View File
@@ -0,0 +1,185 @@
@import "./variables";
// 全局样式
* {
margin: 0;
padding: 0;
list-style-type: none;
box-sizing: border-box;
outline: none;
}
html {
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.2em;
background-color: #f1f1f1;
margin: 0;
padding: 0;
}
a {
color: #343440;
text-decoration: none;
}
.clearfix {
&::after {
content: "";
display: table;
height: 0;
line-height: 0;
visibility: hidden;
clear: both;
}
}
//浮动
.float-r {
float: right;
}
//浮动
.float-l {
float: left;
}
// 字体加粗
.fw-b {
font-weight: bold;
}
//文章一行显示,多余省略号显示
.title-item {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// .bg-color-black {
// background-color: rgba(19, 25, 47, 0.6);
// }
.bg-color-blue {
background-color: #1a5cd7;
}
.colorBlack {
color: #272727 !important;
&:hover {
color: #272727 !important;
}
}
.colorGrass {
color: #33cea0;
&:hover {
color: #33cea0 !important;
}
}
.colorRed {
color: #ff5722;
&:hover {
color: #ff5722 !important;
}
}
.colorText {
color: #d3d6dd !important;
&:hover {
color: #d3d6dd !important;
}
}
.colorBlue {
color: #257dff !important;
&:hover {
color: #257dff !important;
}
}
//颜色
@each $colorkey, $color in $colors {
.text-#{$colorkey} {
color: $color;
}
.bg-#{$colorkey} {
background-color: $color;
}
}
//对齐
@each $var in (left, center, right) {
.text-#{$var} {
text-align: $var !important;
}
}
//flex
@each $key, $value in $flex-jc {
.jc-#{$key} {
justify-content: $value;
}
}
@each $key, $value in $flex-ai {
.ai-#{$key} {
align-items: $value;
}
}
//字体
@each $fontkey, $fontvalue in $font-sizes {
.fs-#{$fontkey} {
font-size: $fontvalue * $base-font-size;
}
}
//.mt-1 => margin top
//spacing
@each $typekey, $type in $spacing-types {
//.m-1
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}-#{$sizekey} {
#{$type}: $size * $spacing-base-size;
}
}
//.mx-1
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}x-#{$sizekey} {
#{$type}-left: $size * $spacing-base-size;
#{$type}-right: $size * $spacing-base-size;
}
.#{$typekey}y-#{$sizekey} {
#{$type}-top: $size * $spacing-base-size;
#{$type}-bottom: $size * $spacing-base-size;
}
}
//.mt-1
@each $directionkey, $direction in $spacing-directions {
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}#{$directionkey}-#{$sizekey} {
#{$type}-#{$direction}: $size * $spacing-base-size;
}
}
}
.#{$typekey} {
#{$type}: 0;
}
}
@@ -0,0 +1,58 @@
<script lang="ts" setup>
import { type ListItem } from "./data"
interface Props {
list: ListItem[]
}
const props = defineProps<Props>()
</script>
<template>
<el-empty v-if="props.list.length === 0" />
<el-card v-else v-for="(item, index) in props.list" :key="index" shadow="never" class="card-container">
<template #header>
<div class="card-header">
<div>
<span>
<span class="card-title">{{ item.title }}</span>
<el-tag v-if="item.extra" :type="item.status" effect="plain" size="small">{{ item.extra }}</el-tag>
</span>
<div class="card-time">{{ item.datetime }}</div>
</div>
<div v-if="item.avatar" class="card-avatar">
<img :src="item.avatar" width="34" />
</div>
</div>
</template>
<div class="card-body">
{{ item.description ?? "No Data" }}
</div>
</el-card>
</template>
<style lang="scss" scoped>
.card-container {
margin-bottom: 10px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.card-title {
font-weight: bold;
margin-right: 10px;
}
.card-time {
font-size: 12px;
color: grey;
}
.card-avatar {
display: flex;
align-items: center;
}
}
.card-body {
font-size: 12px;
}
}
</style>
+66
View File
@@ -0,0 +1,66 @@
export interface ListItem {
avatar?: string
title: string
datetime?: string
description?: string
status?: "" | "success" | "info" | "warning" | "danger"
extra?: string
}
export const notifyData: ListItem[] = [
{
avatar: "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png",
title: "V3 Admin Vite 上线啦",
datetime: "一年前",
description:
"一个免费开源的中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus、Pinia 和 Vite 等主流技术"
},
{
avatar: "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png",
title: "V3 Admin 上线啦",
datetime: "两年前",
description: "一个中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus 和 Pinia"
}
]
export const messageData: ListItem[] = [
{
avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
title: "来自楚门的世界",
description: "如果再也不能见到你,祝你早安、午安和晚安",
datetime: "1998-06-05"
},
{
avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
title: "来自大话西游",
description: "如果非要在这份爱上加上一个期限,我希望是一万年",
datetime: "1995-02-04"
},
{
avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
title: "来自龙猫",
description: "心存善意,定能途遇天使",
datetime: "1988-04-16"
}
]
export const todoData: ListItem[] = [
{
title: "任务名称",
description: "这家伙很懒,什么都没留下",
extra: "未开始",
status: "info"
},
{
title: "任务名称",
description: "这家伙很懒,什么都没留下",
extra: "进行中",
status: ""
},
{
title: "任务名称",
description: "这家伙很懒,什么都没留下",
extra: "已超时",
status: "danger"
}
]
+95
View File
@@ -0,0 +1,95 @@
<script lang="ts" setup>
import { ref, computed } from "vue"
import { ElMessage } from "element-plus"
import { Bell } from "@element-plus/icons-vue"
import NotifyList from "./NotifyList.vue"
import { type ListItem, notifyData, messageData, todoData } from "./data"
type TabName = "通知" | "消息" | "待办"
interface DataItem {
name: TabName
type: "primary" | "success" | "warning" | "danger" | "info"
list: ListItem[]
}
/** 角标当前值 */
const badgeValue = computed(() => {
return data.value.reduce((sum, item) => sum + item.list.length, 0)
})
/** 角标最大值 */
const badgeMax = 99
/** 面板宽度 */
const popoverWidth = 350
/** 当前 Tab */
const activeName = ref<TabName>("通知")
/** 所有数据 */
const data = ref<DataItem[]>([
// 通知数据
{
name: "通知",
type: "primary",
list: notifyData
},
// 消息数据
{
name: "消息",
type: "danger",
list: messageData
},
// 待办数据
{
name: "待办",
type: "warning",
list: todoData
}
])
const handleHistory = () => {
ElMessage.success(`跳转到${activeName.value}历史页面`)
}
</script>
<template>
<div class="notify">
<el-popover placement="bottom" :width="popoverWidth" trigger="click">
<template #reference>
<el-badge :value="badgeValue" :max="badgeMax" :hidden="badgeValue === 0">
<el-tooltip effect="dark" content="消息通知" placement="bottom">
<el-icon :size="20">
<Bell />
</el-icon>
</el-tooltip>
</el-badge>
</template>
<template #default>
<el-tabs v-model="activeName" class="demo-tabs" stretch>
<el-tab-pane v-for="(item, index) in data" :name="item.name" :key="index">
<template #label>
{{ item.name }}
<el-badge :value="item.list.length" :max="badgeMax" :type="item.type" />
</template>
<el-scrollbar height="400px">
<NotifyList :list="item.list" />
</el-scrollbar>
</el-tab-pane>
</el-tabs>
<div class="notify-history">
<el-button link @click="handleHistory">查看{{ activeName }}历史</el-button>
</div>
</template>
</el-popover>
</div>
</template>
<style lang="scss" scoped>
.notify {
margin-right: 10px;
color: var(--el-text-color-regular);
}
.notify-history {
text-align: center;
padding-top: 12px;
border-top: 1px solid var(--el-border-color);
}
</style>
@@ -0,0 +1,92 @@
<script lang="ts" setup>
import { computed, ref, watchEffect } from "vue"
import { ElMessage } from "element-plus"
import screenfull from "screenfull"
interface Props {
/** 全屏的元素,默认是 html */
element?: string
/** 打开全屏提示语 */
openTips?: string
/** 关闭全屏提示语 */
exitTips?: string
/** 是否只针对内容区 */
content?: boolean
}
const props = withDefaults(defineProps<Props>(), {
element: "html",
openTips: "全屏",
exitTips: "退出全屏",
content: false
})
//#region 全屏
const isFullscreen = ref<boolean>(false)
const fullscreenTips = computed(() => {
return isFullscreen.value ? props.exitTips : props.openTips
})
const fullscreenSvgName = computed(() => {
return isFullscreen.value ? "fullscreen-exit" : "fullscreen"
})
const handleFullscreenClick = () => {
const dom = document.querySelector(props.element) || undefined
screenfull.isEnabled ? screenfull.toggle(dom) : ElMessage.warning("您的浏览器无法工作")
}
const handleFullscreenChange = () => {
isFullscreen.value = screenfull.isFullscreen
}
watchEffect((onCleanup) => {
// 挂载组件时自动执行
screenfull.on("change", handleFullscreenChange)
// 卸载组件时自动执行
onCleanup(() => {
screenfull.isEnabled && screenfull.off("change", handleFullscreenChange)
})
})
//#endregion
//#region 内容区
const isContentLarge = ref<boolean>(false)
const contentLargeTips = computed(() => {
return isContentLarge.value ? "内容区复原" : "内容区放大"
})
const contentLargeSvgName = computed(() => {
return isContentLarge.value ? "fullscreen-exit" : "fullscreen"
})
const handleContentLargeClick = () => {
document.body.className = !isContentLarge.value ? "content-large" : ""
isContentLarge.value = !isContentLarge.value
}
//#endregion
</script>
<template>
<div>
<!-- 全屏 -->
<el-tooltip v-if="!content" effect="dark" :content="fullscreenTips" placement="bottom">
<SvgIcon :name="fullscreenSvgName" @click="handleFullscreenClick" />
</el-tooltip>
<!-- 内容区 -->
<el-dropdown v-else>
<SvgIcon :name="contentLargeSvgName" />
<template #dropdown>
<el-dropdown-menu>
<!-- 内容区放大 -->
<el-dropdown-item @click="handleContentLargeClick">{{ contentLargeTips }}</el-dropdown-item>
<!-- 内容区全屏 -->
<el-dropdown-item @click="handleFullscreenClick" :disabled="isFullscreen">内容区全屏</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<style lang="scss" scoped>
.svg-icon {
font-size: 20px;
&:focus {
outline: none;
}
}
</style>
@@ -0,0 +1,57 @@
<script lang="ts" setup>
import { computed } from "vue"
import { useAppStore } from "@/store/modules/app"
import { DeviceEnum } from "@/constants/app-key"
interface Props {
total: number
}
const props = defineProps<Props>()
const appStore = useAppStore()
const isMobile = computed(() => appStore.device === DeviceEnum.Mobile)
</script>
<template>
<div class="search-footer">
<template v-if="!isMobile">
<span class="search-footer-item">
<SvgIcon name="keyboard-enter" />
<span>确认</span>
</span>
<span class="search-footer-item">
<SvgIcon name="keyboard-up" />
<SvgIcon name="keyboard-down" />
<span>切换</span>
</span>
<span class="search-footer-item">
<SvgIcon name="keyboard-esc" />
<span>关闭</span>
</span>
</template>
<span class="search-footer-total">共 {{ props.total }} 项</span>
</div>
</template>
<style lang="scss" scoped>
.search-footer {
display: flex;
color: var(--el-text-color-secondary);
font-size: 14px;
&-item {
display: flex;
align-items: center;
margin-right: 12px;
.svg-icon {
margin-right: 5px;
padding: 2px;
font-size: 20px;
background-color: var(--el-fill-color);
}
}
&-total {
margin: 0 0 0 auto;
}
}
</style>
@@ -0,0 +1,219 @@
<script lang="ts" setup>
import { computed, ref, shallowRef } from "vue"
import { type RouteRecordName, type RouteRecordRaw, useRouter } from "vue-router"
import { useAppStore } from "@/store/modules/app"
import { usePermissionStore } from "@/store/modules/permission"
import SearchResult from "./SearchResult.vue"
import SearchFooter from "./SearchFooter.vue"
import { ElMessage, ElScrollbar } from "element-plus"
import { cloneDeep, debounce } from "lodash-es"
import { DeviceEnum } from "@/constants/app-key"
import { isExternal } from "@/utils/validate"
interface Props {
/** 控制 modal 显隐 */
modelValue: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
"update:modelValue": [boolean]
}>()
const appStore = useAppStore()
const router = useRouter()
const inputRef = ref<HTMLInputElement | null>(null)
const scrollbarRef = ref<InstanceType<typeof ElScrollbar> | null>(null)
const searchResultRef = ref<InstanceType<typeof SearchResult> | null>(null)
const keyword = ref<string>("")
const resultList = shallowRef<RouteRecordRaw[]>([])
const activeRouteName = ref<RouteRecordName | undefined>(undefined)
/** 是否按下了上键或下键(用于解决和 mouseenter 事件的冲突) */
const isPressUpOrDown = ref<boolean>(false)
/** 控制搜索对话框宽度 */
const modalWidth = computed(() => (appStore.device === DeviceEnum.Mobile ? "80vw" : "40vw"))
/** 控制搜索对话框显隐 */
const modalVisible = computed({
get() {
return props.modelValue
},
set(value: boolean) {
emit("update:modelValue", value)
}
})
/** 树形菜单 */
const menusData = computed(() => cloneDeep(usePermissionStore().routes))
/** 搜索(防抖) */
const handleSearch = debounce(() => {
const flatMenusData = flatTree(menusData.value)
resultList.value = flatMenusData.filter((menu) =>
keyword.value ? menu.meta?.title?.toLocaleLowerCase().includes(keyword.value.toLocaleLowerCase().trim()) : false
)
// 默认选中搜索结果的第一项
const length = resultList.value?.length
activeRouteName.value = length > 0 ? resultList.value[0].name : undefined
}, 500)
/** 将树形菜单扁平化为一维数组,用于菜单搜索 */
const flatTree = (arr: RouteRecordRaw[], result: RouteRecordRaw[] = []) => {
arr.forEach((item) => {
result.push(item)
item.children && flatTree(item.children, result)
})
return result
}
/** 关闭搜索对话框 */
const handleClose = () => {
modalVisible.value = false
// 延时处理防止用户看到重置数据的操作
setTimeout(() => {
keyword.value = ""
resultList.value = []
}, 200)
}
/** 根据下标位置进行滚动 */
const scrollTo = (index: number) => {
if (!searchResultRef.value) return
const scrollTop = searchResultRef.value.getScrollTop(index)
// 手动控制 el-scrollbar 滚动条滚动,设置滚动条到顶部的距离
scrollbarRef.value?.setScrollTop(scrollTop)
}
/** 键盘上键 */
const handleUp = () => {
isPressUpOrDown.value = true
const { length } = resultList.value
if (length === 0) return
// 获取该 name 在菜单中第一次出现的位置
const index = resultList.value.findIndex((item) => item.name === activeRouteName.value)
// 如果已处在顶部
if (index === 0) {
const bottomName = resultList.value[length - 1].name
// 如果顶部和底部的 bottomName 相同,且长度大于 1,就再跳一个位置(可解决遇到首尾两个相同 name 导致的上键不能生效的问题)
if (activeRouteName.value === bottomName && length > 1) {
activeRouteName.value = resultList.value[length - 2].name
scrollTo(length - 2)
} else {
// 跳转到底部
activeRouteName.value = bottomName
scrollTo(length - 1)
}
} else {
activeRouteName.value = resultList.value[index - 1].name
scrollTo(index - 1)
}
}
/** 键盘下键 */
const handleDown = () => {
isPressUpOrDown.value = true
const { length } = resultList.value
if (length === 0) return
// 获取该 name 在菜单中最后一次出现的位置(可解决遇到连续两个相同 name 导致的下键不能生效的问题)
const index = resultList.value.map((item) => item.name).lastIndexOf(activeRouteName.value)
// 如果已处在底部
if (index === length - 1) {
const topName = resultList.value[0].name
// 如果底部和顶部的 topName 相同,且长度大于 1,就再跳一个位置(可解决遇到首尾两个相同 name 导致的下键不能生效的问题)
if (activeRouteName.value === topName && length > 1) {
activeRouteName.value = resultList.value[1].name
scrollTo(1)
} else {
// 跳转到顶部
activeRouteName.value = topName
scrollTo(0)
}
} else {
activeRouteName.value = resultList.value[index + 1].name
scrollTo(index + 1)
}
}
/** 键盘回车键 */
const handleEnter = () => {
const { length } = resultList.value
if (length === 0) return
const name = activeRouteName.value
const path = resultList.value.find((item) => item.name === name)?.path
if (path && isExternal(path)) {
window.open(path, "_blank", "noopener, noreferrer")
return
}
if (!name) {
ElMessage.warning("无法通过搜索进入该菜单,请为对应的路由设置唯一的 Name")
return
}
try {
router.push({ name })
} catch {
ElMessage.error("该菜单有必填的动态参数,无法通过搜索进入")
return
}
handleClose()
}
/** 释放上键或下键 */
const handleReleaseUpOrDown = () => {
isPressUpOrDown.value = false
}
</script>
<template>
<el-dialog
v-model="modalVisible"
@opened="inputRef?.focus()"
@closed="inputRef?.blur()"
@keydown.up="handleUp"
@keydown.down="handleDown"
@keydown.enter="handleEnter"
@keyup.up.down="handleReleaseUpOrDown"
:before-close="handleClose"
:width="modalWidth"
top="5vh"
class="search-modal__private"
append-to-body
>
<el-input ref="inputRef" v-model="keyword" @input="handleSearch" placeholder="搜索菜单" size="large" clearable>
<template #prefix>
<SvgIcon name="search" />
</template>
</el-input>
<el-empty v-if="resultList.length === 0" description="暂无搜索结果" :image-size="100" />
<template v-else>
<p>搜索结果</p>
<el-scrollbar ref="scrollbarRef" max-height="40vh" always>
<SearchResult
ref="searchResultRef"
v-model="activeRouteName"
:list="resultList"
:isPressUpOrDown="isPressUpOrDown"
@click="handleEnter"
/>
</el-scrollbar>
</template>
<template #footer>
<SearchFooter :total="resultList.length" />
</template>
</el-dialog>
</template>
<style lang="scss">
.search-modal__private {
.svg-icon {
font-size: 18px;
}
.el-dialog__header {
display: none;
}
.el-dialog__footer {
border-top: 1px solid var(--el-border-color);
padding: var(--el-dialog-padding-primary);
}
}
</style>
@@ -0,0 +1,122 @@
<script lang="ts" setup>
import { computed, getCurrentInstance, onBeforeMount, onBeforeUnmount, onMounted, ref } from "vue"
import { type RouteRecordName, type RouteRecordRaw } from "vue-router"
interface Props {
modelValue: RouteRecordName | undefined
list: RouteRecordRaw[]
isPressUpOrDown: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
"update:modelValue": [RouteRecordName | undefined]
}>()
const instance = getCurrentInstance()
const scrollbarHeight = ref<number>(0)
/** 选中的菜单 */
const activeRouteName = computed({
get() {
return props.modelValue
},
set(value: RouteRecordName | undefined) {
emit("update:modelValue", value)
}
})
/** 菜单的样式 */
const itemStyle = (item: RouteRecordRaw) => {
const flag = item.name === activeRouteName.value
return {
background: flag ? "var(--el-color-primary)" : "",
color: flag ? "#fff" : ""
}
}
/** 鼠标移入 */
const handleMouseenter = (item: RouteRecordRaw) => {
// 如果上键或下键与 mouseenter 事件同时生效,则以上下键为准,不执行该函数的赋值逻辑
if (props.isPressUpOrDown) return
activeRouteName.value = item.name
}
/** 计算滚动可视区高度 */
const getScrollbarHeight = () => {
// el-scrollbar max-height="40vh"
scrollbarHeight.value = Number((window.innerHeight * 0.4).toFixed(1))
}
/** 根据下标计算到顶部的距离 */
const getScrollTop = (index: number) => {
const currentInstance = instance?.proxy?.$refs[`resultItemRef${index}`] as HTMLDivElement[]
if (!currentInstance) return 0
const currentRef = currentInstance[0]
const scrollTop = currentRef.offsetTop + 128 // 128 = 两个 result-item (56 + 56 = 112)高度与上下 margin(8 + 8 = 16)大小之和
return scrollTop > scrollbarHeight.value ? scrollTop - scrollbarHeight.value : 0
}
/** 在组件挂载前添加窗口大小变化事件监听器 */
onBeforeMount(() => {
window.addEventListener("resize", getScrollbarHeight)
})
/** 在组件挂载时立即计算滚动可视区高度 */
onMounted(() => {
getScrollbarHeight()
})
/** 在组件卸载前移除窗口大小变化事件监听器 */
onBeforeUnmount(() => {
window.removeEventListener("resize", getScrollbarHeight)
})
defineExpose({ getScrollTop })
</script>
<template>
<!-- 外层 div 不能删除,是用来接收父组件 click 事件的 -->
<div>
<div
v-for="(item, index) in list"
:key="index"
:ref="`resultItemRef${index}`"
class="result-item"
:style="itemStyle(item)"
@mouseenter="handleMouseenter(item)"
>
<SvgIcon v-if="item.meta?.svgIcon" :name="item.meta.svgIcon" />
<component v-else-if="item.meta?.elIcon" :is="item.meta.elIcon" class="el-icon" />
<span class="result-item-title">
{{ item.meta?.title }}
</span>
<SvgIcon v-if="activeRouteName && activeRouteName === item.name" name="keyboard-enter" />
</div>
</div>
</template>
<style lang="scss" scoped>
.result-item {
display: flex;
align-items: center;
height: 56px;
padding: 0 15px;
margin-top: 8px;
border: 1px solid var(--el-border-color);
border-radius: 4px;
cursor: pointer;
.svg-icon {
min-width: 1em;
font-size: 18px;
}
.el-icon {
width: 1em;
font-size: 18px;
}
&-title {
flex: 1;
margin-left: 12px;
}
}
</style>
@@ -0,0 +1,29 @@
<script lang="ts" setup>
import { ref } from "vue"
import SearchModal from "./SearchModal.vue"
/** 控制 modal 显隐 */
const modalVisible = ref<boolean>(false)
/** 打开 modal */
const handleOpen = () => {
modalVisible.value = true
}
</script>
<template>
<div>
<el-tooltip effect="dark" content="搜索菜单" placement="bottom">
<SvgIcon name="search" @click="handleOpen" />
</el-tooltip>
<SearchModal v-model="modalVisible" />
</div>
</template>
<style lang="scss" scoped>
.svg-icon {
font-size: 20px;
&:focus {
outline: none;
}
}
</style>
@@ -0,0 +1,29 @@
<script lang="ts" setup>
import { computed } from "vue"
interface Props {
prefix?: string
name: string
}
const props = withDefaults(defineProps<Props>(), {
prefix: "icon"
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
<template>
<svg class="svg-icon" aria-hidden="true">
<use :href="symbolId" />
</svg>
</template>
<style lang="scss" scoped>
.svg-icon {
width: 1em;
height: 1em;
fill: currentColor;
overflow: hidden;
}
</style>
@@ -0,0 +1,30 @@
<script lang="ts" setup>
import { useTheme } from "@/hooks/useTheme"
import { MagicStick } from "@element-plus/icons-vue"
const { themeList, activeThemeName, setTheme } = useTheme()
</script>
<template>
<el-dropdown trigger="click" @command="setTheme">
<div>
<el-tooltip effect="dark" content="主题模式" placement="bottom">
<el-icon :size="20">
<MagicStick />
</el-icon>
</el-tooltip>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="(theme, index) in themeList"
:key="index"
:disabled="activeThemeName === theme.name"
:command="theme.name"
>
<span>{{ theme.title }}</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
+12
View File
@@ -0,0 +1,12 @@
export interface IGlobalConfig {
baseApiUrl: string
}
export const loadConfigFile = async () => {
const response = await fetch('/js/globalConfig.json');
if (!response.ok) {
throw new Error('Failed to load configuration file');
}
return response.json();
};
+48
View File
@@ -0,0 +1,48 @@
import { getConfigLayout } from "@/utils/cache/local-storage"
/** 项目配置类型 */
export interface LayoutSettings {
/** 是否显示 Settings Panel */
showSettings: boolean
/** 布局模式 */
layoutMode: "left" | "top" | "left-top"
/** 是否显示标签栏 */
showTagsView: boolean
/** 是否显示 Logo */
showLogo: boolean
/** 是否固定 Header */
fixedHeader: boolean
/** 是否显示消息通知 */
showNotify: boolean
/** 是否显示切换主题按钮 */
showThemeSwitch: boolean
/** 是否显示全屏按钮 */
showScreenfull: boolean
/** 是否显示搜索按钮 */
showSearchMenu: boolean
/** 是否缓存标签栏 */
cacheTagsView: boolean
/** 是否显示灰色模式 */
showGreyMode: boolean
/** 是否显示色弱模式 */
showColorWeakness: boolean
}
/** 默认配置 */
const defaultSettings: LayoutSettings = {
layoutMode: "left",
showSettings: true,
showTagsView: true,
fixedHeader: true,
showLogo: true,
showNotify: true,
showThemeSwitch: true,
showScreenfull: true,
showSearchMenu: true,
cacheTagsView: false,
showGreyMode: false,
showColorWeakness: false
}
/** 项目配置 */
export const layoutSettings: LayoutSettings = { ...defaultSettings, ...getConfigLayout() }
+28
View File
@@ -0,0 +1,28 @@
/** 动态路由配置 */
interface RouteSettings {
/**
* 是否开启动态路由功能?
* 1. 开启后需要后端配合,在查询用户详情接口返回当前用户可以用来判断并加载动态路由的字段(该项目用的是角色 roles 字段)
* 2. 假如项目不需要根据不同的用户来显示不同的页面,则应该将 async: false
*/
async: boolean
/** 当动态路由功能关闭时:
* 1. 应该将所有路由都写到常驻路由里面(表明所有登陆的用户能访问的页面都是一样的)
* 2. 系统自动给当前登录用户赋值一个没有任何作用的默认角色
*/
defaultRoles: Array<string>
/**
* 是否开启三级及其以上路由缓存功能?
* 1. 开启后会进行路由降级(把三级及其以上的路由转化为二级路由)
* 2. 由于都会转成二级路由,所以二级及其以上路由有内嵌子路由将会失效
*/
thirdLevelRouteCache: boolean
}
const routeSettings: RouteSettings = {
async: false,
defaultRoles: ["DEFAULT_ROLE"],
thirdLevelRouteCache: false
}
export default routeSettings
+15
View File
@@ -0,0 +1,15 @@
import { type RouteLocationNormalized } from "vue-router"
/** 免登录白名单(匹配路由 path) */
const whiteListByPath: string[] = ["/login"]
/** 免登录白名单(匹配路由 name) */
const whiteListByName: string[] = []
/** 判断是否在白名单 */
const isWhiteList = (to: RouteLocationNormalized) => {
// path 和 name 任意一个匹配上即可
return whiteListByPath.indexOf(to.path) !== -1 || whiteListByName.indexOf(to.name as any) !== -1
}
export default isWhiteList
+13
View File
@@ -0,0 +1,13 @@
/** 设备类型 */
export enum DeviceEnum {
Mobile,
Desktop
}
/** 侧边栏打开状态常量 */
export const SIDEBAR_OPENED = "opened"
/** 侧边栏关闭状态常量 */
export const SIDEBAR_CLOSED = "closed"
export type SidebarOpened = typeof SIDEBAR_OPENED
export type SidebarClosed = typeof SIDEBAR_CLOSED
+15
View File
@@ -0,0 +1,15 @@
const SYSTEM_NAME = "acs-office"
/** 缓存数据时用到的 Key */
class CacheKey {
static readonly TOKEN = `${SYSTEM_NAME}-token-key`
static readonly CONFIG_LAYOUT = `${SYSTEM_NAME}-config-layout-key`
static readonly SIDEBAR_STATUS = `${SYSTEM_NAME}-sidebar-status-key`
static readonly ACTIVE_THEME_NAME = `${SYSTEM_NAME}-active-theme-name-key`
static readonly VISITED_VIEWS = `${SYSTEM_NAME}-visited-views-key`
static readonly CACHED_VIEWS = `${SYSTEM_NAME}-cached-views-key`
static readonly PRODUCTION_CONFIG = `${SYSTEM_NAME}-cached-production-config-key`
static readonly USER_NAME = `${SYSTEM_NAME}-cached-username-key`
}
export default CacheKey
+7
View File
@@ -0,0 +1,7 @@
import { type App } from "vue"
import { permission } from "./permission"
/** 挂载自定义指令 */
export function loadDirectives(app: App) {
app.directive("permission", permission)
}
@@ -0,0 +1,17 @@
import { type Directive } from "vue"
import { useUserStoreHook } from "@/store/modules/user"
/** 权限指令,和权限判断函数 checkPermission 功能类似 */
export const permission: Directive = {
mounted(el, binding) {
const { value: permissionRoles } = binding
const { roles } = useUserStoreHook()
if (Array.isArray(permissionRoles) && permissionRoles.length > 0) {
const hasPermission = roles.some((role) => permissionRoles.includes(role))
// hasPermission || (el.style.display = "none") // 隐藏
hasPermission || el.parentNode?.removeChild(el) // 销毁
} else {
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
}
}
}
+126
View File
@@ -0,0 +1,126 @@
export interface AgvTask{
/**
* 唯一标识 (GUID)
*/
id: string;
/**
* ERP 任务 ID (GUID)
*/
erpTaskId: string;
/**
* 合格证号
*/
barCode: string;
/**
* 订单号
*/
orderNo: string;
/**
* 用户名称
*/
customName: string;
/**
* 物料名称
*/
materiaName: string;
/**
* 物料类型
*/
materiaType: string;
/**
* 单个托盘上面的物料数量
*/
materiaNum: number;
/**
* 批次号(作业单号 + 日期 + 班次)
*/
materiaBatch: string;
/**
* 物料编号
*/
materiaCode: string;
/**
* 联动线出口,机械手设备唯一号
*/
equipmentNo: string;
/**
* 工单状态
*/
taskStatus: number;
/**
* 任务类型
*/
taskType: number;
/**
* 优先级
*/
priority: number;
/**
* 楼层
*/
floor: number;
/**
* 起点(库位编号)
*/
startPositionCode: string;
/**
* 终点(库位编号)
*/
endPositionCode: string;
/**
* 码头位置
*/
transport: number;
/**
* 任务是否锁定(true 表示锁定,false 表示未锁定)
*/
isLock: boolean;
/**
* ERP 数据上传状态
*/
erpUploadStatus: number;
/**
* ERP 返回错误信息
*/
erpReturnMsg: string;
/**
* 重试次数
*/
retryNum: number;
/**
* 分组 ID (GUID)
*/
groupId: string;
/**
* 创建时间(可选)
*/
creationTime?: Date;
/**
* 修改时间(可选)
*/
lastModifiedTime?: Date;
}
@@ -0,0 +1,28 @@
export class ProductionConfig {
web!: number
isDoubleLevel!: boolean
maxLevel!: number
position?: string
mainKnife?: string
maxSpeed?: number
cycleDayTime?: number
paperCodeWordMaxLen?: number
maxSecNum?: number
maxLineNum?: number
rcvOrderFilePath?: string
historyFilePath?: string
recycleFilePath?: string
showInchWeb?: boolean
continuousStop?: number
minSecWidth?: number
minCutlength?: number
localIpAdderss?: string
trimHighLightMinValue?: number
lineCode?: string
enableSpeed?: boolean
stkSecWidth?: number
threeBestSpd?: number
fiveBestSpd?: number
sevenBestSpd?: number
minBestSpd?: number
}
+139
View File
@@ -0,0 +1,139 @@
export interface ErpTask{
/**
* 唯一标识
*/
Id: string; // GUID 转换为 string
/**
* 库位编号(起点)
*/
StorageRackNo: string;
/**
* 订单号
*/
OrderNo: string;
/**
* 生产退库单号
*/
ProduceReturnCode: string;
/**
* 销售单号
*/
SaleNo: string;
/**
* 销售退库单号
*/
SaleReturnCode: string;
/**
* 合格证号
*/
BarCode: string;
/**
* 用户名称
*/
CustomName: string;
/**
* 物料名称
*/
MateriaName: string;
/**
* 物料类型
*/
MateriaType: string;
/**
* 批次号的生成规则为:作业单号+日期+班次
*/
MateriaBatch: string;
/**
* 物料编号
*/
MateriaCode: string;
/**
* 联动线出口,机械手设备唯一号
*/
EquipmentNo: string;
/**
* erp下发命令中出入库总数量
*/
ErpOrderNum: number;
/**
* 任务状态
*/
TaskStatus: number;
/**
* 任务类型
*/
TaskType: number;
/**
* 楼层(入库,尾托回库指定楼层使用)
*/
Floor: number;
/**
* 码头位置 1:北区 2:南区 3:人工 4:退货到车间 99:其它
*/
Transport: number;
/**
* 优先级 1:入库 10:出库 20:托盘入库 30:托盘出库 40:移库 99:其它
*/
Priority: number;
/**
* 锁定 false:未锁定 true:锁定
*/
IsLock: boolean;
/**
* 已上传给Erp的数量
*/
AlreadyUploadNum: number;
/**
* Erp出库撤单数量
*/
ErpCancelNum: number;
/**
* 回调Erp失败/成功 1:成功 0:失败
*/
IsCallBackErpEnd: boolean;
/**
* Erp回调Wms接口地址
*/
ErpCallWmsInterface: string;
/**
* Wms回调Erp接口地址
*/
WmsCallErpInterface: string;
//任务信息(生成失败提示等)
TaskMsg:string,
/**
* 创建时间
*/
CreationTime?: Date; // 可空类型
/**
* 修改时间
*/
LastModifiedTime?: Date; // 可空类型
}
@@ -0,0 +1,5 @@
export interface ErpTaskQueryParam {
StartTime: Date,
EndTime: Date,
TaskType: number
}
@@ -0,0 +1,19 @@
export interface OperationLog {
OperationSource: number,
OperationType: number,
UserId: string,
OldObject: string,
NewObject: string,
CreationTime: Date,
LastModifiedTime: Date
}
export interface OperationLogQueryParam {
StartTime?: Date,
EndTime?: Date,
UserId: string,
OperationType: number,
OperationSource: number,
PageIndex: number,
PageSize: number
}
@@ -0,0 +1,25 @@
export interface PaperBaseInfo {
Barcode: string // 条码
StockItem: string // 物料号
StockDescription: string // 规格型号说明
Location: string //库区
LocSub: string //库位
StockMark: string // 残卷标志
Paper: string // 材质
PaperWidth: string // 幅宽
GPerM2: string // 克重
ActualQty: string // 重量(公斤)
Diameter: string // 直径(毫米)
StockMeter: string // 米数(米)
Maker: string // 制造商
SuppID: string // 供应商编号
SuppShortName: string //供应商简称
ReceiveNote: string // 入库单号
Remark: string // 备注
ReservedCustID: string // 来料客户编号
Status: string //状态
CanUse: string // 可用状态
StockChecking: string //盘点状态
ObjID: string //该纸卷库存的唯一身份标记
InWeight:string //回库重量
}
@@ -0,0 +1,11 @@
export interface PaperCostInfo {
Date: string,
PaperStockOutWeightTotal: number,
PaperStockInWeightTotal: number,
PaperCostTotal: number
}
export interface PaperCostInfoQueryParam{
startTime:string,
endTime:string
}
@@ -0,0 +1,6 @@
export interface PaperUsingRateInfo {
Date: string,
Supplier: string,
PaperCode: string,
UsingRate: string
}
@@ -0,0 +1,23 @@
export interface PaperWastageStatisticInfo
{
Date:string,
Group:string,
HC:MachinePaperInfo,
SF1W:MachinePaperInfo,
SF1X:MachinePaperInfo,
SF2W:MachinePaperInfo,
SF2X:MachinePaperInfo
}
export interface MachinePaperInfo
{
Plan:number,
Used:number,
Wastage:number
}
export interface PaperWastageStatisticQueryParam{
startTime: string;
endTime: string;
}
@@ -0,0 +1,131 @@
import { UUID } from "crypto"
//订单用纸信息
export interface PaperOrderMapInfo {
[key: string]: string | number | undefined | null | void|UUID|Date
Id: UUID; // 在TypeScript中,通常使用string类型代替C#中的Guid,除非有特定的库支持Guid类型
/// <summary>
/// 卷标
/// </summary>
PaperLabel: string;
/// <summary>
/// 纸卷上架时间
/// </summary>
UpTime: Date;
/// <summary>
/// 纸卷下架时间
/// </summary>
DownTime: Date;
/// <summary>
/// 纸卷使用长度
/// </summary>
UsedLength: number;
/// <summary>
/// 幅宽
/// </summary>
Breadth: number;
/// <summary>
/// 纸卷材质
/// </summary>
PaperMaterial: string;
/// <summary>
/// 机台
/// </summary>
MachineNum: string;
/// <summary>
/// 楞型
/// </summary>
Flute: string;
/// <summary>
/// 订单号
/// </summary>
OrderId: string;
/// <summary>
/// 订单号
/// </summary>
OrderNo: string;
/// <summary>
/// 客户名称
/// </summary>
CustomName: string;
/// <summary>
/// 订单楞型
/// </summary>
OrderFlutes: string;
/// <summary>
/// 订单每片长度
/// </summary>
OrderLength: number;
/// <summary>
/// 订单每片宽度
/// </summary>
OrderWidth: number;
/// <summary>
/// 计划生产片数
/// </summary>
OrderPlanqty: number;
/// <summary>
/// 实际生产片数
/// </summary>
OrderProdqty: number;
/// <summary>
/// 订单开始生产时间
/// </summary>
OrderStartTime: Date;
/// <summary>
/// 创建时间
/// </summary>
CreationTime?: Date; // 使用?表示这个属性是可选的,即可以为null或undefined
/// <summary>
/// 修改时间
/// </summary>
LastModifiedTime?: Date; // 同样,这个属性也是可选的
}
//订单用纸信息查询参数
export interface PaperOrderMapQueryParam{
/// <summary>
/// 开始时间
/// </summary>
StartTime?: Date;
/// <summary>
/// 结束时间
/// </summary>
EndTime?: Date;
/// <summary>
/// 订单号
/// </summary>
OrderNo: string;
/// <summary>
/// 订单号集合
/// </summary>
OrderNoList: Array<string>;
/// <summary>
/// 卷标
/// </summary>
PaperLabel: string;
/// <summary>
/// 纸质
/// </summary>
PaperCode: string;
/// <summary>
/// 门幅
/// </summary>
PaperWidth: string;
/// <summary>
/// 机台
/// </summary>
MachineNum: string;
/// <summary>
/// 订单号
/// </summary>
OrderId: string;
/// <summary>
/// 页码
/// </summary>
PageIndex: number,
/// <summary>
/// 每页显示的数据条数
/// </summary>
PageSize: number,
}
@@ -0,0 +1,4 @@
export interface PaperOrderMapNew {
date: string
name: string
}
@@ -0,0 +1,161 @@
import { UUID } from "crypto"
export interface PaperReplace {
[key: string]: string | number | undefined | null | void | UUID | Date
Id: UUID; // 在TypeScript中,通常使用string类型代替C#中的Guid,除非有特定的库支持Guid类型
/**
* 原纸卷标
*/
PaperLabel: string;
/**
* 产线名称
*/
ProductLineName: string;
/**
* 供应商
*/
Supplier: string;
/**
* 制造商
*/
MakerName: string;
/**
* 仓库名称
*/
StockHouseName: string;
/**
* 库位
*/
LocationMark: string;
/**
* 原纸克重
*/
PaperUnitWeight: number;
/**
* 原纸编码(纸质)
*/
PaperCode: string;
/**
* 门幅
*/
PaperWidth: number;
/**
* PLC原纸编码
*/
PLCCode: string;
/**
* PLC门幅
*/
PLCWidth: number;
/**
* 代纸开始时间
*/
StartTime: Date;
/**
* 代纸结束时间
*/
EndTime: Date;
/**
* 代纸米长
*/
ReplaceLength: number;
/**机台 */
MachineNum: string;
/**
* 备注
*/
Memo: string;
/**
* 创建时间
*/
CreationTime?: Date;
/**
* 修改时间
*/
LastModifiedTime?: Date;
/**
* 原纸信息批次ID
*/
BathId: string; // 注意:在TypeScript中,Guid通常表示为字符串
/**
* ERP接口更新状态
*/
WantitErpUploadStatus: number;
/**
* ERP接口返回信息
*/
ErpStockInMsg: string;
}
export interface PaperReplaceQueryParam {
StartTime: string;
EndTime: string;
/**
* 卷标
*/
PaperLabel: string;
/**
* 产线名称
*/
ProductLineName: string;
/**
* 班组
*/
TeamName: string;
/**
* 纸质
*/
PaperCode: string;
/**
* 门幅
*/
PaperWidth: string;
/**
* 需求的材质
*/
WanttedCode: string;
/**
* 需求的门幅
*/
WanttedWidth?: string; // 同上,通常在数据库中门幅是数值类型。
/**
* 代纸米长
*/
ReplaceLength: string;
//机台
MachineNum: string;
/// <summary>
/// 页码
/// </summary>
PageIndex: number;
/// <summary>
/// 每页显示的数据条数
/// </summary>
PageSize: number;
}

Some files were not shown because too many files have changed in this diff Show More