Commit 92e8663c by zhuzhequan

工厂端仓库

parent e7c1f32e
......@@ -9,8 +9,10 @@ declare module 'vue' {
export interface GlobalComponents {
CommonCard: typeof import('./src/components/CommonCard.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
......@@ -24,7 +26,9 @@ declare module 'vue' {
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
......
import axios from '@/api/axios.ts'
import { BasePaginationData, BaseRespData } from '@/types/api'
export interface factoryWarehouseInfo{
pageSize:number
currentPage:number
total?:number
}
export interface UpdateDefaulted{
id?: number;
defaulted: number;
}
export interface warehouseInfo{
id?: number;
name: string;
code: string;
sort: string;
defaulted: number;
factoryId?: number;
factoryCode?: string;
remarks: string
}
interface WarehouseWarningData {
id: number;
factoryId: number;
warehouseId: number;
warehouseName: string;
warehouseLocationId: number;
locationName: string;
warehouseSku: string;
skuName: string;
unit: string;
occupyInventory: number;
freezeInventory: number;
inventory: number;
upperLimit: number;
floorLimit: number;
productNumber: string;
itemSort: number;
dataVersion: number;
status: number;
createTime: string;
updateTime: string;
}
export function getFactoryWarehouseInfo(data: factoryWarehouseInfo) {
return axios.post<never, BasePaginationData<warehouseInfo>>(
'factoryWarehouseInfo/list_page',
data,
)
}
export function createWarehouseApi(data:warehouseInfo) {
return axios.post<never, BaseRespData<never>>(
'/factoryWarehouseInfo/add',
data
)
}
export function createWarehouseInventoryApi(data:WarehouseWarningData) {
return axios.post<never, BaseRespData<never>>(
'/factoryWarehouseInventory/add',
data
)
}
export function updateWarehouseApi(data:warehouseInfo | UpdateDefaulted) {
return axios.post<never, BaseRespData<never>>(
'/factoryWarehouseInfo/update',
data
)
}
export function updateWarehouseInventoryApi(data:WarehouseWarningData) {
return axios.post<never, BaseRespData<never>>(
'/factoryWarehouseInventory/update',
data
)
}
export function deleteWarehouseApi(ids:string) {
return axios.get<never, BaseRespData<never>>(
'/factoryWarehouseInfo/delete',
{
params:{ids}
},
)
}
export function deleteWarehouseInventory(ids:string) {
return axios.get<never, BaseRespData<never>>(
'/factoryWarehouseInventory/delete',
{
params:{ids}
},
)
}
......@@ -16,11 +16,13 @@ import { getToken } from '@/api/axios'
import UserPage from '@/views/UserPage.vue'
import DeliveryNotePage from '@/views/DeliveryNotePage.vue'
import AccountStatementNote from '@/views/AccountStatementNote.vue'
import Product from '@/views/product/index.vue'
import PodBillOrder from '@/views/podBillOrder/index.vue'
import TypeseetingManagement from '@/views/typesetting/TypesettingManagement.vue'
import PodOrderList from '@/views/order/pod/index.vue'
import PodDeliveryNoteList from '@/views/order/pod/deliveryOrderList.vue'
import WarehouseManage from '@/views/warehouse/manage.vue'
import WarehouseWarning from '@/views/warehouse/warning.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
......@@ -35,6 +37,12 @@ const router = createRouter({
title: '概览',
},
component: Dashboard,
},{
path: '/product',
meta: {
title: '商品',
},
component: Product,
},
{
path: '/order/list',
......@@ -97,6 +105,18 @@ const router = createRouter({
title: '打版管理',
},
component: TypeseetingManagement,
},{
path: '/warehouse/manage',
meta: {
title: '仓库管理',
},
component: WarehouseManage,
},{
path: '/warehouse/warning',
meta: {
title: '仓库预警',
},
component: WarehouseWarning,
},
],
},
......
......@@ -12,6 +12,43 @@ const menu: MenuItem[] = [
label: '概览',
},
{
index: '/product',
id: 11,
label: '商品',
},
{
index: '13',
id: 13,
label: '库存',
children: [
{
index: '/warehouse/manage',
id: 121,
label: '仓库管理',
},
{
index: '/order/list',
id: 122,
label: '库位管理',
},
{
index: '/pod-order/list',
id: 123,
label: '入库单',
},
{
index: '/pod-order/list',
id: 124,
label: '出库单',
},
{
index: '/warehouse/warning',
id: 125,
label: '仓库预警',
},
],
},
{
index: '1',
id: 2,
label: '订单',
......@@ -93,6 +130,6 @@ const menu: MenuItem[] = [
// }
// ]
// },
]
]
export default menu
<template>
<div class="h100">
<div class="wraper" @mouseout="closeShow">
<div class="image-box" :title="data.name">
<el-image
style="width: 100%; height: 100%"
:src="imageUrl"
fit="cover"
/>
<div
v-if="isShowHomeSku === 'bottom'"
class="app-btn-bottom"
style="width: 100%"
>
<transition>
<div
class="more_wrap"
style="max-width: 100%; overflow-x: auto; overflow-y: hidden"
>
<slot name="operations" />
</div>
</transition>
</div>
</div>
<div class="content">
<div class="colors_main">
<div class="colors_wrap">
<ul class="colors">
<li v-for="(val, index) in data.colorImageList" :key="index">
<img
style="display: block"
width="30"
loading="lazy"
height="30"
:src="val"
alt=""
@mouseenter.stop="setCurrentImg(val)"
/>
</li>
</ul>
</div>
</div>
<!-- <slot name="skuid" v-if="$slots.skuid"></slot> -->
<slot name="content">
<div
style="
display: flex;
align-items: center;
position: relative;
/* height: 24px; */
"
>
<slot name="product-name"></slot>
<slot name="price" />
<slot name="synthesizeStatus"></slot>
<slot name="level-time"></slot>
</div>
</slot>
<slot name="otherContent"></slot>
</div>
<slot name="extra" />
</div>
</div>
</template>
<script lang="ts" setup>
import {computed} from 'vue'
const props = defineProps({
// 控制一些元素显示与否
isStore: {
type: Boolean,
},
width: {
type: Number,
default: 300,
},
hasWidth: {
type: Boolean,
default: false,
},
isFormat: {
type: Boolean,
default: false,
},
smallWidth: {
type: Number,
default: 45,
},
isShowTag: {
type: Boolean,
default: false,
},
isShowHomeSku: {
type: [String, Boolean],
validator: (v) => v === "top" || v === "bottom" || !v,
},
isSkuImageList: {
type: Boolean,
},
isShowSkuId: {
type: Boolean,
default: true,
},
isShowTitle: {
type: Boolean,
default: false,
},
isShowLevel: {
type: Boolean,
default: true,
},
isShowStatus: {
type: Boolean,
default: true,
},
isShowSku: {
type: Boolean,
default: true,
},
isShowSales: {
type: Boolean,
default: true,
},
showSelectable: {
type: Boolean,
default: true,
},
openly: {
type: Number,
default: 1,
},
showOpenly: {
type: Boolean,
default: false,
},
proportion: {
type: Number,
default: 125,
},
data: {
type: Object,
default: () => ({ colorImageList: [] }),
},
selectIds: {
type: Array,
default: () => [],
},
activeFn: {
type: Function,
default: () => {},
},
index: {
type: Number,
default: null,
},
searchForm: {
type: Object,
default: () => {},
},
operational: {
type: Boolean,
default: true,
},
customTagList: {
type: Array,
default: () => [],
},
isCustom: {
type: Boolean,
default: () => false,
},
});
const emits = defineEmits(["setCurrentImg"]);
const imageUrl = computed(() => {
return props.data.img_url;
});
const setCurrentImg = (val: string) => {
if (!val) return;
emits("setCurrentImg", val);
};
const closeShow = () => {
if (!props.data.colorImageList.length) return;
emits("setCurrentImg", props.data.colorImageList[0]);
};
// edit(item) {
// this.$emit('showEdit', item)
// }
</script>
<style lang="scss" scoped>
.wraper {
position: relative;
border-radius: 12px 0px 0px 0px;
border: 1px solid #efefef;
background: #eeeeee;
overflow: hidden;
}
.wraper:hover {
border: 1px solid #4168ff;
}
.addtag {
display: none;
}
.wraper:hover .addtag {
display: block;
}
.sales_wrap {
padding-top: 5px;
height: 24px;
display: flex;
align-items: center;
}
.sales_wrap svg {
margin-bottom: 5px;
}
.sales {
flex: 1;
height: 24px;
margin-left: 5px;
line-height: 24px;
box-sizing: border-box;
background-position: left center;
background-size: contain;
background-repeat: no-repeat;
display: inline-block;
font-size: 14px;
vertical-align: bottom;
padding-top: 1px;
font-weight: bold;
text-align: center;
}
.high {
color: red;
font-weight: bold;
color: #444444;
background: linear-gradient(0deg, rgb(255, 255, 255) 0%, #dddddd 100%);
border-radius: 4px 4px 0 0;
position: relative;
}
.high::before {
position: absolute;
top: -11px;
right: 0;
left: 0;
text-align: center;
line-height: 20px;
font-size: 12px;
font-weight: normal;
}
.today.high::before {
content: "today";
}
.seven.high::before {
content: "seven";
}
.thirty.high::before {
content: "thirty";
}
.history.high::before {
content: "history";
}
.active-icon {
position: relative;
display: block;
width: 16px;
height: 16px;
border: 1px solid #cccccc;
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.4) inset;
border-radius: 8px;
background: #fff;
}
.active-icon.active {
background: #4168ff;
position: relative;
border-color: #4168ff;
box-shadow: none;
font-size: 18px;
top: -1px;
left: -1px;
}
.active-icon.active::after {
position: absolute;
content: "";
top: 0px;
left: 4px;
width: 4px;
height: 8px;
border-width: 2px;
border-style: solid;
border-color: transparent #fff #fff transparent;
transform: rotate(45deg) scale(0.8);
}
.colors_main {
height: 40px;
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.colors_wrap {
height: 40px;
flex: 1;
overflow-x: auto;
overflow-y: hidden;
}
.colors {
white-space: nowrap;
display: flex;
}
.colors_wrap::-webkit-scrollbar {
height: 5px;
width: 5px;
}
.colors li {
border-right: 1px solid #fff;
width: 30px;
min-width: 30px;
height: 30px;
background: #ddd;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
margin-right: 5px;
border-radius: 5px;
overflow: hidden;
border: 1px solid #ddd;
box-sizing: border-box;
}
.colors li img {
object-fit: contain;
object-position: center;
}
.star {
display: inline-block;
width: 80px;
color: red;
padding-left: 2px;
}
.star span {
display: inline-block;
height: 14px;
width: 14px;
margin-right: 2px;
background-position: center;
background-size: contain;
// background-image: url('../../assets/icon/star-no.svg');
}
// .star span.active {
// background-image: url('../../assets/icon/star.svg');
// }
// .moneyall {
// background-image: url('../../assets/images/moneyall.png');
// }
// .moneyone {
// background-image: url('../../assets/images/moneyone.png');
// }
// .rmb {
// background-image: url('../../assets/images/rmb.png');
// }
.version {
display: block;
width: 18px;
height: 18px;
line-height: 14px;
font-size: 12px;
color: #fff;
padding: 0 0 3px 2px;
text-align: center;
box-sizing: border-box;
// background: no-repeat url('../../assets/images/supply/no-version.png');
}
.repeat {
display: inline-block;
height: 24px;
width: 24px;
border-radius: 12px;
font-size: 12px;
background: red;
line-height: 22px;
color: #fff;
text-align: center;
}
// .version.main {
// background-image: url('../../assets/images/supply/version.png');
// }
// .dollar {
// background-image: url('../../assets/images/supply/money.png');
// }
// .eidt_title {
// background-image: url('../../assets/images/edit001.png');
// }
// .edit_online {
// background-image: url('../../assets/images/plane.png');
// }
.scroll {
overflow: auto;
padding-top: 10px;
user-select: none;
border: 1px solid #ddd;
}
.empty.elements {
border: none;
}
.select-number {
position: absolute;
left: 5px;
top: 10px;
}
.left_mark {
position: absolute;
top: 5px;
left: 5px;
}
.right_check {
position: absolute;
top: 5px;
right: 5px;
display: flex;
}
.right_check > * {
display: block;
margin-bottom: 5px;
}
.app-btn-top {
position: relative;
height: 30px;
}
.app-btn-top > .more_wrap {
position: absolute;
right: 5px;
}
.image-box {
position: relative;
padding-top: 100%;
width: 100%;
.el-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.app-btn-bottom {
position: absolute;
bottom: 5px;
left: 0;
}
}
.log_btn {
height: 22px;
display: inline-block;
background: #ffffff;
margin-right: 5px;
padding: 0 8px;
font-size: 12px;
vertical-align: middle;
box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.2);
border-radius: 13px;
text-align: center;
cursor: pointer;
}
.edit {
vertical-align: middle;
}
.content {
padding: 5px 10px;
background: linear-gradient(
90deg,
rgba(228, 228, 228, 0.4) 0%,
rgba(255, 255, 255, 1) 100%
);
}
.wraper:hover .content {
background: linear-gradient(
90deg,
rgba(26, 125, 255, 0.404) 0%,
rgba(64, 158, 255, 0) 100%
);
}
.footer_wrap {
display: flex;
align-items: center;
padding: 5px 0px 0;
}
.more_wrap {
display: none;
height: 35px;
/* //display: flex; */
align-items: center;
}
.wraper:hover .more_wrap {
display: flex;
}
.more_wrap :deep(> img) {
margin-left: 6px;
cursor: pointer;
}
.more_wrap :deep(> img:hover) {
transform: scale(1.3);
}
.price {
color: rgba(181, 124, 91, 1);
font-size: 14px;
font-weight: bold;
}
.new {
display: block;
width: 43px;
height: 16px;
line-height: 14px;
background: #8fc31f;
text-align: center;
border-radius: 8px;
font-size: 12px;
font-family: Alibaba PuHuiTi;
font-weight: 400;
color: #ffffff;
}
.bottom-home-sku {
cursor: pointer;
display: flex;
align-items: center;
padding: 2px 5px 2px 0;
background: rgba(255, 255, 255, 0.5);
border-radius: 5px;
margin-right: 6px;
position: relative;
z-index: 1;
}
.bottom-home-sku span,
.top-home-sku span {
font-size: 14px;
vertical-align: top;
margin-left: 5px;
color: #222;
}
.more_wrap :deep(> .delete:hover),
.more_wrap :deep(> .download:hover) {
transform: scale(1.3);
}
.delete,
.download {
display: inline-block;
width: 20px;
height: 20px;
background: rgba(255, 0, 0, 0.678);
padding: 0 4px;
border-radius: 10px;
box-sizing: border-box;
}
.delete svg,
.download svg {
margin-top: -1px;
width: 12px;
height: 12px;
}
.product {
right: 66px;
background: #4168ff;
color: #ffffff;
padding: 0 8px 8px 8px;
border-radius: 18px;
}
.variants {
display: flex;
padding: 5px 0;
}
.variants + .variants {
border-top: 1px solid #ddd;
}
.variants .title {
width: 120px;
min-width: 110px;
color: #303133;
font-size: 14px;
font-weight: bold;
line-height: 20px;
}
.variants li {
display: inline-block;
position: relative;
width: 96px;
padding: 0 6px;
margin-left: 6px;
box-sizing: border-box;
border: 1px solid #dcdfe6;
background: #fff;
border-radius: 4px;
overflow: hidden;
white-space: nowrap;
font-weight: 500;
font-size: 12px;
line-height: 24px;
color: #606266;
cursor: pointer;
text-overflow: ellipsis;
padding-right: 10px;
}
.variants li.active {
border: 1px solid blue;
}
.variants li i {
position: absolute;
top: 7px;
right: 5px;
}
.value {
display: inline-block;
width: 150px;
text-align: left;
color: #000;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.wraper:hover .store::after {
display: none;
}
.img_footer_cont {
position: absolute;
display: none;
right: 0;
bottom: 0;
left: 0;
padding-top: 50px;
background-image: linear-gradient(
to top,
rgba(255, 255, 255, 0.9),
rgba(255, 255, 255, 0)
);
}
.img_footer_cont .title {
min-height: 24px;
line-height: 24px;
font-size: 12px;
color: #222;
padding: 5px 8px 0;
}
.wraper:hover .img_footer_cont {
display: block;
}
.top-home-sku {
position: absolute;
bottom: 5px;
left: 5px;
z-index: 888;
display: flex;
align-items: center;
padding: 2px 5px;
background: hsla(0, 0%, 100%, 0.5);
border-radius: 5px;
}
.top-home-sku > span {
width: auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
}
.openly {
top: 5px;
z-index: 3;
right: 5px;
position: absolute;
}
</style>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import cardWrapper from './cardWrapper.vue'
const queryParams = reactive({
name: "",
sku: "",
diy_sku: "",
print_type: "",
category_id: "",
});
const pager = reactive({
page:1,
size:100,
loading: false ,
count: 0,
lists: [] ,
extend: {}
})
const setCurrentImg = (item: any, val: string) => {
item.img_url = val;
};
const categoryTree = ref([])
const resetPage = () => {
}
</script>
<template>
<div class="product">
<el-card>
<el-form
ref="formRef"
class="searchForm"
label-width="80px"
:model="queryParams"
:inline="true"
>
<el-form-item label="商品名称">
<el-input
v-model="queryParams.name"
clearable
maxlength="40"
style="width: 150px"
show-word-limit
placeholder="请输入商品名称"
/>
</el-form-item>
<el-form-item label="SKU">
<el-input
v-model="queryParams.sku"
clearable
style="width: 150px"
placeholder="请输入sku"
/>
</el-form-item>
<el-form-item label="印花类型">
<el-select
v-model="queryParams.print_type"
style="width: 150px"
clearable
placeholder="请选择"
>
<el-option
v-for="(item, index) in ['满印', '局部印']"
:key="index"
:label="item"
:value="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="商品分类">
<el-cascader
ref="categoryCascader"
v-model="queryParams.category_id"
:options="categoryTree"
clearable
style="width: 150px"
:props="{
label: 'name',
value: 'id',
emitPath: false,
}"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="product-list">
<el-card
style="flex: 1; flex-shrink: 0; overflow: hidden"
class="!border-none"
shadow="never"
>
<div
v-loading="pager.loading"
class="eltable"
element-loading-text="加载中..."
>
<div v-if="pager.lists.length > 0" id="shopline" class="card-mode">
<div
v-for="(item, index) in pager.lists"
:key="index"
class="card-item"
>
<card-wrapper
:data="item"
:index="index"
is-show-home-sku="bottom"
:is-sku-image-list="true"
:has-width="true"
:is-show-sku="false"
:is-show-sales="false"
:is-custom="true"
@set-current-img="(val) => setCurrentImg(item, val)"
>
<template #operations>
<!-- <img-->
<!-- title="操作日志"-->
<!-- width="24"-->
<!-- height="24"-->
<!-- src="@/assets/images/log.png"-->
<!-- alt=""-->
<!-- @click.stop="viewTheLog(item.id)"-->
<!-- />-->
<img
title="编辑"
width="24"
height="24"
src="@/assets/images/edit.png"
alt=""
@click.stop="editInfo(item, 'edit')"
/>
</template>
<template #price>
<span
style="margin: 0 5px"
class="price"
:title="'建议零售价' + item.sales_price"
>
{{ item.sales_price ? "¥" : ""
}}{{ item.sales_price }}&nbsp;
</span>
</template>
<template #level-time>
<div
class="create-time"
:title="`上架时间:${item.create_time}`"
>
<span>{{ item.create_time }}</span>
</div>
</template>
<template #synthesizeStatus>
<div title="印花状态" style="position: absolute; right: 0">
<el-tag :type="item.print_type == 0 ? '' : 'warning'">
{{ item.print_type == 0 ? "满印" : "局部印" }}
</el-tag>
</div>
</template>
<template #otherContent>
<div class="sds-keyid">
<div class="product-id" @click.stop="copy(item.id)">
<img
:title="'复制' + item.id"
width="20"
src="@/assets/images/id.png"
alt=""
/>
<span :title="item.id">
{{ item.id }}
</span>
</div>
<div class="product-sku" @click.stop="copy(item.sku)">
<span :title="item.sku">
{{ item.sku }}
</span>
</div>
</div>
</template>
</card-wrapper>
</div>
</div>
<div v-else class="empty">暂无数据</div>
</div>
<div class="flex justify-center mt-4">
<div
style="
display: flex;
align-items: center;
margin-left: 20px;
width: max-content;
"
>
<span>一行展示</span>
<el-input
v-model="rowNumber"
type="number"
style="width: 80px; margin: 0 10px"
placeholder="请输入"
clearable
@change="changeRowNumber"
/>
<span></span>
</div>
&emsp;&emsp;&emsp;
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</div>
</template>
<style scoped lang="scss">
.product{
display: flex;
flex-direction: column;
height: 100%;
}
.searchForm{
::v-deep(.el-form-item){
margin-bottom: 0;
}
}
.justify-center{
display: flex;
justify-content: center;
}
.product-list{
flex: 1;
margin-top: 10px;
flex-shrink: 0;
::v-deep(.el-card){
height: 100%;
.el-card__body{
display: flex;
height: 100%;
flex-direction: column;
.eltable{
flex: 1;
flex-shrink: 0;
overflow: auto;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
</style>
<script setup lang="ts">
import {
getFactoryWarehouseInfo,
factoryWarehouseInfo,
warehouseInfo,
createWarehouseApi,
updateWarehouseApi, deleteWarehouseApi,
} from '@/api/warehouse.ts'
import { nextTick, ref } from 'vue'
const selections = ref<warehouseInfo[]>([])
const formRef = ref()
const createData = ref({
title: '',
show: false,
isEdit: false,
form: {
name: '',
code: '',
sort: '',
defaulted: 1,
remarks: '',
},
})
const rules = {
name: [
{ required: true, message: '请输入仓库名称', trigger: 'blur' },
],
code: [
{ required: true, message: '请输入仓库编码', trigger: 'blur' },
],
defaulted: [
{ required: true, message: '请选择是否默认仓库', trigger: 'change' },
],
}
const leftData = ref<warehouseInfo[]>([])
const pagination = ref<factoryWarehouseInfo>({
pageSize: 50,
currentPage: 1,
total: 0,
})
async function getData() {
const res = await getFactoryWarehouseInfo({
...pagination.value,
})
leftData.value = res.data.records
pagination.value.total = res.data.total
}
const handleSelectionChange = (data: warehouseInfo[]) => {
selections.value = data
}
const handleSizeChange = (pageSize: number) => {
pagination.value.pageSize = pageSize
getData()
}
const handleCurrentChange = (currentPage: number) => {
pagination.value.currentPage = currentPage
getData()
}
const handleConfirm = async () => {
await formRef.value?.validate()
if (!createData.value.isEdit) {
await createWarehouseApi(createData.value.form)
} else {
await updateWarehouseApi(createData.value.form)
}
createData.value.show = false
ElMessage.success('操作成功')
await getData()
}
const handleBatchDelete = async () => {
if (!selections.value.length) {
return ElMessage.warning('请选择要删除的数据')
}
await ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
const str = selections.value.map((el) => el.id).join(',')
await deleteWarehouseApi(str)
ElMessage.success('删除成功')
await getData()
}
const createWarehouse = () => {
createData.value.show = true
createData.value.isEdit = false
createData.value.title = '新增仓库'
createData.value.form = {
name: '',
code: '',
sort: '',
defaulted: 1,
remarks: '',
}
nextTick(() => {
formRef.value?.clearValidate()
})
}
const updateDefaulted = async (item: warehouseInfo) => {
await updateWarehouseApi({
id: item.id,
defaulted: item.defaulted,
})
}
const updateWarehouse = (item: warehouseInfo) => {
createData.value.show = true
createData.value.isEdit = true
createData.value.title = '修改仓库'
createData.value.form = { ...item }
nextTick(() => {
formRef.value?.clearValidate()
})
}
getData()
</script>
<template>
<el-card style="height: 100%">
<div class="manage">
<div class="header">
<el-button type="success" @click="createWarehouse">新增仓库</el-button>
<el-button type="danger" @click="handleBatchDelete">删除</el-button>
</div>
<div class="table-flex">
<div class="left-table">
<div class="table-container">
<el-table height="100%" :data="leftData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" />
<el-table-column type="index" label="序号" width="60" />
<el-table-column label="仓库名称" prop="name" align="center" />
<el-table-column label="仓库类型" prop="name" align="center" />
<el-table-column label="仓库编码" prop="code" align="center" />
<el-table-column label="仓库地址" prop="name" align="center" />
<el-table-column label="备注" prop="remarks" align="center" />
<el-table-column label="默认仓库" prop="defaulted" align="center">
<template #default="{row}">
<el-switch
v-model="row.defaulted" :active-value="1" :inactive-value="0"
@click="updateDefaulted(row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{row}">
<el-button type="primary" @click="updateWarehouse(row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination
v-model:current-page="pagination.currentPage"
v-model:page-size="pagination.pageSize"
:page-sizes="[50, 100, 150, 200]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<el-dialog v-model="createData.show" :title="createData.title">
<el-form ref="formRef" label-width="110px" :rules="rules" :model="createData.form">
<el-form-item label="仓库名称" prop="name">
<el-input v-model="createData.form.name" clearable placeholder="请输入仓库名称"></el-input>
</el-form-item>
<el-form-item label="仓库编码" prop="code">
<el-input v-model="createData.form.code" clearable placeholder="请输入仓库编码"></el-input>
</el-form-item>
<el-form-item label="仓库序号" prop="sort">
<el-input-number v-model="createData.form.sort"></el-input-number>
</el-form-item>
<el-form-item label="是否默认仓库" prop="defaulted">
<el-switch v-model="createData.form.defaulted" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input
v-model="createData.form.remarks" type="textarea" :rows="4" clearable
placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="createData.show=false">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</template>
</el-dialog>
</div>
</el-card>
</template>
<style scoped lang="scss">
.el-card {
::v-deep(.el-card__body) {
height: 100%;
}
}
.manage {
height: 100%;
display: flex;
flex-direction: column;
.header {
margin-bottom: 10px;
}
.table-flex {
flex: 1;
flex-shrink: 0;
overflow: hidden;
display: flex;
}
.right-table {
flex: 1;
margin-left: 10px;
flex-shrink: 0;
}
.left-table {
height: 100%;
display: flex;
width: 100%;
flex-direction: column;
.pagination {
display: flex;
margin-top: 10px;
justify-content: center;
}
.table-container {
flex: 1;
flex-shrink: 0;
overflow: hidden;
}
}
}
</style>
<script setup lang="ts">
import {
getFactoryWarehouseInfo,
factoryWarehouseInfo,
warehouseInfo,
updateWarehouseApi,
deleteWarehouseInventory,
createWarehouseInventoryApi,
updateWarehouseInventoryApi,
} from '@/api/warehouse.ts'
import { nextTick, ref } from 'vue'
const selections = ref<warehouseInfo[]>([])
const formRef = ref()
const createData = ref({
title: '',
show: false,
isEdit: false,
form: {
name: '',
code: '',
sort: '',
defaulted: 1,
remarks: '',
},
})
const rules = {
name: [
{ required: true, message: '请输入仓库名称', trigger: 'blur' },
],
code: [
{ required: true, message: '请输入仓库编码', trigger: 'blur' },
],
defaulted: [
{ required: true, message: '请选择是否默认仓库', trigger: 'change' },
],
}
const leftData = ref<warehouseInfo[]>([])
const pagination = ref<factoryWarehouseInfo>({
pageSize: 50,
currentPage: 1,
total: 0,
})
async function getData() {
const res = await getFactoryWarehouseInfo({
...pagination.value,
})
leftData.value = res.data.records
pagination.value.total = res.data.total
}
const handleSelectionChange = (data: warehouseInfo[]) => {
selections.value = data
}
const handleSizeChange = (pageSize: number) => {
pagination.value.pageSize = pageSize
getData()
}
const handleCurrentChange = (currentPage: number) => {
pagination.value.currentPage = currentPage
getData()
}
const handleConfirm = async () => {
await formRef.value?.validate()
if (!createData.value.isEdit) {
await createWarehouseInventoryApi(createData.value.form)
} else {
await updateWarehouseInventoryApi(createData.value.form)
}
createData.value.show = false
ElMessage.success('操作成功')
await getData()
}
const handleBatchDelete = async () => {
if (!selections.value.length) {
return ElMessage.warning('请选择要删除的数据')
}
await ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
const str = selections.value.map((el) => el.id).join(',')
await deleteWarehouseInventory(str)
ElMessage.success('删除成功')
await getData()
}
const createWarehouse = () => {
createData.value.show = true
createData.value.isEdit = false
createData.value.title = '新增仓库'
createData.value.form = {
name: '',
code: '',
sort: '',
defaulted: 1,
remarks: '',
}
nextTick(() => {
formRef.value?.clearValidate()
})
}
const updateDefaulted = async (item: warehouseInfo) => {
await updateWarehouseApi({
id: item.id,
defaulted: item.defaulted,
})
}
const updateWarehouse = (item: warehouseInfo) => {
createData.value.show = true
createData.value.isEdit = true
createData.value.title = '修改仓库'
createData.value.form = { ...item }
nextTick(() => {
formRef.value?.clearValidate()
})
}
getData()
</script>
<template>
<el-card style="height: 100%">
<div class="manage">
<div class="header">
<el-button type="success" @click="createWarehouse">新增仓库</el-button>
<el-button type="danger" @click="handleBatchDelete">删除</el-button>
</div>
<div class="table-flex">
<div class="left-table">
<div class="table-container">
<el-table height="100%" :data="leftData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" />
<el-table-column type="index" label="序号" width="60" />
<el-table-column label="仓库名称" prop="name" align="center" />
<el-table-column label="仓库类型" prop="name" align="center" />
<el-table-column label="仓库编码" prop="code" align="center" />
<el-table-column label="仓库地址" prop="name" align="center" />
<el-table-column label="备注" prop="remarks" align="center" />
<el-table-column label="默认仓库" prop="defaulted" align="center">
<template #default="{row}">
<el-switch
v-model="row.defaulted" :active-value="1" :inactive-value="0"
@click="updateDefaulted(row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{row}">
<el-button type="primary" @click="updateWarehouse(row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination
v-model:current-page="pagination.currentPage"
v-model:page-size="pagination.pageSize"
:page-sizes="[50, 100, 150, 200]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<el-dialog v-model="createData.show" :title="createData.title">
<el-form ref="formRef" label-width="110px" :rules="rules" :model="createData.form">
<el-form-item label="仓库名称" prop="name">
<el-input v-model="createData.form.name" clearable placeholder="请输入仓库名称"></el-input>
</el-form-item>
<el-form-item label="仓库编码" prop="code">
<el-input v-model="createData.form.code" clearable placeholder="请输入仓库编码"></el-input>
</el-form-item>
<el-form-item label="仓库序号" prop="sort">
<el-input-number v-model="createData.form.sort"></el-input-number>
</el-form-item>
<el-form-item label="是否默认仓库" prop="defaulted">
<el-switch v-model="createData.form.defaulted" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input
v-model="createData.form.remarks" type="textarea" :rows="4" clearable
placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="createData.show=false">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</template>
</el-dialog>
</div>
</el-card>
</template>
<style scoped lang="scss">
.el-card {
::v-deep(.el-card__body) {
height: 100%;
}
}
.manage {
height: 100%;
display: flex;
flex-direction: column;
.header {
margin-bottom: 10px;
}
.table-flex {
flex: 1;
flex-shrink: 0;
overflow: hidden;
display: flex;
}
.right-table {
flex: 1;
margin-left: 10px;
flex-shrink: 0;
}
.left-table {
height: 100%;
display: flex;
width: 100%;
flex-direction: column;
.pagination {
display: flex;
margin-top: 10px;
justify-content: center;
}
.table-container {
flex: 1;
flex-shrink: 0;
overflow: hidden;
}
}
}
</style>
......@@ -7,6 +7,15 @@ import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
base: '/',
server: {
port: 9803,
host: true,
proxy: {
"/api": {
target: "http://10.168.31.230:8060"
}
}
},
plugins: [
vue(),
AutoImport({
......
// vite.config.ts
import { defineConfig } from "file:///C:/work/factory_front/node_modules/vite/dist/node/index.js";
import AutoImport from "file:///C:/work/factory_front/node_modules/unplugin-auto-import/dist/vite.js";
import Components from "file:///C:/work/factory_front/node_modules/unplugin-vue-components/dist/vite.js";
import { ElementPlusResolver } from "file:///C:/work/factory_front/node_modules/unplugin-vue-components/dist/resolvers.js";
import vue from "file:///C:/work/factory_front/node_modules/@vitejs/plugin-vue/dist/index.mjs";
var vite_config_default = defineConfig({
base: "./",
server: {
port: 9803,
host: true,
proxy: {
"/api": {
target: "http://192.168.31.40:8060"
}
}
},
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: { "@": "/src" }
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFx3b3JrXFxcXGZhY3RvcnlfZnJvbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkM6XFxcXHdvcmtcXFxcZmFjdG9yeV9mcm9udFxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vQzovd29yay9mYWN0b3J5X2Zyb250L3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcbmltcG9ydCBBdXRvSW1wb3J0IGZyb20gJ3VucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGUnXG5pbXBvcnQgQ29tcG9uZW50cyBmcm9tICd1bnBsdWdpbi12dWUtY29tcG9uZW50cy92aXRlJ1xuaW1wb3J0IHsgRWxlbWVudFBsdXNSZXNvbHZlciB9IGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3Jlc29sdmVycydcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJ1xuXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYmFzZTogJy4vJyxcbiAgc2VydmVyOiB7XG4gICAgcG9ydDogOTgwMyxcbiAgICBob3N0OiB0cnVlLFxuICAgIHByb3h5OiB7XG4gICAgICAnL2FwaSc6IHtcbiAgICAgICAgdGFyZ2V0OiAnaHR0cDovLzE5Mi4xNjguMzEuNDA6ODA2MCcsXG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG4gIHBsdWdpbnM6IFtcbiAgICB2dWUoKSxcbiAgICBBdXRvSW1wb3J0KHtcbiAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV0sXG4gICAgfSksXG4gICAgQ29tcG9uZW50cyh7XG4gICAgICByZXNvbHZlcnM6IFtFbGVtZW50UGx1c1Jlc29sdmVyKCldLFxuICAgIH0pLFxuICBdLFxuICByZXNvbHZlOiB7XG4gICAgYWxpYXM6IHsgJ0AnOiAnL3NyYycgfSxcbiAgfSxcbn0pXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXVQLFNBQVMsb0JBQW9CO0FBQ3BSLE9BQU8sZ0JBQWdCO0FBQ3ZCLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMsMkJBQTJCO0FBQ3BDLE9BQU8sU0FBUztBQUdoQixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixNQUFNO0FBQUEsRUFDTixRQUFRO0FBQUEsSUFDTixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsSUFDTixPQUFPO0FBQUEsTUFDTCxRQUFRO0FBQUEsUUFDTixRQUFRO0FBQUEsTUFDVjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFDUCxJQUFJO0FBQUEsSUFDSixXQUFXO0FBQUEsTUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxJQUNuQyxDQUFDO0FBQUEsSUFDRCxXQUFXO0FBQUEsTUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxJQUNuQyxDQUFDO0FBQUEsRUFDSDtBQUFBLEVBQ0EsU0FBUztBQUFBLElBQ1AsT0FBTyxFQUFFLEtBQUssT0FBTztBQUFBLEVBQ3ZCO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment