Merge branch 'dev_NEW_pro' into dev_宁夏_英泽防锈
# Conflicts:
# multiple/config.json
# src/assets/styles/sidebar.scss
| | |
| | | }); |
| | | } |
| | | export function updateApprovalStatus(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/updateApprovalStatus", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | return request({ |
| | | url: "/purchase/ledger/updateApprovalStatus", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // 保存采购模板 |
| | | export function addPurchaseTemplate(data) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // 修改采购模板 |
| | | export function updatePurchaseTemplate(data) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // 查询采购模板 |
| | | export function getPurchaseTemplateList(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseTemplateList", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseTemplateList", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // 删除采购模板 |
| | | export function delPurchaseTemplate(id) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/delete", |
| | | method: "delete", |
| | | data: id, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/delete", |
| | | method: "delete", |
| | | data: id, |
| | | }); |
| | | } |
| | | // 查询采购详情 |
| | | export function getPurchaseByCode(id) { |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseByCode", |
| | | method: "get", |
| | | params: id, |
| | | }); |
| | | } |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseByCode", |
| | | method: "get", |
| | | params: id, |
| | | }); |
| | | } |
| | | |
| | | export function batchGeneratePurchaseInboundSteps(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/batchInsertPurchaseSteps", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | |
| | | #app {
|
| | | .main-container {
|
| | | min-height: 100vh;
|
| | | margin-left: var(--sidebar-width);
|
| | | transition: margin-left 0.25s ease;
|
| | | position: relative;
|
| | | background: transparent;
|
| | | }
|
| | |
|
| | | .sidebarHide {
|
| | | margin-left: 0 !important;
|
| | | }
|
| | |
|
| | | .sidebar-container {
|
| | | transition: width 0.25s ease;
|
| | | width: var(--sidebar-width) !important;
|
| | | height: 100vh;
|
| | | position: fixed;
|
| | | top: 0;
|
| | | left: 0;
|
| | | z-index: 1001;
|
| | | overflow: hidden;
|
| | | padding: 0;
|
| | | font-size: 0;
|
| | | background: var(--sidebar-bg);
|
| | | border-right: 1px solid rgba(255, 255, 255, 0.08);
|
| | | box-shadow: 8px 0 24px rgba(15, 23, 42, 0.08);
|
| | | isolation: isolate;
|
| | |
|
| | | &::before {
|
| | | content: "";
|
| | | position: absolute;
|
| | | inset: -28% -52% -18% -38%;
|
| | | z-index: 0;
|
| | | pointer-events: none;
|
| | | background:
|
| | | radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%),
|
| | | radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%),
|
| | | radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%),
|
| | | radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%),
|
| | | conic-gradient(
|
| | | from 210deg at 58% 38%,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg,
|
| | | rgba(56, 189, 248, 0.05) 76deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg,
|
| | | rgba(125, 211, 252, 0.04) 290deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg
|
| | | );
|
| | | filter: blur(7px) saturate(1.24) contrast(1.05);
|
| | | opacity: 0.96;
|
| | | transform: translate3d(0, 0, 0);
|
| | | transform-origin: 44% 58%;
|
| | | animation:
|
| | | sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite,
|
| | | sidebarAuroraBreath 9.7s ease-in-out infinite,
|
| | | sidebarAuroraSkew 6.9s steps(23, end) infinite;
|
| | | }
|
| | |
|
| | | &::after {
|
| | | content: "";
|
| | | position: absolute;
|
| | | inset: 0;
|
| | | z-index: 0;
|
| | | pointer-events: none;
|
| | | background:
|
| | | linear-gradient(
|
| | | 108deg,
|
| | | transparent 10%,
|
| | | rgba(255, 255, 255, 0.17) 34%,
|
| | | rgba(255, 255, 255, 0.04) 48%,
|
| | | transparent 72%
|
| | | ),
|
| | | linear-gradient(
|
| | | 202deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%,
|
| | | transparent 34%,
|
| | | rgba(56, 189, 248, 0.18) 66%,
|
| | | transparent 100%
|
| | | ),
|
| | | radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%),
|
| | | radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%);
|
| | | background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%;
|
| | | background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%;
|
| | | opacity: 0.52;
|
| | | transform: translate3d(0, 0, 0);
|
| | | animation:
|
| | | sidebarSheenSweep 13.1s linear infinite,
|
| | | sidebarSheenJitter 4.7s steps(31, end) infinite;
|
| | | }
|
| | |
|
| | | > * {
|
| | | position: relative;
|
| | | z-index: 1;
|
| | | }
|
| | |
|
| | | .horizontal-collapse-transition {
|
| | | transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
| | | }
|
| | |
|
| | | .scrollbar-wrapper {
|
| | | overflow-x: hidden !important;
|
| | | overflow-y: auto !important;
|
| | | }
|
| | |
|
| | | .el-scrollbar__bar.is-vertical {
|
| | | right: 2px;
|
| | | }
|
| | |
|
| | | .el-scrollbar {
|
| | | height: 100%;
|
| | | }
|
| | |
|
| | | &.has-logo {
|
| | | .el-scrollbar {
|
| | | height: calc(100% - 78px);
|
| | | }
|
| | | }
|
| | |
|
| | | .is-horizontal {
|
| | | display: none;
|
| | | }
|
| | |
|
| | | a {
|
| | | display: inline-block;
|
| | | width: 100%;
|
| | | overflow: hidden;
|
| | | }
|
| | |
|
| | | .el-menu {
|
| | | border: none !important;
|
| | | height: 100%;
|
| | | width: 100% !important;
|
| | | padding: 10px 0 16px;
|
| | | border-radius: 0;
|
| | | background: transparent !important;
|
| | | box-shadow: none;
|
| | | backdrop-filter: none;
|
| | | }
|
| | |
|
| | | .el-menu-item,
|
| | | .el-sub-menu__title,
|
| | | .menu-title {
|
| | | overflow: hidden !important;
|
| | | text-overflow: ellipsis !important;
|
| | | white-space: nowrap !important;
|
| | | }
|
| | |
|
| | | .el-menu-item .el-menu-tooltip__trigger {
|
| | | display: inline-flex !important;
|
| | | width: 100%;
|
| | | align-items: center;
|
| | | }
|
| | |
|
| | | .submenu-title-noDropdown,
|
| | | .el-sub-menu__title,
|
| | | .el-menu-item {
|
| | | min-width: 0 !important;
|
| | | width: calc(100% - 24px) !important;
|
| | | margin: 0 12px 8px !important;
|
| | | height: 50px;
|
| | | line-height: 50px;
|
| | | border-radius: 14px;
|
| | | padding-left: 16px !important;
|
| | | padding-right: 36px !important;
|
| | | box-sizing: border-box;
|
| | | transition: all 0.28s ease;
|
| | | color: var(--sidebar-text);
|
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01));
|
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important;
|
| | | position: relative;
|
| | | overflow: hidden;
|
| | | }
|
| | |
|
| | | .submenu-title-noDropdown::after,
|
| | | .el-sub-menu__title::after,
|
| | | .el-menu-item::after {
|
| | | content: "";
|
| | | position: absolute;
|
| | | inset: 0;
|
| | | background: linear-gradient(115deg, transparent 12%, rgba(255, 255, 255, 0.16), transparent 78%);
|
| | | transform: translateX(-100%);
|
| | | opacity: 0;
|
| | | transition: transform 0.45s ease, opacity 0.26s ease;
|
| | | pointer-events: none;
|
| | | }
|
| | |
|
| | | .submenu-title-noDropdown:hover,
|
| | | .el-sub-menu__title:hover,
|
| | | .el-menu-item:hover {
|
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.28), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.08)) !important;
|
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.32) !important;
|
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 8px 18px rgba(8, 36, 76, 0.24);
|
| | | transform: translateX(3px);
|
| | | }
|
| | |
|
| | | .submenu-title-noDropdown:hover::after,
|
| | | .el-sub-menu__title:hover::after,
|
| | | .el-menu-item:hover::after,
|
| | | .el-menu-item.is-active::after,
|
| | | .el-sub-menu.is-active > .el-sub-menu__title::after {
|
| | | transform: translateX(100%);
|
| | | opacity: 1;
|
| | | }
|
| | |
|
| | | & .theme-light .is-active > .el-sub-menu__title,
|
| | | & .theme-dark .is-active > .el-sub-menu__title,
|
| | | & .el-menu-item.is-active {
|
| | | color: #fff !important;
|
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
|
| | | background-size: 180% 180%;
|
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
|
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important;
|
| | | animation: sidebarActiveFlow 4.6s ease infinite;
|
| | | }
|
| | |
|
| | | & .nest-menu .el-sub-menu > .el-sub-menu__title,
|
| | | & .el-sub-menu .el-menu-item {
|
| | | min-width: 0 !important;
|
| | | width: calc(100% - 24px) !important;
|
| | | margin: 0 12px 8px !important;
|
| | | height: 46px;
|
| | | line-height: 46px;
|
| | | padding-left: 14px !important;
|
| | | padding-right: 14px !important;
|
| | | border-radius: 12px;
|
| | | transition: all 0.24s ease;
|
| | | color: var(--sidebar-text);
|
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important;
|
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
|
| | |
|
| | | &:hover {
|
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important;
|
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important;
|
| | | transform: translateX(2px);
|
| | | }
|
| | |
|
| | | &.is-active {
|
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
|
| | | background-size: 180% 180%;
|
| | | color: #fff !important;
|
| | | font-weight: 500;
|
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
|
| | | animation: sidebarActiveFlow 4.6s ease infinite;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .hideSidebar {
|
| | | .sidebar-container {
|
| | | width: var(--sidebar-collapsed-width) !important;
|
| | | }
|
| | |
|
| | | .main-container {
|
| | | margin-left: var(--sidebar-collapsed-width);
|
| | | }
|
| | |
|
| | | .submenu-title-noDropdown {
|
| | | padding: 0 !important;
|
| | | position: relative;
|
| | | display: flex !important;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | |
|
| | | .svg-icon {
|
| | | margin-right: 0;
|
| | | }
|
| | |
|
| | | .el-tooltip {
|
| | | padding: 0 !important;
|
| | | display: inline-flex !important;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | | width: 100%;
|
| | |
|
| | | .svg-icon {
|
| | | margin-left: 0;
|
| | | }
|
| | | }
|
| | |
|
| | | .el-menu-tooltip__trigger {
|
| | | width: 100%;
|
| | | display: inline-flex !important;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | |
|
| | | .svg-icon {
|
| | | width: 22px;
|
| | | height: 22px;
|
| | | margin-right: 0;
|
| | | flex-shrink: 0;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .el-sub-menu {
|
| | | overflow: hidden;
|
| | |
|
| | | & > .el-sub-menu__title {
|
| | | padding: 0 !important;
|
| | | display: flex !important;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | |
|
| | | .svg-icon {
|
| | | margin-left: 0;
|
| | | margin-right: 0;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .el-menu--collapse {
|
| | | width: 100% !important;
|
| | | padding: 12px 0 16px;
|
| | |
|
| | | > .el-menu-item,
|
| | | .el-sub-menu {
|
| | | & > .el-sub-menu__title,
|
| | | &.el-menu-item {
|
| | | width: calc(100% - 12px) !important;
|
| | | margin: 0 6px 8px !important;
|
| | | padding-left: 0 !important;
|
| | | padding-right: 0 !important;
|
| | | box-sizing: border-box;
|
| | | display: flex !important;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | |
|
| | | .svg-icon {
|
| | | width: 22px;
|
| | | height: 22px;
|
| | | margin-right: 0;
|
| | | flex-shrink: 0;
|
| | | }
|
| | |
|
| | | & > span {
|
| | | height: 0;
|
| | | width: 0;
|
| | | overflow: hidden;
|
| | | visibility: hidden;
|
| | | display: inline-block;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .el-menu--collapse .el-menu .el-sub-menu {
|
| | | min-width: var(--sidebar-width) !important;
|
| | | }
|
| | |
|
| | | .mobile {
|
| | | .main-container {
|
| | | margin-left: 0;
|
| | | }
|
| | |
|
| | | .sidebar-container {
|
| | | transition: transform 0.25s;
|
| | | width: var(--sidebar-width) !important;
|
| | | }
|
| | |
|
| | | &.hideSidebar {
|
| | | .sidebar-container {
|
| | | pointer-events: none;
|
| | | transition-duration: 0.3s;
|
| | | transform: translate3d(calc(-1 * var(--sidebar-width)), 0, 0);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .withoutAnimation {
|
| | | .main-container,
|
| | | .sidebar-container {
|
| | | transition: none;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .el-menu--vertical {
|
| | | & > .el-menu {
|
| | | .svg-icon {
|
| | | margin-right: 10px;
|
| | | }
|
| | | }
|
| | |
|
| | | .nest-menu .el-sub-menu > .el-sub-menu__title,
|
| | | .el-menu-item {
|
| | | min-width: 0 !important;
|
| | | margin: 0 10px 8px;
|
| | | width: calc(100% - 20px);
|
| | | height: 46px;
|
| | | line-height: 46px;
|
| | | padding-left: 12px !important;
|
| | | padding-right: 12px !important;
|
| | | box-sizing: border-box;
|
| | | border-radius: 12px;
|
| | | color: var(--sidebar-text);
|
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important;
|
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01));
|
| | | transition: all 0.24s ease;
|
| | |
|
| | | &:hover {
|
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important;
|
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important;
|
| | | transform: translateX(2px);
|
| | | }
|
| | |
|
| | | &.is-active {
|
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
|
| | | background-size: 180% 180%;
|
| | | color: #fff !important;
|
| | | border-radius: 12px;
|
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
|
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important;
|
| | | animation: sidebarActiveFlow 4.6s ease infinite;
|
| | | }
|
| | | }
|
| | |
|
| | | > .el-menu--popup {
|
| | | max-height: 100vh;
|
| | | overflow: hidden;
|
| | | padding: 10px;
|
| | | border-radius: 14px;
|
| | | position: relative;
|
| | | isolation: isolate;
|
| | | border: 1px solid rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.26);
|
| | | box-shadow:
|
| | | 0 18px 40px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16),
|
| | | var(--shadow-md);
|
| | | background: var(--sidebar-bg);
|
| | | backdrop-filter: blur(16px);
|
| | |
|
| | | &::before {
|
| | | content: "";
|
| | | position: absolute;
|
| | | inset: -28% -52% -18% -38%;
|
| | | z-index: 0;
|
| | | pointer-events: none;
|
| | | background:
|
| | | radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%),
|
| | | radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%),
|
| | | radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%),
|
| | | radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%),
|
| | | conic-gradient(
|
| | | from 210deg at 58% 38%,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg,
|
| | | rgba(56, 189, 248, 0.05) 76deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg,
|
| | | rgba(125, 211, 252, 0.04) 290deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg
|
| | | );
|
| | | filter: blur(7px) saturate(1.24) contrast(1.05);
|
| | | opacity: 0.96;
|
| | | transform: translate3d(0, 0, 0);
|
| | | transform-origin: 44% 58%;
|
| | | animation:
|
| | | sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite,
|
| | | sidebarAuroraBreath 9.7s ease-in-out infinite,
|
| | | sidebarAuroraSkew 6.9s steps(23, end) infinite;
|
| | | }
|
| | |
|
| | | &::after {
|
| | | content: "";
|
| | | position: absolute;
|
| | | inset: 0;
|
| | | z-index: 0;
|
| | | pointer-events: none;
|
| | | background:
|
| | | linear-gradient(
|
| | | 108deg,
|
| | | transparent 10%,
|
| | | rgba(255, 255, 255, 0.17) 34%,
|
| | | rgba(255, 255, 255, 0.04) 48%,
|
| | | transparent 72%
|
| | | ),
|
| | | linear-gradient(
|
| | | 202deg,
|
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%,
|
| | | transparent 34%,
|
| | | rgba(56, 189, 248, 0.18) 66%,
|
| | | transparent 100%
|
| | | ),
|
| | | radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%),
|
| | | radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%);
|
| | | background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%;
|
| | | background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%;
|
| | | opacity: 0.52;
|
| | | transform: translate3d(0, 0, 0);
|
| | | animation:
|
| | | sidebarSheenSweep 13.1s linear infinite,
|
| | | sidebarSheenJitter 4.7s steps(31, end) infinite;
|
| | | }
|
| | |
|
| | | > * {
|
| | | position: relative;
|
| | | z-index: 1;
|
| | | }
|
| | |
|
| | | > .el-menu {
|
| | | max-height: calc(100vh - 20px);
|
| | | overflow-y: auto;
|
| | | overflow-x: hidden;
|
| | |
|
| | | &::-webkit-scrollbar-track-piece {
|
| | | background: var(--surface-muted);
|
| | | }
|
| | |
|
| | | &::-webkit-scrollbar {
|
| | | width: 5px;
|
| | | }
|
| | |
|
| | | &::-webkit-scrollbar-thumb {
|
| | | background: var(--accent-light);
|
| | | border-radius: 10px;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarActiveFlow {
|
| | | 0% {
|
| | | background-position: 0% 50%;
|
| | | }
|
| | | 50% {
|
| | | background-position: 100% 50%;
|
| | | }
|
| | | 100% {
|
| | | background-position: 0% 50%;
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarAuroraDrift {
|
| | | 0% {
|
| | | transform: translate3d(-6.3%, -1.8%, 0) scale(1.05) rotate(-1.8deg);
|
| | | }
|
| | | 6% {
|
| | | transform: translate3d(2.2%, -4.6%, 0) scale(1.08) rotate(0.7deg);
|
| | | }
|
| | | 17% {
|
| | | transform: translate3d(-3.7%, 4.4%, 0) scale(1.11) rotate(2deg);
|
| | | }
|
| | | 27% {
|
| | | transform: translate3d(5.6%, 1.2%, 0) scale(1.03) rotate(-1deg);
|
| | | }
|
| | | 39% {
|
| | | transform: translate3d(-4.8%, -3.1%, 0) scale(1.09) rotate(1.5deg);
|
| | | }
|
| | | 52% {
|
| | | transform: translate3d(2.9%, 4.8%, 0) scale(1.04) rotate(-1.4deg);
|
| | | }
|
| | | 64% {
|
| | | transform: translate3d(-6.4%, 0.3%, 0) scale(1.08) rotate(0.5deg);
|
| | | }
|
| | | 73% {
|
| | | transform: translate3d(4.8%, -3.9%, 0) scale(1.05) rotate(1.6deg);
|
| | | }
|
| | | 81% {
|
| | | transform: translate3d(-2.4%, 2.9%, 0) scale(1.1) rotate(-0.8deg);
|
| | | }
|
| | | 92% {
|
| | | transform: translate3d(3.7%, -1.7%, 0) scale(1.06) rotate(-1.6deg);
|
| | | }
|
| | | 100% {
|
| | | transform: translate3d(-5.9%, 0.8%, 0) scale(1.08) rotate(1.2deg);
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarAuroraBreath {
|
| | | 0% {
|
| | | opacity: 0.76;
|
| | | filter: blur(5px) saturate(1.08);
|
| | | }
|
| | | 15% {
|
| | | opacity: 1;
|
| | | filter: blur(7px) saturate(1.28);
|
| | | }
|
| | | 37% {
|
| | | opacity: 0.84;
|
| | | filter: blur(8px) saturate(1.12);
|
| | | }
|
| | | 61% {
|
| | | opacity: 0.98;
|
| | | filter: blur(6px) saturate(1.24);
|
| | | }
|
| | | 83% {
|
| | | opacity: 0.86;
|
| | | filter: blur(7px) saturate(1.16);
|
| | | }
|
| | | 100% {
|
| | | opacity: 0.94;
|
| | | filter: blur(6px) saturate(1.2);
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarAuroraSkew {
|
| | | 0% {
|
| | | transform-origin: 44% 58%;
|
| | | }
|
| | | 21% {
|
| | | transform-origin: 62% 42%;
|
| | | }
|
| | | 43% {
|
| | | transform-origin: 31% 66%;
|
| | | }
|
| | | 66% {
|
| | | transform-origin: 68% 74%;
|
| | | }
|
| | | 100% {
|
| | | transform-origin: 39% 45%;
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarSheenSweep {
|
| | | 0% {
|
| | | background-position: 232% 0, 10% 18%, 80% 12%, 20% 82%;
|
| | | }
|
| | | 8% {
|
| | | background-position: 186% 0, 16% 30%, 74% 18%, 28% 74%;
|
| | | }
|
| | | 21% {
|
| | | background-position: 116% 0, 34% 10%, 62% 26%, 18% 64%;
|
| | | }
|
| | | 37% {
|
| | | background-position: 52% 0, 50% 24%, 46% 12%, 32% 58%;
|
| | | }
|
| | | 52% {
|
| | | background-position: -4% 0, 34% 54%, 22% 22%, 12% 46%;
|
| | | }
|
| | | 69% {
|
| | | background-position: -62% 0, 14% 36%, 32% 34%, 24% 56%;
|
| | | }
|
| | | 84% {
|
| | | background-position: -106% 0, 20% 20%, 46% 20%, 34% 70%;
|
| | | }
|
| | | 100% {
|
| | | background-position: -136% 0, 10% 18%, 80% 12%, 20% 82%;
|
| | | }
|
| | | }
|
| | |
|
| | | @keyframes sidebarSheenJitter {
|
| | | 0% {
|
| | | opacity: 0.28;
|
| | | transform: translate3d(0, 0, 0);
|
| | | }
|
| | | 17% {
|
| | | opacity: 0.56;
|
| | | transform: translate3d(1.8%, -0.5%, 0);
|
| | | }
|
| | | 38% {
|
| | | opacity: 0.34;
|
| | | transform: translate3d(-1.2%, 0.8%, 0);
|
| | | }
|
| | | 63% {
|
| | | opacity: 0.6;
|
| | | transform: translate3d(2.3%, -0.3%, 0);
|
| | | }
|
| | | 81% {
|
| | | opacity: 0.3;
|
| | | transform: translate3d(-1.6%, 0.7%, 0);
|
| | | }
|
| | | 100% {
|
| | | opacity: 0.52;
|
| | | transform: translate3d(2%, -0.1%, 0);
|
| | | }
|
| | | }
|
| | | #app { |
| | | .main-container { |
| | | min-height: 100vh; |
| | | margin-left: var(--sidebar-width); |
| | | transition: margin-left 0.25s ease; |
| | | position: relative; |
| | | background: transparent; |
| | | } |
| | | |
| | | .sidebarHide { |
| | | margin-left: 0 !important; |
| | | } |
| | | |
| | | .sidebar-container { |
| | | transition: width 0.25s ease; |
| | | width: var(--sidebar-width) !important; |
| | | height: 100vh; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | z-index: 1001; |
| | | overflow: hidden; |
| | | padding: 0; |
| | | font-size: 0; |
| | | background: var(--sidebar-bg); |
| | | border-right: 1px solid rgba(255, 255, 255, 0.08); |
| | | box-shadow: 8px 0 24px rgba(15, 23, 42, 0.08); |
| | | isolation: isolate; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | inset: -28% -52% -18% -38%; |
| | | z-index: 0; |
| | | pointer-events: none; |
| | | background: |
| | | radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%), |
| | | radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%), |
| | | radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%), |
| | | radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%), |
| | | conic-gradient( |
| | | from 210deg at 58% 38%, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg, |
| | | rgba(56, 189, 248, 0.05) 76deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg, |
| | | rgba(125, 211, 252, 0.04) 290deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg |
| | | ); |
| | | filter: blur(7px) saturate(1.24) contrast(1.05); |
| | | opacity: 0.96; |
| | | transform: translate3d(0, 0, 0); |
| | | transform-origin: 44% 58%; |
| | | animation: |
| | | sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite, |
| | | sidebarAuroraBreath 9.7s ease-in-out infinite, |
| | | sidebarAuroraSkew 6.9s steps(23, end) infinite; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | inset: 0; |
| | | z-index: 0; |
| | | pointer-events: none; |
| | | background: |
| | | linear-gradient( |
| | | 108deg, |
| | | transparent 10%, |
| | | rgba(255, 255, 255, 0.17) 34%, |
| | | rgba(255, 255, 255, 0.04) 48%, |
| | | transparent 72% |
| | | ), |
| | | linear-gradient( |
| | | 202deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%, |
| | | transparent 34%, |
| | | rgba(56, 189, 248, 0.18) 66%, |
| | | transparent 100% |
| | | ), |
| | | radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%), |
| | | radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%); |
| | | background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%; |
| | | background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%; |
| | | opacity: 0.52; |
| | | transform: translate3d(0, 0, 0); |
| | | animation: |
| | | sidebarSheenSweep 13.1s linear infinite, |
| | | sidebarSheenJitter 4.7s steps(31, end) infinite; |
| | | } |
| | | |
| | | > * { |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .horizontal-collapse-transition { |
| | | transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; |
| | | } |
| | | |
| | | .scrollbar-wrapper { |
| | | overflow-x: hidden !important; |
| | | overflow-y: auto !important; |
| | | } |
| | | |
| | | .el-scrollbar__bar.is-vertical { |
| | | right: 2px; |
| | | } |
| | | |
| | | .el-scrollbar { |
| | | height: 100%; |
| | | } |
| | | |
| | | &.has-logo { |
| | | .el-scrollbar { |
| | | height: calc(100% - 78px); |
| | | } |
| | | } |
| | | |
| | | .is-horizontal { |
| | | display: none; |
| | | } |
| | | |
| | | a { |
| | | display: inline-block; |
| | | width: 100%; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .el-menu { |
| | | border: none !important; |
| | | height: 100%; |
| | | width: 100% !important; |
| | | padding: 10px 0 16px; |
| | | border-radius: 0; |
| | | background: transparent !important; |
| | | box-shadow: none; |
| | | backdrop-filter: none; |
| | | } |
| | | |
| | | .el-menu-item, |
| | | .el-sub-menu__title, |
| | | .menu-title { |
| | | overflow: hidden !important; |
| | | text-overflow: ellipsis !important; |
| | | white-space: nowrap !important; |
| | | } |
| | | |
| | | .el-menu-item .el-menu-tooltip__trigger { |
| | | display: inline-flex !important; |
| | | width: 100%; |
| | | align-items: center; |
| | | } |
| | | |
| | | .submenu-title-noDropdown, |
| | | .el-sub-menu__title, |
| | | .el-menu-item { |
| | | min-width: 0 !important; |
| | | width: calc(100% - 24px) !important; |
| | | margin: 0 12px 8px !important; |
| | | height: 50px; |
| | | line-height: 50px; |
| | | border-radius: 14px; |
| | | padding-left: 16px !important; |
| | | padding-right: 36px !important; |
| | | box-sizing: border-box; |
| | | transition: all 0.28s ease; |
| | | color: var(--sidebar-text); |
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01)); |
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important; |
| | | position: relative; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .submenu-title-noDropdown::after, |
| | | .el-sub-menu__title::after, |
| | | .el-menu-item::after { |
| | | content: ""; |
| | | position: absolute; |
| | | inset: 0; |
| | | background: linear-gradient(115deg, transparent 12%, rgba(255, 255, 255, 0.16), transparent 78%); |
| | | transform: translateX(-100%); |
| | | opacity: 0; |
| | | transition: transform 0.45s ease, opacity 0.26s ease; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .submenu-title-noDropdown:hover, |
| | | .el-sub-menu__title:hover, |
| | | .el-menu-item:hover { |
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.28), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.08)) !important; |
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.32) !important; |
| | | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 8px 18px rgba(8, 36, 76, 0.24); |
| | | transform: translateX(3px); |
| | | } |
| | | |
| | | .submenu-title-noDropdown:hover::after, |
| | | .el-sub-menu__title:hover::after, |
| | | .el-menu-item:hover::after, |
| | | .el-menu-item.is-active::after, |
| | | .el-sub-menu.is-active > .el-sub-menu__title::after { |
| | | transform: translateX(100%); |
| | | opacity: 1; |
| | | } |
| | | |
| | | & .theme-light .is-active > .el-sub-menu__title, |
| | | & .theme-dark .is-active > .el-sub-menu__title, |
| | | & .el-menu-item.is-active { |
| | | color: #fff !important; |
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important; |
| | | background-size: 180% 180%; |
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34)); |
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important; |
| | | animation: sidebarActiveFlow 4.6s ease infinite; |
| | | } |
| | | |
| | | & .nest-menu .el-sub-menu > .el-sub-menu__title, |
| | | & .el-sub-menu .el-menu-item { |
| | | min-width: 0 !important; |
| | | width: calc(100% - 32px) !important; |
| | | margin: 0 16px 6px !important; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | padding-left: 12px !important; |
| | | padding-right: 12px !important; |
| | | border-radius: 8px; |
| | | transition: all 0.24s ease; |
| | | color: var(--sidebar-text); |
| | | border: none !important; |
| | | background: transparent; |
| | | font-size: 13px; |
| | | |
| | | &:hover { |
| | | background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.12) !important; |
| | | transform: translateX(4px); |
| | | } |
| | | |
| | | &.is-active { |
| | | background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.85) !important; |
| | | color: #fff !important; |
| | | font-weight: 500; |
| | | box-shadow: 0 4px 12px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.25); |
| | | } |
| | | } |
| | | |
| | | // 子菜单容器样式 - 增加缩进和视觉层次 |
| | | & .el-sub-menu .el-menu { |
| | | padding: 4px 0 8px; |
| | | margin-left: 8px; |
| | | border-left: 2px solid rgba(255, 255, 255, 0.08); |
| | | } |
| | | } |
| | | |
| | | .hideSidebar { |
| | | .sidebar-container { |
| | | width: var(--sidebar-collapsed-width) !important; |
| | | } |
| | | |
| | | .main-container { |
| | | margin-left: var(--sidebar-collapsed-width); |
| | | } |
| | | |
| | | .submenu-title-noDropdown { |
| | | padding: 0 !important; |
| | | position: relative; |
| | | display: flex !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .svg-icon { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .el-tooltip { |
| | | padding: 0 !important; |
| | | display: inline-flex !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | |
| | | .svg-icon { |
| | | margin-left: 0; |
| | | } |
| | | } |
| | | |
| | | .el-menu-tooltip__trigger { |
| | | width: 100%; |
| | | display: inline-flex !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .svg-icon { |
| | | width: 22px; |
| | | height: 22px; |
| | | margin-right: 0; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-sub-menu { |
| | | overflow: hidden; |
| | | |
| | | & > .el-sub-menu__title { |
| | | padding: 0 !important; |
| | | display: flex !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .svg-icon { |
| | | margin-left: 0; |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-menu--collapse { |
| | | width: 100% !important; |
| | | padding: 12px 0 16px; |
| | | |
| | | > .el-menu-item, |
| | | .el-sub-menu { |
| | | & > .el-sub-menu__title, |
| | | &.el-menu-item { |
| | | width: calc(100% - 12px) !important; |
| | | margin: 0 6px 8px !important; |
| | | padding-left: 0 !important; |
| | | padding-right: 0 !important; |
| | | box-sizing: border-box; |
| | | display: flex !important; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .svg-icon { |
| | | width: 22px; |
| | | height: 22px; |
| | | margin-right: 0; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | & > span { |
| | | height: 0; |
| | | width: 0; |
| | | overflow: hidden; |
| | | visibility: hidden; |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-menu--collapse .el-menu .el-sub-menu { |
| | | min-width: var(--sidebar-width) !important; |
| | | } |
| | | |
| | | .mobile { |
| | | .main-container { |
| | | margin-left: 0; |
| | | } |
| | | |
| | | .sidebar-container { |
| | | transition: transform 0.25s; |
| | | width: var(--sidebar-width) !important; |
| | | } |
| | | |
| | | &.hideSidebar { |
| | | .sidebar-container { |
| | | pointer-events: none; |
| | | transition-duration: 0.3s; |
| | | transform: translate3d(calc(-1 * var(--sidebar-width)), 0, 0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .withoutAnimation { |
| | | .main-container, |
| | | .sidebar-container { |
| | | transition: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-menu--vertical { |
| | | & > .el-menu { |
| | | .svg-icon { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | |
| | | .nest-menu .el-sub-menu > .el-sub-menu__title, |
| | | .el-menu-item { |
| | | min-width: 0 !important; |
| | | margin: 0 10px 8px; |
| | | width: calc(100% - 20px); |
| | | height: 46px; |
| | | line-height: 46px; |
| | | padding-left: 12px !important; |
| | | padding-right: 12px !important; |
| | | box-sizing: border-box; |
| | | border-radius: 12px; |
| | | color: var(--sidebar-text); |
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important; |
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01)); |
| | | transition: all 0.24s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important; |
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important; |
| | | transform: translateX(2px); |
| | | } |
| | | |
| | | &.is-active { |
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important; |
| | | background-size: 180% 180%; |
| | | color: #fff !important; |
| | | border-radius: 12px; |
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34)); |
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important; |
| | | animation: sidebarActiveFlow 4.6s ease infinite; |
| | | } |
| | | } |
| | | |
| | | > .el-menu--popup { |
| | | max-height: 100vh; |
| | | overflow: hidden; |
| | | padding: 10px; |
| | | border-radius: 14px; |
| | | position: relative; |
| | | isolation: isolate; |
| | | border: 1px solid rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.26); |
| | | box-shadow: |
| | | 0 18px 40px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16), |
| | | var(--shadow-md); |
| | | background: var(--sidebar-bg); |
| | | backdrop-filter: blur(16px); |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | inset: -28% -52% -18% -38%; |
| | | z-index: 0; |
| | | pointer-events: none; |
| | | background: |
| | | radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%), |
| | | radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%), |
| | | radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%), |
| | | radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%), |
| | | conic-gradient( |
| | | from 210deg at 58% 38%, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg, |
| | | rgba(56, 189, 248, 0.05) 76deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg, |
| | | rgba(125, 211, 252, 0.04) 290deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg |
| | | ); |
| | | filter: blur(7px) saturate(1.24) contrast(1.05); |
| | | opacity: 0.96; |
| | | transform: translate3d(0, 0, 0); |
| | | transform-origin: 44% 58%; |
| | | animation: |
| | | sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite, |
| | | sidebarAuroraBreath 9.7s ease-in-out infinite, |
| | | sidebarAuroraSkew 6.9s steps(23, end) infinite; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | inset: 0; |
| | | z-index: 0; |
| | | pointer-events: none; |
| | | background: |
| | | linear-gradient( |
| | | 108deg, |
| | | transparent 10%, |
| | | rgba(255, 255, 255, 0.17) 34%, |
| | | rgba(255, 255, 255, 0.04) 48%, |
| | | transparent 72% |
| | | ), |
| | | linear-gradient( |
| | | 202deg, |
| | | rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%, |
| | | transparent 34%, |
| | | rgba(56, 189, 248, 0.18) 66%, |
| | | transparent 100% |
| | | ), |
| | | radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%), |
| | | radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%); |
| | | background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%; |
| | | background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%; |
| | | opacity: 0.52; |
| | | transform: translate3d(0, 0, 0); |
| | | animation: |
| | | sidebarSheenSweep 13.1s linear infinite, |
| | | sidebarSheenJitter 4.7s steps(31, end) infinite; |
| | | } |
| | | |
| | | > * { |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | > .el-menu { |
| | | max-height: calc(100vh - 20px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | |
| | | &::-webkit-scrollbar-track-piece { |
| | | background: var(--surface-muted); |
| | | } |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 5px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: var(--accent-light); |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarActiveFlow { |
| | | 0% { |
| | | background-position: 0% 50%; |
| | | } |
| | | 50% { |
| | | background-position: 100% 50%; |
| | | } |
| | | 100% { |
| | | background-position: 0% 50%; |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarAuroraDrift { |
| | | 0% { |
| | | transform: translate3d(-6.3%, -1.8%, 0) scale(1.05) rotate(-1.8deg); |
| | | } |
| | | 6% { |
| | | transform: translate3d(2.2%, -4.6%, 0) scale(1.08) rotate(0.7deg); |
| | | } |
| | | 17% { |
| | | transform: translate3d(-3.7%, 4.4%, 0) scale(1.11) rotate(2deg); |
| | | } |
| | | 27% { |
| | | transform: translate3d(5.6%, 1.2%, 0) scale(1.03) rotate(-1deg); |
| | | } |
| | | 39% { |
| | | transform: translate3d(-4.8%, -3.1%, 0) scale(1.09) rotate(1.5deg); |
| | | } |
| | | 52% { |
| | | transform: translate3d(2.9%, 4.8%, 0) scale(1.04) rotate(-1.4deg); |
| | | } |
| | | 64% { |
| | | transform: translate3d(-6.4%, 0.3%, 0) scale(1.08) rotate(0.5deg); |
| | | } |
| | | 73% { |
| | | transform: translate3d(4.8%, -3.9%, 0) scale(1.05) rotate(1.6deg); |
| | | } |
| | | 81% { |
| | | transform: translate3d(-2.4%, 2.9%, 0) scale(1.1) rotate(-0.8deg); |
| | | } |
| | | 92% { |
| | | transform: translate3d(3.7%, -1.7%, 0) scale(1.06) rotate(-1.6deg); |
| | | } |
| | | 100% { |
| | | transform: translate3d(-5.9%, 0.8%, 0) scale(1.08) rotate(1.2deg); |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarAuroraBreath { |
| | | 0% { |
| | | opacity: 0.76; |
| | | filter: blur(5px) saturate(1.08); |
| | | } |
| | | 15% { |
| | | opacity: 1; |
| | | filter: blur(7px) saturate(1.28); |
| | | } |
| | | 37% { |
| | | opacity: 0.84; |
| | | filter: blur(8px) saturate(1.12); |
| | | } |
| | | 61% { |
| | | opacity: 0.98; |
| | | filter: blur(6px) saturate(1.24); |
| | | } |
| | | 83% { |
| | | opacity: 0.86; |
| | | filter: blur(7px) saturate(1.16); |
| | | } |
| | | 100% { |
| | | opacity: 0.94; |
| | | filter: blur(6px) saturate(1.2); |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarAuroraSkew { |
| | | 0% { |
| | | transform-origin: 44% 58%; |
| | | } |
| | | 21% { |
| | | transform-origin: 62% 42%; |
| | | } |
| | | 43% { |
| | | transform-origin: 31% 66%; |
| | | } |
| | | 66% { |
| | | transform-origin: 68% 74%; |
| | | } |
| | | 100% { |
| | | transform-origin: 39% 45%; |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarSheenSweep { |
| | | 0% { |
| | | background-position: 232% 0, 10% 18%, 80% 12%, 20% 82%; |
| | | } |
| | | 8% { |
| | | background-position: 186% 0, 16% 30%, 74% 18%, 28% 74%; |
| | | } |
| | | 21% { |
| | | background-position: 116% 0, 34% 10%, 62% 26%, 18% 64%; |
| | | } |
| | | 37% { |
| | | background-position: 52% 0, 50% 24%, 46% 12%, 32% 58%; |
| | | } |
| | | 52% { |
| | | background-position: -4% 0, 34% 54%, 22% 22%, 12% 46%; |
| | | } |
| | | 69% { |
| | | background-position: -62% 0, 14% 36%, 32% 34%, 24% 56%; |
| | | } |
| | | 84% { |
| | | background-position: -106% 0, 20% 20%, 46% 20%, 34% 70%; |
| | | } |
| | | 100% { |
| | | background-position: -136% 0, 10% 18%, 80% 12%, 20% 82%; |
| | | } |
| | | } |
| | | |
| | | @keyframes sidebarSheenJitter { |
| | | 0% { |
| | | opacity: 0.28; |
| | | transform: translate3d(0, 0, 0); |
| | | } |
| | | 17% { |
| | | opacity: 0.56; |
| | | transform: translate3d(1.8%, -0.5%, 0); |
| | | } |
| | | 38% { |
| | | opacity: 0.34; |
| | | transform: translate3d(-1.2%, 0.8%, 0); |
| | | } |
| | | 63% { |
| | | opacity: 0.6; |
| | | transform: translate3d(2.3%, -0.3%, 0); |
| | | } |
| | | 81% { |
| | | opacity: 0.3; |
| | | transform: translate3d(-1.6%, 0.7%, 0); |
| | | } |
| | | 100% { |
| | | opacity: 0.52; |
| | | transform: translate3d(2%, -0.1%, 0); |
| | | } |
| | | } |
| | |
| | | </script>
|
| | |
|
| | | <style lang="scss" scoped>
|
| | | .sidebar-item-wrapper { |
| | | :deep(.menu-icon) { |
| | | width: 26px; |
| | | height: 26px; |
| | | margin-right: 12px; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-shrink: 0; |
| | | transition: color 0.2s ease; |
| | | color: var(--sidebar-text); |
| | | opacity: 0.88; |
| | | } |
| | | |
| | | :deep(.el-menu-item:hover .menu-icon), |
| | | :deep(.el-sub-menu__title:hover .menu-icon) { |
| | | color: #ffffff; |
| | | opacity: 1; |
| | | } |
| | | .sidebar-item-wrapper {
|
| | | :deep(.menu-icon) {
|
| | | width: 26px;
|
| | | height: 26px;
|
| | | margin-right: 12px;
|
| | | display: inline-flex;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | | flex-shrink: 0;
|
| | | transition: color 0.2s ease;
|
| | | color: var(--sidebar-text);
|
| | | opacity: 0.88;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item:hover .menu-icon),
|
| | | :deep(.el-sub-menu__title:hover .menu-icon) {
|
| | | color: #ffffff;
|
| | | opacity: 1;
|
| | | }
|
| | |
|
| | | :deep(.el-menu-item.is-active .menu-icon) {
|
| | | color: var(--menu-active-text) !important;
|
| | | opacity: 1;
|
| | | }
|
| | |
|
| | | :deep(.menu-title) { |
| | | font-weight: 500; |
| | | transition: color 0.2s ease; |
| | | color: var(--sidebar-text); |
| | | opacity: 0.82; |
| | | } |
| | | |
| | | :deep(.el-menu-item:hover .menu-title), |
| | | :deep(.el-sub-menu__title:hover .menu-title) { |
| | | color: #ffffff; |
| | | opacity: 1; |
| | | } |
| | | |
| | | :deep(.el-menu-item.is-active .menu-title) { |
| | | color: var(--menu-active-text) !important; |
| | | opacity: 1; |
| | | } |
| | | |
| | | :deep(.nest-menu) { |
| | | .menu-icon { |
| | | width: 22px; |
| | | height: 22px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .menu-title { font-size: 13px; } |
| | | } |
| | | } |
| | | :deep(.menu-title) {
|
| | | font-weight: 500;
|
| | | transition: color 0.2s ease;
|
| | | color: var(--sidebar-text);
|
| | | opacity: 0.82;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item:hover .menu-title),
|
| | | :deep(.el-sub-menu__title:hover .menu-title) {
|
| | | color: #ffffff;
|
| | | opacity: 1;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item.is-active .menu-title) {
|
| | | color: var(--menu-active-text) !important;
|
| | | opacity: 1;
|
| | | }
|
| | | |
| | | :deep(.nest-menu) {
|
| | | .menu-icon {
|
| | | width: 18px;
|
| | | height: 18px;
|
| | | margin-right: 8px;
|
| | | opacity: 0.7;
|
| | | }
|
| | | |
| | | .menu-title { |
| | | font-size: 13px;
|
| | | opacity: 0.85;
|
| | | }
|
| | | |
| | | .el-menu-item.is-active {
|
| | | .menu-icon {
|
| | | opacity: 1;
|
| | | }
|
| | | .menu-title {
|
| | | opacity: 1;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | </style>
|
| | |
| | | </el-form-item> --> |
| | | <el-form-item label="创建时间" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="formData.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive } from "vue"; |
| | | import { onMounted, ref, reactive, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | parameterListPage, |
| | | addParameter, |
| | |
| | | }, |
| | | }, |
| | | ], |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | // const productTypes = ref([]); |
| | | const isEdit = ref(false); |
| | |
| | | formData.unit = ""; |
| | | formData.remark = ""; |
| | | formData.isRequired = 0; |
| | | formData.createTime = new Date().toISOString().split("T")[0]; |
| | | formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | formData.remark = row.remark || ""; |
| | | formData.paramFormat = row.paramFormat || ""; |
| | | formData.isRequired = row.isRequired || 0; |
| | | formData.createTime = row.createTime || ""; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <!-- 用印申请管理 --> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" class="mb-20 "> |
| | |
| | | :isShowPagination="true" |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 用印申请对话框 --> |
| | |
| | | const sealFormRef = ref() |
| | | const userList = ref([]) |
| | | const sealForm = reactive({ |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | |
| | | |
| | | // 用印申请表格列配置(需在 getStatusText/getSealTypeText 等之后定义) |
| | | const sealTableColumn = ref([ |
| | | { label: '申请编号', prop: 'applicationNum',}, |
| | | { label: '申请编号', prop: 'applicationNum' }, |
| | | { label: '申请标题', prop: 'title', showOverflowTooltip: true }, |
| | | { label: '申请人', prop: 'createUserName', }, |
| | | { label: '申请人', prop: 'createUserName' }, |
| | | { label: '所属部门', prop: 'department', width: 150 }, |
| | | { |
| | | label: '用印类型', |
| | |
| | | formatData: (v) => getStatusText(v), |
| | | formatType: (v) => getStatusType(v) |
| | | }, |
| | | { label: '审批人', prop: 'approveUserName', width: 100 }, |
| | | { |
| | | dataType: 'action', |
| | | label: '操作', |
| | | width: 200, |
| | | width: 250, |
| | | fixed: 'right', |
| | | align: 'center', |
| | | operation: [ |
| | | { |
| | | name: '审批', |
| | | clickFun: (row) => approveSeal(row), |
| | | showHide: (row) => row.status === 'pending' |
| | | showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId |
| | | }, |
| | | { |
| | | name: '拒绝', |
| | | clickFun: (row) => rejectSeal(row), |
| | | showHide: (row) => row.status === 'pending' |
| | | showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId |
| | | }, |
| | | { name: '详情', clickFun: (row) => viewSealDetail(row) } |
| | | { |
| | | name: '重新申请', |
| | | clickFun: (row) => reapplySeal(row), |
| | | showHide: (row) => row.status === 'rejected' && Number(userStore.id) === row.createUser |
| | | }, |
| | | { name: '详情', clickFun: (row) => viewSealDetail(row) } |
| | | ] |
| | | } |
| | | ]) |
| | | |
| | | // 搜索印章申请 |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | page.current = 1 |
| | | getSealApplicationList() |
| | | |
| | | // ElMessage.success('搜索完成') |
| | | } |
| | | // 重置印章申请搜索 |
| | | const resetSealSearch = () => { |
| | |
| | | sealSearchForm.applicationNum = '' |
| | | searchSealApplications() |
| | | } |
| | | |
| | | // 重新申请用印 |
| | | const reapplySeal = (row) => { |
| | | // 预填表单数据 |
| | | Object.assign(sealForm, { |
| | | id: row.id, |
| | | applicationNum: row.applicationNum, |
| | | title: row.title, |
| | | sealType: row.sealType, |
| | | reason: row.reason, |
| | | approveUserId: row.approveUserId, |
| | | urgency: row.urgency || 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: row.storageBlobVOList || [] |
| | | }) |
| | | showSealApplyDialog.value = true |
| | | } |
| | | |
| | | // 提交用印申请 |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('申请提交成功') |
| | | const request = sealForm.id ? updateSealApplication : addSealApplication |
| | | request(sealForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success(sealForm.id ? '重新申请成功' : '申请提交成功') |
| | | closeSealApplyDialog() |
| | | getSealApplicationList() |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | approveUserId: '', |
| | | urgency: 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: [] |
| | | }) |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | approveUserId: '', |
| | | urgency: 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: [] |
| | | }) |
| | | } |
| | | }).catch(err => { |
| | | console.log(err.msg) |
| | | }) |
| | | |
| | | } catch (error) { |
| | | } |
| | | } |
| | | |
| | | // 关闭用印申请对话框 |
| | | const closeSealApplyDialog = () => { |
| | | // 清空表单数据 |
| | | Object.assign(sealForm, { |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | if (res.code == 200) { |
| | | ElMessage.success('审批通过') |
| | | getSealApplicationList() |
| | | } |
| | |
| | | inputErrorMessage: '拒绝原因不能为空' |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | row.reason = value |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | if (res.code == 200) { |
| | | ElMessage.success('已拒绝申请') |
| | | getSealApplicationList() |
| | | } |
| | |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | listSealApplication(page, sealSearchForm) |
| | | .then(res => { |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | tableLoading.value = false |
| | | }).catch(err => { |
| | | tableLoading.value = false |
| | | }) |
| | | .then(res => { |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | tableLoading.value = false |
| | | }).catch(err => { |
| | | tableLoading.value = false |
| | | }) |
| | | } |
| | | // 分页变化处理 |
| | | const paginationChange = (obj) => { |
| | |
| | | .attachment-table { |
| | | border-radius: 4px; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker v-model="form.createTime" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | <el-date-picker v-model="createTimeDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | |
| | | |
| | | const form = reactive({ |
| | | ...createDefaultForm(), |
| | | }); |
| | | const createTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | dialogTitle.value = "新增固定资产"; |
| | | Object.assign(form, createDefaultForm(), { |
| | | purchaseDate: new Date().toISOString().split('T')[0], |
| | | createTime: new Date().toISOString().split('T')[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker v-model="form.createTime" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | <el-date-picker v-model="createTimeDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | |
| | | |
| | | const form = reactive({ |
| | | ...createDefaultForm(), |
| | | }); |
| | | const createTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | dialogTitle.value = "新增无形资产"; |
| | | Object.assign(form, createDefaultForm(), { |
| | | acquisitionDate: new Date().toISOString().split('T')[0], |
| | | createTime: new Date().toISOString().split('T')[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="form.createTime" |
| | | v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="paymentForm.createTime" |
| | | v-model="paymentFormCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { getOptions } from "@/api/procurementManagement/procurementLedger.js"; |
| | |
| | | inboundBatches: "", |
| | | status: 0, |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const paymentFormCreateTimeDate = computed({ |
| | | get: () => (paymentForm.createTime ? String(paymentForm.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | paymentForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | remark: form.remark || "", |
| | | status: 0, |
| | | paymentAmount: form.paymentAmount, |
| | | createTime: form.createTime, |
| | | }; |
| | | if (forUpdate) { |
| | | payload.id = currentId.value; |
| | |
| | | stockInRecordIds: [], |
| | | inboundBatches: "", |
| | | status: 0, |
| | | createTime: new Date().toISOString().split("T")[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | inboundBatchList.value = []; |
| | | inboundBatchOptions.value = []; |
| | |
| | | bankAccount: row.bankAccountNum ?? row.bankAccount ?? "", |
| | | bankName: row.bankAccountName ?? row.bankName ?? "", |
| | | remark: "", |
| | | createTime: new Date().toISOString().split("T")[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | paymentDialogVisible.value = true; |
| | | nextTick(() => { |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="form.createTime" |
| | | v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance, defineAsyncComponent } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { listCustomer } from "@/api/basicData/customer.js"; |
| | |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | | customerId: [{ required: true, message: "请选择客户", trigger: "change" }], |
| | |
| | | status: normalizeStatus(row.status ?? row.auditStatus), |
| | | outboundBatchNos, |
| | | outboundBatches: formatOutboundBatches(row.outboundBatches), |
| | | createTime: row.createTime ?? "", |
| | | }); |
| | | }; |
| | | |
| | |
| | | applyDate: new Date().toISOString().split("T")[0], |
| | | content: "", |
| | | remark: "", |
| | | createTime: new Date().toISOString().split("T")[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | outboundBatchList.value = []; |
| | | outboundBatchOptions.value = []; |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="form.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | nextTick, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { listCustomer } from "@/api/basicData/customer.js"; |
| | |
| | | outboundBatches: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | stockOutRecordIds, |
| | | outboundBatches: formatOutboundBatches(row.outboundBatches), |
| | | remark: row.remark ?? "", |
| | | createTime: row.createTime ?? "", |
| | | }); |
| | | }; |
| | | |
| | |
| | | stockOutRecordIds: [], |
| | | outboundBatches: "", |
| | | remark: "", |
| | | createTime: new Date().toISOString().split("T")[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | outboundBatchList.value = []; |
| | | outboundBatchOptions.value = []; |
| | |
| | | currentNodeIndex: 0, |
| | | approvalRecords, |
| | | rejectReason: approvalRecords.find(r => r.result === "rejected")?.opinion || "", |
| | | purchaseContractNumber: row.purchaseContractNumber || "", |
| | | quotationNo: row.quotationNo || "", |
| | | shippingNo: row.shippingNo || "", |
| | | }; |
| | | } |
| | | |
| | |
| | | </div> |
| | | <div class="detail-block"> |
| | | <div class="detail-block-title">填报内容</div> |
| | | <FormPayloadFields :fields="formResolved.fields" |
| | | <!-- 默认表单展示 --> |
| | | <FormPayloadFields v-if="!isSpecialApprovalType" |
| | | :fields="formResolved.fields" |
| | | :form-payload="formResolved.formPayload" |
| | | readonly /> |
| | | |
| | | <!-- 发货审批详情 --> |
| | | <template v-else-if="row.businessType === 7"> |
| | | <div v-if="detailData.shippingInfo" class="shipment-detail"> |
| | | <el-divider content-position="left">发货详情</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="销售订单">{{ detailData.shippingInfo.salesContractNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货订单号">{{ detailData.shippingInfo.shippingNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="客户名称">{{ detailData.shippingInfo.customerName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货类型">{{ detailData.shippingInfo.type || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货日期">{{ detailData.shippingInfo.shippingDateDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="审核状态">{{ detailData.shippingInfo.status || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="发货车牌号">{{ detailData.shippingInfo.shippingCarNumber || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="快递公司">{{ detailData.shippingInfo.expressCompany || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="快递单号" :span="2">{{ detailData.shippingInfo.expressNumber || "--" }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.shippingProductDetailDtoList.length" style="margin-top: 20px;"> |
| | | <h4>产品明细</h4> |
| | | <el-table :data="detailData.shippingProductDetailDtoList" |
| | | border |
| | | size="small" |
| | | style="width: 100%"> |
| | | <el-table-column label="批号" prop="batchNo" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="产品名称" prop="productName" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="规格型号" prop="specificationModel" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="发货数量" prop="deliveryQuantity" min-width="120" align="center" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 采购审批详情 --> |
| | | <template v-else-if="row.businessType === 5"> |
| | | <div v-if="detailData" class="procurement-detail"> |
| | | <el-divider content-position="left">采购详情</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="采购合同号">{{ detailData.purchaseContractNumber || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="供应商名称">{{ detailData.supplierName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="项目名称">{{ detailData.projectName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="销售合同号">{{ detailData.salesContractNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="签订日期">{{ detailData.executionDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="录入日期">{{ detailData.entryDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="付款方式">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="合同金额" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(detailData.contractAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.productData.length" style="margin-top: 20px;"> |
| | | <h4>产品明细</h4> |
| | | <el-table :data="detailData.productData" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="productCategory" label="产品名称" /> |
| | | <el-table-column prop="specificationModel" label="规格型号" /> |
| | | <el-table-column prop="unit" label="单位" /> |
| | | <el-table-column prop="quantity" label="数量" /> |
| | | <el-table-column prop="taxInclusiveUnitPrice" label="含税单价"> |
| | | <template #default="scope">¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="taxInclusiveTotalPrice" label="含税总价"> |
| | | <template #default="scope">¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 报价审批详情 --> |
| | | <template v-else-if="row.businessType === 6"> |
| | | <div v-if="detailData" class="quotation-detail"> |
| | | <el-divider content-position="left">报价详情</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="报价单号">{{ detailData.quotationNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="客户名称">{{ detailData.customer || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="业务员">{{ detailData.salesperson || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="报价日期">{{ detailData.quotationDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="有效期至">{{ detailData.validDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="付款方式">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="报价总额" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(detailData.totalAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.products.length" style="margin-top: 20px;"> |
| | | <h4>产品明细</h4> |
| | | <el-table :data="detailData.products" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="product" label="产品名称" /> |
| | | <el-table-column prop="specification" label="规格型号" /> |
| | | <el-table-column prop="unit" label="单位" /> |
| | | <el-table-column prop="unitPrice" label="单价"> |
| | | <template #default="scope">¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <div v-if="detailData.remark" style="margin-top: 20px;"> |
| | | <h4>备注</h4> |
| | | <p>{{ detailData.remark }}</p> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <div v-if="attachmentList.length" |
| | | class="detail-block"> |
| | |
| | | |
| | | const props = defineProps({ |
| | | row: { type: Object, default: () => ({}) }, |
| | | detailData: { type: Object, default: () => ({}) }, |
| | | }); |
| | | |
| | | const formResolved = computed(() => resolveInstanceFormFields(props.row)); |
| | | |
| | | |
| | | // 是否为特殊审批类型(采购、发货、报价) |
| | | const isSpecialApprovalType = computed(() => { |
| | | return [5, 7, 6].includes(props.row.businessType); |
| | | }); |
| | | |
| | | // 详情数据(直接使用传入的 detail-data 参数) |
| | | const detailData = computed(() => { |
| | | return props.detailData || {}; |
| | | }); |
| | | |
| | | const attachmentList = computed(() => { |
| | | const list = props.row.storageBlobVOList || props.row.storageBlobDTOs || []; |
| | |
| | | align-items: center; |
| | | flex-shrink: 0; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | class="approve-detail-dialog" |
| | | > |
| | | <div class="approve-detail-body"> |
| | | <ApproveDetailPanel :row="detailRow" /> |
| | | <ApproveDetailPanel :row="detailRow" :detail-data="detailData" /> |
| | | <div class="detail-block"> |
| | | <div class="detail-block-title"> |
| | | 审批流程({{ detailRow.tasks?.length || detailRow.flowNodes?.length || 0 }} 项) |
| | |
| | | destroy-on-close |
| | | @closed="approveOpinion = ''" |
| | | > |
| | | <ApproveDetailPanel :row="approveDialog.row" /> |
| | | <ApproveDetailPanel :row="approveDialog.row" :detail-data="detailData" /> |
| | | <div class="detail-block mt16"> |
| | | <div class="detail-block-title"> |
| | | 审批流程({{ approveDialog.row?.tasks?.length || approveDialog.row?.flowNodes?.length || 0 }} 项) |
| | |
| | | tableColumn, |
| | | detailDialog, |
| | | detailRow, |
| | | detailData, |
| | | reimburseDialog, |
| | | approveDialog, |
| | | approveOpinion, |
| | |
| | | border-left: 3px solid var(--el-color-primary); |
| | | line-height: 1.4; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | saveApprovalInstance, |
| | | updateApprovalInstance, |
| | | } from "@/api/officeProcessAutomation/approvalInstance.js"; |
| | | import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; |
| | | import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getDeliveryDetailByShippingNo } from "@/api/salesManagement/deliveryLedger.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | |
| | | |
| | | const detailDialog = reactive({ visible: false }); |
| | | const detailRow = ref({}); |
| | | const detailData = ref({}); |
| | | |
| | | const approveDialog = reactive({ visible: false, row: null }); |
| | | const approveOpinion = ref(""); |
| | |
| | | })); |
| | | |
| | | const tableColumn = ref([ |
| | | { label: "申请人编号", prop: "applicantNo", width: 110 }, |
| | | // { label: "申请人编号", prop: "applicantNo", width: 110 }, |
| | | { label: "申请人名称", prop: "applicantName", minWidth: 100 }, |
| | | { label: "模板类型", prop: "businessName", minWidth: 120 }, |
| | | { |
| | |
| | | fetchBusinessTypeOptions(), |
| | | listApprovalTemplate(TEMPLATE_TYPE_CUSTOM), |
| | | ]); |
| | | submitBusinessTypeOptions.value = typeOptions; |
| | | submitBusinessTypeOptions.value = typeOptions.filter((x) => ![5, 6, 7].includes(x.value)); |
| | | allSubmitTemplates.value = unwrapTemplateList(customRes) |
| | | .filter((row) => mapEnabledFromApi(row.enabled)) |
| | | .map(mapSubmitTemplateCard); |
| | |
| | | await openReimburseDetail(row, "detail"); |
| | | return; |
| | | } |
| | | |
| | | detailRow.value = { ...row }; |
| | | // 报价审批:用审批事由字段承载的"报价单号"去查报价列表 |
| | | if (row.businessType === 6) { |
| | | const quotationNo = row?.quotationNo; |
| | | if (quotationNo) { |
| | | const res = await getQuotationList({ quotationNo }); |
| | | const records = res?.data?.records || []; |
| | | detailData.value = records[0] || {}; |
| | | } |
| | | } |
| | | |
| | | // 采购审批:用审批事由字段承载的"采购合同号"去查采购详情 |
| | | else if (row.businessType === 5) { |
| | | const purchaseContractNumber = row?.purchaseContractNumber; |
| | | if (purchaseContractNumber) { |
| | | const res = await getPurchaseByCode({ purchaseContractNumber }); |
| | | detailData.value = res || {}; |
| | | } |
| | | } |
| | | |
| | | // 发货审批:用审批事由字段承载的"发货单号"去查发货详情 |
| | | else if (row.businessType === 7) { |
| | | const shippingNo = row?.shippingNo; |
| | | if (shippingNo) { |
| | | const res = await getDeliveryDetailByShippingNo({ shippingNo }); |
| | | detailData.value = res?.data || res || {}; |
| | | } |
| | | } |
| | | |
| | | // 其他审批类型 |
| | | else { |
| | | detailData.value = {}; |
| | | } |
| | | |
| | | detailDialog.visible = true; |
| | | } |
| | | |
| | | async function openApprove(row) { |
| | | |
| | | if (inferReimburseModuleKeyFromInstance(row)) { |
| | | approveOpinion.value = ""; |
| | | await openReimburseDetail(row, "approve"); |
| | |
| | | } |
| | | approveDialog.row = { ...row }; |
| | | approveOpinion.value = ""; |
| | | // 报价审批:用审批事由字段承载的"报价单号"去查报价列表 |
| | | if (row.businessType === 6) { |
| | | const quotationNo = row?.quotationNo; |
| | | if (quotationNo) { |
| | | const res = await getQuotationList({ quotationNo }); |
| | | const records = res?.data?.records || []; |
| | | detailData.value = records[0] || {}; |
| | | } |
| | | } |
| | | |
| | | // 采购审批:用审批事由字段承载的"采购合同号"去查采购详情 |
| | | else if (row.businessType === 5) { |
| | | const purchaseContractNumber = row?.purchaseContractNumber; |
| | | if (purchaseContractNumber) { |
| | | const res = await getPurchaseByCode({ purchaseContractNumber }); |
| | | detailData.value = res || {}; |
| | | } |
| | | } |
| | | |
| | | // 发货审批:用审批事由字段承载的"发货单号"去查发货详情 |
| | | else if (row.businessType === 7) { |
| | | const shippingNo = row?.shippingNo; |
| | | if (shippingNo) { |
| | | const res = await getDeliveryDetailByShippingNo({ shippingNo }); |
| | | detailData.value = res?.data || res || {}; |
| | | } |
| | | } |
| | | |
| | | // 其他审批类型 |
| | | else { |
| | | detailData.value = {}; |
| | | } |
| | | approveDialog.visible = true; |
| | | } |
| | | |
| | |
| | | tableColumn, |
| | | detailDialog, |
| | | detailRow, |
| | | detailData, |
| | | reimburseDialog, |
| | | approveDialog, |
| | | approveOpinion, |
| | |
| | | selectedRows, |
| | | batchDelete, |
| | | }; |
| | | } |
| | | } |
| | |
| | | |
| | | <template v-if="detailAttachments.length"> |
| | | |
| | | <el-tag |
| | | |
| | | v-for="(f, i) in detailAttachments" |
| | | |
| | | :key="i" |
| | | |
| | | class="detail-attachment-tag" |
| | | |
| | | type="info" |
| | | |
| | | effect="plain" |
| | | |
| | | > |
| | | |
| | | {{ attachmentDisplayName(f) }} |
| | | |
| | | </el-tag> |
| | | <div class="detail-attachment-list"> |
| | | <div |
| | | v-for="(f, i) in detailAttachments" |
| | | :key="i" |
| | | class="detail-attachment-item" |
| | | @click="openAttachmentFile(f)" |
| | | > |
| | | <el-icon class="attachment-icon"><Document /></el-icon> |
| | | <span class="attachment-name">{{ attachmentDisplayName(f) }}</span> |
| | | <el-icon class="attachment-download"><Download /></el-icon> |
| | | </div> |
| | | </div> |
| | | |
| | | </template> |
| | | |
| | |
| | | |
| | | <script setup> |
| | | |
| | | import { ArrowRight, Plus, RefreshRight } from "@element-plus/icons-vue"; |
| | | import { ArrowRight, Document, Download, Plus, RefreshRight } from "@element-plus/icons-vue"; |
| | | |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | function openAttachmentFile(file) { |
| | | const url = file?.url || file?.previewURL || file?.downloadURL || file?.previewUrl || ""; |
| | | if (url) { |
| | | window.open(url, "_blank"); |
| | | } else { |
| | | ElMessage.warning("无法打开该附件"); |
| | | } |
| | | } |
| | | |
| | | |
| | | function unwrapArray(payload) { |
| | |
| | | |
| | | } |
| | | |
| | | .detail-attachment-tag { |
| | | .detail-attachment-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | margin: 0 8px 8px 0; |
| | | .detail-attachment-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: var(--el-fill-color-light); |
| | | border-radius: 6px; |
| | | cursor: pointer; |
| | | transition: background 0.2s; |
| | | } |
| | | |
| | | .detail-attachment-item:hover { |
| | | background: var(--el-fill-color); |
| | | } |
| | | |
| | | .attachment-icon { |
| | | font-size: 16px; |
| | | color: var(--el-text-color-regular); |
| | | } |
| | | |
| | | .attachment-name { |
| | | font-size: 14px; |
| | | color: var(--el-text-color-primary); |
| | | } |
| | | |
| | | .attachment-download { |
| | | font-size: 14px; |
| | | color: var(--el-text-color-secondary); |
| | | } |
| | | |
| | | .text-muted { |
| | |
| | | }); |
| | | } |
| | | |
| | | function openFormDialog(mode, row) { |
| | | async function openFormDialog(mode, row) { |
| | | formDialog.mode = mode; |
| | | formDialog.title = mode === "add" ? "新建审批模板" : "编辑审批模板"; |
| | | resetForm(mode === "edit" ? row : null); |
| | | if (mode === "edit" && row?.id) { |
| | | // 编辑时先查询详情获取完整数据(包含附件) |
| | | try { |
| | | const res = await getApprovalTemplateDetail(row.id); |
| | | const detailData = mapTemplateFromApi(unwrapTemplateDetail(res)); |
| | | resetForm(detailData); |
| | | } catch { |
| | | resetForm(row); |
| | | } |
| | | } else { |
| | | resetForm(mode === "edit" ? row : null); |
| | | } |
| | | formDialog.visible = true; |
| | | } |
| | | |
| | |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="success" |
| | | plain |
| | | @click="handleBatchGenerate">批量生成数据</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增台账</el-button> |
| | | <el-button type="primary" |
| | |
| | | prop="specificationModel" /> |
| | | <el-table-column label="单位" |
| | | prop="unit" /> |
| | | <el-table-column label="入库审核状态" |
| | | <el-table-column label="入库审核状态" |
| | | prop="stockInApprovalStatus" |
| | | width="120"> |
| | | <template #default="scope"> |
| | |
| | | getOptions, |
| | | getPurchaseTemplateList, |
| | | delPurchaseTemplate, |
| | | batchGeneratePurchaseInboundSteps, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | const FileList = defineAsyncComponent(() => |
| | |
| | | // 获取入库状态标签类型 |
| | | const getStockInStatusType = status => { |
| | | const typeMap = { |
| | | "待入库": "info", // 待入库 - 灰色 |
| | | "入库中": "warning", // 入库中 - 橙色 |
| | | "完全入库": "success", // 完全入库 - 绿色 |
| | | 待入库: "info", // 待入库 - 灰色 |
| | | 入库中: "warning", // 入库中 - 橙色 |
| | | 完全入库: "success", // 完全入库 - 绿色 |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | |
| | | // 获取入库审核状态标签类型 |
| | | const getStockInApprovalStatusType = status => { |
| | | const typeMap = { |
| | | "待入库": "info", // 待入库 - 灰色 |
| | | "入库中": "warning", // 入库中 - 橙色 |
| | | "完全入库": "success", // 完全入库 - 绿色 |
| | | 待入库: "info", // 待入库 - 灰色 |
| | | 入库中: "warning", // 入库中 - 橙色 |
| | | 完全入库: "success", // 完全入库 - 绿色 |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | |
| | | const openForm = async (type, row) => { |
| | | // 编辑时检查入库状态,完全入库时不能编辑 |
| | | if (type === "edit" && row) { |
| | | if (row.stockInStatus === '完全入库') { |
| | | if (row.stockInStatus === "完全入库") { |
| | | proxy.$modal.msgWarning("完全入库状态的记录不能编辑"); |
| | | return; |
| | | } |
| | |
| | | form.value = { ...purchaseRes, stockInStatus: row.stockInStatus }; |
| | | fileList.value = purchaseRes.storageBlobVOS || []; |
| | | // 使用 productList 接口获取产品列表,以获取入库审核状态 |
| | | const productRes = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const productRes = await productList({ |
| | | salesLedgerId: row.id, |
| | | type: 2, |
| | | }); |
| | | productData.value = productRes.data || []; |
| | | } catch (error) { |
| | | console.error("加载采购台账数据失败:", error); |
| | |
| | | // 打开产品弹框 |
| | | const openProductForm = async (type, row, index) => { |
| | | // 编辑时检查产品入库审核状态,完全入库时不能编辑 |
| | | if (type === "edit" && row && row.stockInApprovalStatus === '完全入库') { |
| | | if (type === "edit" && row && row.stockInApprovalStatus === "完全入库") { |
| | | proxy.$modal.msgWarning("完全入库状态的产品不能编辑"); |
| | | return; |
| | | } |
| | |
| | | } |
| | | // 检查选中的产品中是否有完全入库的 |
| | | const hasFullyStocked = productSelectedRows.value.some( |
| | | row => row.stockInApprovalStatus === '完全入库' |
| | | row => row.stockInApprovalStatus === "完全入库" |
| | | ); |
| | | if (hasFullyStocked) { |
| | | proxy.$modal.msgWarning("选中的产品中包含完全入库的产品,无法删除"); |
| | |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | |
| | | const handleBatchGenerate = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | |
| | | ElMessageBox.confirm("确认批量生成数据?", "批量生成", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "info", |
| | | }) |
| | | .then(() => { |
| | | proxy.$modal.loading("正在批量生成数据,请稍候..."); |
| | | batchGeneratePurchaseInboundSteps({ ids }) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("批量生成成功"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("批量生成失败"); |
| | | }) |
| | | .finally(() => { |
| | | proxy.$modal.closeLoading(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | |
| | | contractNo: form.value.salesLedgerId, |
| | | }); |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | productData.value = data || []; |
| | | } |
| | | }; |
| | | |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker v-model="formData.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ref, reactive, onMounted, getCurrentInstance, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Search, Refresh, Plus, Download } from "@element-plus/icons-vue"; |
| | | import { |
| | |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false, |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | // 当前激活的标签页 |
| | |
| | | const handleAdd = () => { |
| | | dialogType.value = "add"; |
| | | resetForm(); |
| | | formData.createTime = new Date().toISOString().split("T")[0]; |
| | | formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间"> |
| | | <el-date-picker v-model="formData.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive } from 'vue' |
| | | import { ref, reactive, computed } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| | | const loading = ref(false) |
| | |
| | | supplierName: '', |
| | | remark: '', |
| | | createTime: '' |
| | | }) |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : '' |
| | | } |
| | | }) |
| | | |
| | | const mockData = [ |
| | |
| | | const openDialog = (type, row = {}) => { |
| | | dialogType.value = type |
| | | if (type === 'edit' && row.id) { |
| | | Object.assign(formData, { supplierName: row.supplierName, remark: row.remark }) |
| | | Object.assign(formData, { supplierName: row.supplierName, remark: row.remark, createTime: row.createTime || '' }) |
| | | } else { |
| | | Object.assign(formData, { supplierName: '', remark: '', createTime: new Date().toISOString().split('T')[0] }) |
| | | Object.assign(formData, { supplierName: '', remark: '', createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') }) |
| | | } |
| | | dialogVisible.value = true |
| | | } |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="创建时间"> |
| | | <el-date-picker v-model="formData.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive } from 'vue' |
| | | import { ref, reactive, computed } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| | | const loading = ref(false) |
| | |
| | | inspector: '', |
| | | remark: '', |
| | | createTime: '' |
| | | }) |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : '' |
| | | } |
| | | }) |
| | | |
| | | const mockData = [ |
| | |
| | | arrivalNo: row.arrivalNo, |
| | | supplierName: row.supplierName, |
| | | inspector: row.inspector, |
| | | remark: row.remark |
| | | remark: row.remark, |
| | | createTime: row.createTime || '' |
| | | }) |
| | | } else { |
| | | Object.assign(formData, { |
| | |
| | | products: [], |
| | | inspector: '', |
| | | remark: '', |
| | | createTime: new Date().toISOString().split('T')[0] |
| | | createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') |
| | | }) |
| | | } |
| | | dialogVisible.value = true |
| | |
| | | <span>{{ currentProduct.identifierType }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间"> |
| | | <el-date-picker v-model="createTime" |
| | | <el-date-picker v-model="createTimeDate" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Search, Loading, Download } from "@element-plus/icons-vue"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | |
| | | const generateQuantity = ref(1); |
| | | const codeRule = ref(""); |
| | | const customPrefix = ref(""); |
| | | const createTime = ref(new Date().toISOString().split('T')[0]); |
| | | const createTime = ref(dayjs().format("YYYY-MM-DD HH:mm:ss")); |
| | | const createTimeDate = computed({ |
| | | get: () => (createTime.value ? String(createTime.value).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | createTime.value = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const newBatchNo = ref(""); |
| | | const reassignReason = ref(""); |
| | | const formRef = ref(); |
| | |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间"> |
| | | <el-date-picker v-model="mergeForm.createTime" |
| | | <el-date-picker v-model="mergeCreateTimeDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="form.createTime" |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | |
| | | Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); |
| | | mergeForm.planCompleteTime = row.requiredDate || ""; |
| | | mergeForm.productId = row.productId || ""; |
| | | mergeForm.createTime = new Date().toISOString().split("T")[0]; |
| | | mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | mergeForm.ids = [row.id]; |
| | | sumAssignedQuantity.value = |
| | | Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); |
| | |
| | | productId: "", |
| | | createTime: "", |
| | | }); |
| | | const mergeCreateTimeDate = computed({ |
| | | get: () => (mergeForm.createTime ? String(mergeForm.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | mergeForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | // 导入相关 |
| | | const importDialogRef = ref(null); |
| | |
| | | promisedDeliveryDate: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const rules = reactive({ |
| | | productId: [{ required: true, message: "请选择产品", trigger: "change" }], |
| | |
| | | mergeForm.totalAssignedQuantity = totalAssignedQuantity; |
| | | mergeForm.planCompleteTime = firstRow.requiredDate || ""; |
| | | mergeForm.productId = firstRow.productId || ""; |
| | | mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | mergeForm.ids = selectedRows.value.map(row => row.id); |
| | | |
| | | // 打开弹窗 |
| | |
| | | requiredDate: "", |
| | | promisedDeliveryDate: "", |
| | | remark: "", |
| | | createTime: new Date().toISOString().split("T")[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | |
| | | requiredDate: row.requiredDate || "", |
| | | promisedDeliveryDate: row.promisedDeliveryDate || "", |
| | | remark: row.remark || "", |
| | | createTime: row.createTime || "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | |
| | | <el-form-item label="创建时间" |
| | | prop="createTime"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.createTime" |
| | | v-model="formCreateTimeDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {}, |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.value.createTime ? String(form.value.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.value.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const { |
| | |
| | | trainingMode: "", // 培训方式 |
| | | placeTraining: "", // 培训地点 |
| | | classHour: "", // 课时 |
| | | createTime: new Date().toISOString().split("T")[0], // 创建时间 |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 创建时间 |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "编辑培训"; |
| | |
| | | trainingMode: row.trainingMode, // 培训方式 |
| | | placeTraining: row.placeTraining, // 培训地点 |
| | | classHour: row.classHour, // 课时 |
| | | createTime: row.createTime || "", // 创建时间 |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="审批中数量" width="120" align="center"> |
| | | <template #default="scope"> |
| | | <span>{{ scope.row.pendingApprovalQuantity || 0 }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="快递公司" |
| | | prop="expressCompany" |
| | |
| | | // 签订日期默认为当天 |
| | | form.value.executionDate = getCurrentDate(); |
| | | // 创建时间默认为当天 |
| | | form.value.createTime = getCurrentDate(); |
| | | form.value.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | // 默认自动生成销售合同号 |
| | | form.value.autoGenerateContractNo = true; |
| | | } else { |
| | |
| | | }; |
| | | |
| | | // 打印功能 |
| | | const handlePrint = async () => { |
| | | const handlePrint = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("请选择要打印的数据"); |
| | | return; |
| | |
| | | // 格式化日期 |
| | | const formatDate = (dateString) => { |
| | | if (!dateString) return getCurrentDate(); |
| | | const date = new Date(dateString); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}/${month}/${day}`; |
| | | return dayjs(dateString).format("YYYY/MM/DD HH:mm:ss"); |
| | | }; |
| | | // 格式化日期时间 |
| | | const formatDateTime = (date) => { |
| | |
| | | |
| | | /** |
| | | * 判断是否可以发货 |
| | | * 只有在产品状态是充足,发货状态是待发货和审核拒绝的时候才可以发货 |
| | | * 只有在产品状态是充足,发货状态是待发货、审批中、审核拒绝、部分发货的时候才可以发货 |
| | | * @param row 行数据 |
| | | */ |
| | | const canShip = (row) => { |
| | |
| | | // 获取发货状态 |
| | | const shippingStatus = row.shippingStatus; |
| | | |
| | | // 如果已发货(有发货日期或车牌号),不能再次发货 |
| | | // 如果已发货,不能再次发货 |
| | | if (shippingStatus === "已发货") { |
| | | return false; |
| | | } |
| | | |
| | | // 发货状态必须是"待发货"或"审核拒绝" |
| | | // 发货状态必须是"待发货"、"审批中"、"审核拒绝"或"部分发货" |
| | | const statusStr = shippingStatus ? String(shippingStatus).trim() : ""; |
| | | return ( |
| | | statusStr === "待发货" || |
| | | statusStr === "审批中" || |
| | | statusStr === "审核拒绝" || |
| | | statusStr === "部分发货" |
| | | ); |
| | |
| | | // 检查是否可以发货 |
| | | if (!canShip(row)) { |
| | | proxy.$modal.msgWarning( |
| | | "只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货" |
| | | "只有在产品状态是充足,发货状态是待发货、审批中、审核拒绝或部分发货的时候才可以发货" |
| | | ); |
| | | return; |
| | | } |
| | |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |