更多新增存酒功能
This commit is contained in:
@@ -5,10 +5,10 @@ ENV = development
|
||||
# VITE_API_WSS = 'wss://sockets.sxczgkj.com/wss'
|
||||
|
||||
# 正式ws
|
||||
VITE_API_WSS = 'wss://czgeatws.sxczgkj.com/wss'
|
||||
# VITE_API_WSS = 'wss://czgeatws.sxczgkj.com/wss'
|
||||
|
||||
# 本地ws
|
||||
# VITE_API_WSS = 'ws://192.168.1.42:2348'
|
||||
VITE_API_WSS = 'ws://192.168.1.42:2348'
|
||||
|
||||
# 正式 php
|
||||
VITE_API_PHP_URL = 'https://newblockwlx.sxczgkj.cn/index.php/api'
|
||||
@@ -23,7 +23,7 @@ VITE_API_PHP_URL = 'https://newblockwlx.sxczgkj.cn/index.php/api'
|
||||
# VITE_API_URL = 'https://tapi.cashier.sxczgkj.cn'
|
||||
|
||||
# 线上正式
|
||||
VITE_API_URL = 'https://cashier.sxczgkj.com'
|
||||
# VITE_API_URL = 'https://cashier.sxczgkj.com'
|
||||
|
||||
# 本地调试连接
|
||||
# VITE_API_URL = 'http://192.168.1.42/'
|
||||
VITE_API_URL = 'http://192.168.1.42/'
|
||||
File diff suppressed because one or more lines are too long
@@ -49,7 +49,7 @@ watch(route, (to) => {
|
||||
includeList.push(to.name);
|
||||
}
|
||||
// 需要全屏的路由
|
||||
let arr = ["/login", "/device_list", "/add_device", "/add_label", "/webview", '/workrecord'];
|
||||
let arr = ["/login", "/device_list", "/add_device", "/add_label", "/webview", '/workrecord', '/store_wine'];
|
||||
if (arr.includes(to.path)) {
|
||||
hideLeftMenu.value = true;
|
||||
} else {
|
||||
|
||||
@@ -65,6 +65,44 @@ export function storageGoodGet(params) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加酒品
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function storageGoodPost(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/product/admin/storageGood",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑酒品
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function storageGoodPut(data) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/product/admin/storageGood/edit",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除酒品
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function storageGoodDelete(id) {
|
||||
return request({
|
||||
method: "DELETE",
|
||||
url: `/product/admin/storageGood?id=${id}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 存酒记录添加
|
||||
* @param {*} data
|
||||
@@ -117,6 +155,18 @@ export function shopStorageRecord(params) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 存酒统计
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function shopStorageCount() {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/product/admin/shopStorage/count"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 耗材库存列表接口
|
||||
* @param {*} data
|
||||
|
||||
@@ -45,11 +45,19 @@
|
||||
<div class="drawerbox_bo_box_itembox" @click="router.push({ name: 'device_list' })">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40">
|
||||
<TurnOff />
|
||||
<Printer />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_icontext">设备管理</div>
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_itembox" @click="router.push({ name: 'store_wine' })">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40">
|
||||
<Goblet />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_icontext">存酒管理</div>
|
||||
</div>
|
||||
<!-- <div class="drawerbox_bo_box_itembox" @click="openCallHandle">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40">
|
||||
|
||||
@@ -17,7 +17,6 @@ import { ref } from 'vue';
|
||||
import userStore from '@/utils/useStorage.js'
|
||||
import { ElUpload, ElMessage } from 'element-plus';
|
||||
|
||||
|
||||
const fileList = ref([])
|
||||
|
||||
// 定义接收的外部属性
|
||||
|
||||
@@ -101,6 +101,11 @@ const routes = [
|
||||
name: "webview",
|
||||
component: () => import("@/views/webview/index.vue"),
|
||||
},
|
||||
{
|
||||
path: "/store_wine",
|
||||
name: "store_wine",
|
||||
component: () => import("@/views/store_wine/index.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
收银
|
||||
</template>
|
||||
@@ -38,7 +38,7 @@
|
||||
@click="takeWineDialogVisible = true; maxTakeNum = row.num; takeWineForm.id = row.id;">
|
||||
<span v-if="isExpired(row.expTime) || row.status == 2">已过期</span>
|
||||
<span v-else-if="row.num <= 0">已取完</span>
|
||||
<span v-else>取酒</span>
|
||||
<span v-else>待取酒</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -48,18 +48,18 @@
|
||||
</div>
|
||||
</el-drawer>
|
||||
<el-dialog v-model="dialogVisible" title="新增存酒" width="350px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form :model="form" :rules="rules" label-width="100px" label-position="left">
|
||||
<el-form-item label="选择酒品">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-position="left">
|
||||
<el-form-item label="选择酒品" prop="shopStorageGoodId">
|
||||
<el-select v-model="form.shopStorageGoodId" placeholder="请选择存酒商品" style="width: 180px;">
|
||||
<el-option v-for="item in storageGoodList" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="存酒数量">
|
||||
<el-input-number v-model="form.num" :min="1"></el-input-number>
|
||||
<el-input-number v-model="form.num" :min="1" :step="1" step-strictly></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="存酒有效期">
|
||||
<el-input-number v-model="form.expDay" :min="1"></el-input-number>
|
||||
<el-input-number v-model="form.expDay" :min="1" :step="1" step-strictly></el-input-number>
|
||||
<span style="margin-left: 8px;">天</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -77,7 +77,8 @@
|
||||
<el-dialog v-model="takeWineDialogVisible" title="取酒" width="350px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form :model="takeWineForm" :rules="takeWineRules" label-width="100px" label-position="left">
|
||||
<el-form-item label="取酒数量">
|
||||
<el-input-number v-model="takeWineForm.num" :min="1" :max="maxTakeNum"></el-input-number>
|
||||
<el-input-number v-model="takeWineForm.num" :min="1" :step="1" step-strictly
|
||||
:max="maxTakeNum"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer">
|
||||
@@ -131,6 +132,8 @@ async function shopStorageGetAjax() {
|
||||
}
|
||||
}
|
||||
|
||||
const formRef = ref(null)
|
||||
|
||||
const form = ref({
|
||||
userId: '',
|
||||
shopStorageGoodId: '', // 存酒商品ID
|
||||
@@ -146,19 +149,23 @@ const rules = {
|
||||
|
||||
// 确认存酒
|
||||
const confirmLoading = ref(false);
|
||||
async function confirmHandle() {
|
||||
try {
|
||||
confirmLoading.value = true;
|
||||
form.value.userId = props.userInfo.userId;
|
||||
await shopStoragePost(form.value);
|
||||
ElMessage.success('存酒成功');
|
||||
dialogVisible.value = false;
|
||||
shopStorageGetAjax(); // 刷新存酒商品列表
|
||||
} catch (error) {
|
||||
console.error('存酒失败:', error);
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
function confirmHandle() {
|
||||
formRef.value.validate(async vaild => {
|
||||
try {
|
||||
if (vaild) {
|
||||
confirmLoading.value = true;
|
||||
form.value.userId = props.userInfo.userId;
|
||||
await shopStoragePost(form.value);
|
||||
ElMessage.success('存酒成功');
|
||||
dialogVisible.value = false;
|
||||
shopStorageGetAjax(); // 刷新存酒商品列表
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('存酒失败:', error);
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取存酒商品列表
|
||||
|
||||
55
src/views/store_wine/components/countPage.vue
Normal file
55
src/views/store_wine/components/countPage.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<el-table :data="list" stripe border v-loading="loading" height="100%">
|
||||
<el-table-column label="商品信息">
|
||||
<template v-slot="scope">
|
||||
<div class="center">
|
||||
<el-avatar :size="40" shape="square" :src="scope.row.imgUrl" style="flex-shrink: 0;">
|
||||
{{ scope.row.name.charAt(0) }}
|
||||
</el-avatar>
|
||||
<el-text>{{ scope.row.name }}</el-text>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="有效存酒" prop="savNum"></el-table-column>
|
||||
<el-table-column label="已过期存酒" prop="savNum"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { shopStorageCount } from '@/api/product_new'
|
||||
|
||||
const loading = ref(false)
|
||||
const list = ref([])
|
||||
|
||||
async function shopStorageCountAjax() {
|
||||
try {
|
||||
loading.value = true
|
||||
list.value = await shopStorageCount()
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
shopStorageCountAjax()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
416
src/views/store_wine/components/managePage.vue
Normal file
416
src/views/store_wine/components/managePage.vue
Normal file
@@ -0,0 +1,416 @@
|
||||
<!-- 存酒记录 -->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<div class="top_wrap">
|
||||
<el-form :model="queryForm" inline>
|
||||
<el-form-item label="酒名">
|
||||
<el-input v-model="queryForm.name" placeholder="请输入酒名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" :loading="tableData.loading"
|
||||
@click="storageGoodGetAjax">搜索</el-button>
|
||||
<el-button icon="Refresh" :loading="tableData.loading" @click="reset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" @click="addFormDialogShow = true">新增</el-button>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<div class="tab_wrap">
|
||||
<el-table :data="tableData.list" v-loading="tableData.loading" border stripe height="100%">
|
||||
<el-table-column label="酒品名">
|
||||
<template v-slot="scope">
|
||||
<div class="center">
|
||||
<el-avatar :size="40" shape="square" :src="scope.row.imgUrl" style="flex-shrink: 0;">
|
||||
{{ scope.row.name.charAt(0) }}
|
||||
</el-avatar>
|
||||
<el-text>{{ scope.row.name }}</el-text>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" prop="unit"></el-table-column>
|
||||
<el-table-column label="有效期(天)" prop="period"></el-table-column>
|
||||
<el-table-column label="来源" prop="source" width="100">
|
||||
<template v-slot="scope">
|
||||
<el-text v-if="scope.row.source === 1">商品</el-text>
|
||||
<el-text v-if="scope.row.source === 0">手动</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="300">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" @click="storeHandle(row)">存酒</el-button>
|
||||
<el-button @click="editorHandle(row)">编辑</el-button>
|
||||
<el-button type="danger" @click="deleteHandle(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<el-pagination background v-model:current-page="tableData.page" v-model:page-size="tableData.size"
|
||||
:page-sizes="[10, 30, 50, 100]" layout="sizes, pager, jumper, total" :total="tableData.total"
|
||||
@size-change="storageGoodGetAjax" @current-change="storageGoodGetAjax"></el-pagination>
|
||||
</div>
|
||||
<!-- 添加/编辑存酒 -->
|
||||
<el-dialog :title="addForm.id ? '编辑酒品' : '添加酒品'" width="600px" v-model="addFormDialogShow"
|
||||
@close="addFormDialogClsoe">
|
||||
<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="120" label-position="right">
|
||||
<el-form-item label="类型">
|
||||
<el-radio-group v-model="addForm.source">
|
||||
<el-radio-button label="手动添加" :value="0"></el-radio-button>
|
||||
<el-radio-button label="从商品添加" :value="1"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="addForm.source === 0">
|
||||
<el-form-item label="酒品名" prop="name">
|
||||
<el-input placeholder="请输入酒品名称" v-model="addForm.name" style="width: 80%;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="酒品图片">
|
||||
<UploadImg ref="UploadImgRef" @success="e => addForm.imgUrl = e" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位">
|
||||
<el-input placeholder="请输入单位" v-model="addForm.unit" style="width: 50%;"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-form-item label="选择商品">
|
||||
<el-select v-model="addForm.prodId" style="width: 80%;">
|
||||
<el-option v-for="item in goodsStore.originGoodsList" :label="item.name" :value="item.id"
|
||||
:key="item.id" @click="selectGoods(item)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品名称">
|
||||
<el-text v-if="addForm.name">{{ addForm.name }}</el-text>
|
||||
<el-text type="info" v-else>请选择商品</el-text>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品图片">
|
||||
<el-image :src="addForm.imgUrl" style="width: 140px;height: 140px;"></el-image>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label="有效期">
|
||||
<el-input-number v-model="addForm.period" :min="1" :step="1" step-strictly></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer">
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" @click="addFormDialogShow = false">
|
||||
取消
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" type="primary" :loading="addFormConfirmLoading"
|
||||
@click="addFormConfirm">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 存酒 -->
|
||||
<el-dialog v-model="dialogVisible" :title="`${form.name} - 新增存酒`" width="400px" :close-on-click-modal="false"
|
||||
destroy-on-close @close="storeInClose">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-position="left">
|
||||
<el-form-item label="选择用户" prop="userId">
|
||||
<el-select v-model="form.userId" placeholder="请选择用户(可搜索)" clearable filterable remote
|
||||
remote-show-suffix :remote-method="remoteMethod" :loading="userListLoading"
|
||||
@clear="getUserList">
|
||||
<el-option :label="`${item.nickName}/${item.phone}`" :value="item.userId"
|
||||
v-for="item in userList" :key="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="选择酒品">
|
||||
<el-select v-model="form.shopStorageGoodId" placeholder="请选择存酒商品">
|
||||
<el-option v-for="item in storageGoodList" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="存酒数量">
|
||||
<el-input-number v-model="form.num" :min="1" :step="1" step-strictly></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="存酒有效期">
|
||||
<el-input-number v-model="form.expDay" :min="1" :step="1" step-strictly></el-input-number>
|
||||
<span style="margin-left: 8px;">天</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer">
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" @click="dialogVisible = false">取 消</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" type="primary" :loading="confirmLoading" @click="confirmHandle">确
|
||||
定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash'
|
||||
import { ref, onMounted, nextTick } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { shopStoragePost, storageGoodGet, storageGoodPost, storageGoodPut, storageGoodDelete } from '@/api/product_new'
|
||||
import { shopUserList } from '@/api/account.js'
|
||||
import UploadImg from '@/components/uploadImg.vue'
|
||||
import { useGoods } from '@/store/goods.js'
|
||||
|
||||
const goodsStore = useGoods()
|
||||
|
||||
const UploadImgRef = ref(null)
|
||||
|
||||
const queryForm = ref({
|
||||
name: ''
|
||||
})
|
||||
|
||||
const tableData = ref({
|
||||
loading: false,
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
list: []
|
||||
});
|
||||
|
||||
function isExpired(expTime) {
|
||||
if (!expTime) return false;
|
||||
const now = new Date();
|
||||
const expDate = new Date(expTime);
|
||||
return expDate < now;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
queryForm.value.name = ''
|
||||
tableData.page = 1
|
||||
storageGoodGetAjax()
|
||||
}
|
||||
|
||||
const userList = ref([])
|
||||
// 获取用户列表
|
||||
const userListLoading = ref(false)
|
||||
|
||||
function remoteMethod(query) {
|
||||
if (query) {
|
||||
getUserList(query)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
async function getUserList(name = '') {
|
||||
try {
|
||||
userListLoading.value = true
|
||||
const res = await shopUserList({ page: 1, key: name, size: 20 })
|
||||
userList.value = res.records
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
userListLoading.value = false
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取存酒商品列表
|
||||
const storageGoodList = ref([]);
|
||||
async function storageGoodGetAjax() {
|
||||
try {
|
||||
tableData.value.loading = true
|
||||
const res = await storageGoodGet({
|
||||
name: queryForm.value.name,
|
||||
page: tableData.value.page,
|
||||
size: tableData.value.size,
|
||||
});
|
||||
tableData.value.list = res.records || [];
|
||||
tableData.value.total = +res.totalRow || 0
|
||||
} catch (error) {
|
||||
console.error('获取存酒商品列表失败:', error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
tableData.value.loading = false
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const formObj = {
|
||||
name: '',
|
||||
userId: '',
|
||||
shopStorageGoodId: '', // 存酒商品ID
|
||||
num: 1, // 存酒数量
|
||||
expDay: 1, // 存酒有效期,单位天默认1天
|
||||
}
|
||||
const formRef = ref(null)
|
||||
const form = ref(formObj)
|
||||
const rules = {
|
||||
userId: [{ required: true, message: '请选择用户', trigger: 'change' }],
|
||||
shopStorageGoodId: [{ required: true, message: '请选择存酒商品', trigger: 'change' }],
|
||||
num: [{ required: true, message: '请输入存酒数量', trigger: 'change' }],
|
||||
expDay: [{ required: true, message: '请输入存酒有效期', trigger: 'change' }],
|
||||
}
|
||||
|
||||
function storeInClose() {
|
||||
formRef.value.resetFields()
|
||||
form.value = _.cloneDeep(formObj)
|
||||
}
|
||||
|
||||
// 确认存酒
|
||||
const confirmLoading = ref(false);
|
||||
function confirmHandle() {
|
||||
formRef.value.validate(async vaild => {
|
||||
try {
|
||||
if (vaild) {
|
||||
confirmLoading.value = true;
|
||||
await shopStoragePost(form.value);
|
||||
ElMessage.success('存酒成功');
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('存酒失败:', error);
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 添加酒品
|
||||
const addFormDialogShow = ref(false)
|
||||
const addFormRef = ref(null)
|
||||
const addFormObj = {
|
||||
id: '',
|
||||
name: '', // 酒品名称
|
||||
imgUrl: '', // 商品图片
|
||||
unit: '瓶', // 单位
|
||||
period: 365, // 过期时间
|
||||
prodId: '', // 商品id
|
||||
source: 0, // 0手动 1商品
|
||||
}
|
||||
const addForm = ref(_.cloneDeep(addFormObj))
|
||||
|
||||
const addFormRules = ref({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入酒品名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 显示存酒
|
||||
async function storeHandle(row) {
|
||||
form.value.name = row.name
|
||||
form.value.shopStorageGoodId = row.id
|
||||
await nextTick()
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑
|
||||
async function editorHandle(row) {
|
||||
addForm.value = _.cloneDeep(row)
|
||||
addFormDialogShow.value = true
|
||||
if (row.source == 0) {
|
||||
await nextTick()
|
||||
UploadImgRef.value.init([{ url: row.imgUrl }])
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
function deleteHandle(row) {
|
||||
ElMessageBox.confirm(`确认要删除酒品「${row.name}」吗?`).then(async () => {
|
||||
try {
|
||||
tableData.value.loading = true
|
||||
await storageGoodDelete(row.id)
|
||||
reset()
|
||||
} catch (error) {
|
||||
tableData.value.loading = false
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
// 选择商品
|
||||
function selectGoods(item) {
|
||||
addForm.value.name = item.name
|
||||
addForm.value.imgUrl = item.coverImg
|
||||
}
|
||||
|
||||
function addFormDialogClsoe() {
|
||||
addFormRef.value.resetFields()
|
||||
addForm.value = _.cloneDeep(addFormObj)
|
||||
if (form.value.source == 0) {
|
||||
UploadImgRef.value.init([])
|
||||
}
|
||||
}
|
||||
|
||||
const addFormConfirmLoading = ref(false)
|
||||
function addFormConfirm() {
|
||||
addFormRef.value.validate(async vaild => {
|
||||
try {
|
||||
if (vaild) {
|
||||
addFormConfirmLoading.value = true
|
||||
if (addForm.value.id) {
|
||||
await storageGoodPut(addForm.value)
|
||||
} else {
|
||||
await storageGoodPost(addForm.value)
|
||||
}
|
||||
ElMessage.success(addForm.value.id ? '编辑成功' : '添加成功')
|
||||
addFormDialogShow.value = false
|
||||
reset()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
addFormConfirmLoading.value = false
|
||||
}, 300);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
storageGoodGetAjax()
|
||||
getUserList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.tab_wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.top_wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
padding-top: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
393
src/views/store_wine/components/record.vue
Normal file
393
src/views/store_wine/components/record.vue
Normal file
@@ -0,0 +1,393 @@
|
||||
<!-- 存酒记录 -->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<div class="top_wrap">
|
||||
<el-form :model="queryForm" inline>
|
||||
<el-form-item label="酒名/用户昵称">
|
||||
<el-input v-model="queryForm.key" placeholder="请输入酒名/用户昵称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryForm.status" placeholder="请选择状态" clearable style="width: 150px;">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="已取完" value="0" />
|
||||
<el-option label="储存中" value="1" />
|
||||
<el-option label="已过期" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" :loading="tableData.loading"
|
||||
@click="shopStorageGetAjax">搜索</el-button>
|
||||
<el-button icon="Refresh" :loading="tableData.loading" @click="reset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" @click="dialogVisible = true">新增存酒</el-button>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<div class="tab_wrap">
|
||||
<el-table :data="tableData.list" v-loading="tableData.loading" border stripe height="100%">
|
||||
<el-table-column label="用户">
|
||||
<template v-slot="scope">
|
||||
<div class="center">
|
||||
<el-avatar :size="40" :src="scope.row.headImg" style="flex-shrink: 0;">
|
||||
{{ scope.row.nickName.charAt(0) }}
|
||||
</el-avatar>
|
||||
<el-text>{{ scope.row.nickName }}</el-text>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="酒品名">
|
||||
<template v-slot="scope">
|
||||
<div class="center">
|
||||
<el-avatar :size="40" shape="square" :src="scope.row.imgUrl" style="flex-shrink: 0;">
|
||||
{{ scope.row.name.charAt(0) }}
|
||||
</el-avatar>
|
||||
<el-text>{{ scope.row.name }}</el-text>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" prop="num" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-text>{{ scope.row.num }}{{ scope.row.unit }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存酒时间" prop="savTime"></el-table-column>
|
||||
<el-table-column label="到期时间" prop="expTime"></el-table-column>
|
||||
<el-table-column label="状态" prop="status" width="100">
|
||||
<template v-slot="scope">
|
||||
<el-tag disable-transitions type="info"
|
||||
v-if="isExpired(scope.row.expTime) || scope.row.status == 2">已过期</el-tag>
|
||||
<el-tag disable-transitions type="info" v-else-if="scope.row.num <= 0">已取完</el-tag>
|
||||
<el-tag disable-transitions type="primary" v-else>未取完</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="240">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" @click="viewRecord(row)">查看记录</el-button>
|
||||
<el-button type="danger" :disabled="isExpired(row.expTime) || row.num <= 0"
|
||||
@click="takeWineDialogVisible = true; maxTakeNum = row.num; takeWineForm.id = row.id;">
|
||||
<span v-if="isExpired(row.expTime) || row.status == 2">已过期</span>
|
||||
<span v-else-if="row.num <= 0">已取完</span>
|
||||
<span v-else>待取酒</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<el-pagination background v-model:current-page="tableData.page" v-model:page-size="tableData.size"
|
||||
:page-sizes="[10, 30, 50, 100]" layout="sizes, pager, jumper, total" :total="tableData.total"
|
||||
@size-change="shopStorageGetAjax" @current-change="shopStorageGetAjax"></el-pagination>
|
||||
</div>
|
||||
<!-- 存酒 -->
|
||||
<el-dialog v-model="dialogVisible" title="新增存酒" width="400px" :close-on-click-modal="false" destroy-on-close
|
||||
@open="storeInOpen">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-position="left">
|
||||
<el-form-item label="选择用户" prop="userId">
|
||||
<el-select v-model="form.userId" placeholder="请选择用户(可搜索)" clearable filterable remote
|
||||
remote-show-suffix :remote-method="remoteMethod" :loading="userListLoading"
|
||||
@clear="getUserList">
|
||||
<el-option :label="`${item.nickName}/${item.phone}`" :value="item.userId"
|
||||
v-for="item in userList" :key="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="选择酒品" prop="shopStorageGoodId">
|
||||
<el-select v-model="form.shopStorageGoodId" placeholder="请选择存酒商品">
|
||||
<el-option v-for="item in storageGoodList" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="存酒数量">
|
||||
<el-input-number v-model="form.num" :min="1" :step="1" step-strictly></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="存酒有效期">
|
||||
<el-input-number v-model="form.expDay" :min="1" :step="1" step-strictly></el-input-number>
|
||||
<span style="margin-left: 8px;">天</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer">
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" @click="dialogVisible = false">取 消</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" type="primary" :loading="confirmLoading" @click="confirmHandle">确
|
||||
定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 存取酒记录弹窗 -->
|
||||
<el-dialog title="记录" width="600px" v-model="showRecordDialogVisible">
|
||||
<el-table :data="recordList" border stripe>
|
||||
<el-table-column label="记录" prop="content"></el-table-column>
|
||||
<el-table-column label="操作时间" prop="time"></el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
<!-- 取酒对话框,只选择数量即可,不可超过存酒的数量 -->
|
||||
<el-dialog v-model="takeWineDialogVisible" title="取酒" width="350px" :close-on-click-modal="false"
|
||||
destroy-on-close>
|
||||
<el-form :model="takeWineForm" :rules="takeWineRules" label-width="100px" label-position="left">
|
||||
<el-form-item label="取酒数量">
|
||||
<el-input-number v-model="takeWineForm.num" :min="1" :step="1" step-strictly
|
||||
:max="maxTakeNum"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer">
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" @click="takeWineDialogVisible = false">取 消</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%;" type="primary" :loading="takeWineConfirmLoading"
|
||||
@click="confirmTakeWineHandle">确 定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { shopStoragePost, storageGoodGet, shopStorageGet, shopStoragePut, shopStorageRecord } from '@/api/product_new'
|
||||
import { shopUserList } from '@/api/account.js'
|
||||
|
||||
const queryForm = ref({
|
||||
key: '',
|
||||
status: ''
|
||||
})
|
||||
|
||||
const tableData = ref({
|
||||
loading: false,
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
list: []
|
||||
});
|
||||
|
||||
function isExpired(expTime) {
|
||||
if (!expTime) return false;
|
||||
const now = new Date();
|
||||
const expDate = new Date(expTime);
|
||||
return expDate < now;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
queryForm.value.name = ''
|
||||
queryForm.value.status = ''
|
||||
tableData.page = 1
|
||||
shopStorageGetAjax()
|
||||
}
|
||||
|
||||
// 获取存酒记录
|
||||
async function shopStorageGetAjax() {
|
||||
try {
|
||||
tableData.value.loading = true
|
||||
const res = await shopStorageGet({
|
||||
key: queryForm.value.key,
|
||||
phone: '',
|
||||
status: queryForm.value.status,
|
||||
page: tableData.value.page,
|
||||
size: tableData.value.size,
|
||||
});
|
||||
tableData.value.list = res.records || [];
|
||||
tableData.value.total = +res.totalRow || 0
|
||||
} catch (error) {
|
||||
console.error('获取存酒列表失败:', error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
tableData.value.loading = false
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
function storeInOpen() {
|
||||
init()
|
||||
getUserList()
|
||||
storageGoodGetAjax()
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
form.value = {
|
||||
userId: '',
|
||||
shopStorageGoodId: '',
|
||||
num: 1,
|
||||
expDay: 1,
|
||||
};
|
||||
}
|
||||
|
||||
const userList = ref([])
|
||||
// 获取用户列表
|
||||
const userListLoading = ref(false)
|
||||
|
||||
function remoteMethod(query) {
|
||||
if (query) {
|
||||
getUserList(query)
|
||||
}
|
||||
}
|
||||
|
||||
async function getUserList(name = '') {
|
||||
try {
|
||||
userListLoading.value = true
|
||||
const res = await shopUserList({ page: 1, key: name, size: 20 })
|
||||
userList.value = res.records
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
userListLoading.value = false
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取存酒商品列表
|
||||
const storageGoodList = ref([]);
|
||||
async function storageGoodGetAjax() {
|
||||
try {
|
||||
const res = await storageGoodGet({
|
||||
page: 1,
|
||||
size: 999,
|
||||
});
|
||||
storageGoodList.value = res.records || [];
|
||||
} catch (error) {
|
||||
console.error('获取存酒商品列表失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const formRef = ref(null)
|
||||
const form = ref({
|
||||
userId: '',
|
||||
shopStorageGoodId: '', // 存酒商品ID
|
||||
num: 1, // 存酒数量
|
||||
expDay: 1, // 存酒有效期,单位天默认1天
|
||||
})
|
||||
|
||||
const rules = {
|
||||
userId: [{ required: true, message: '请选择用户', trigger: 'change' }],
|
||||
shopStorageGoodId: [{ required: true, message: '请选择存酒商品', trigger: 'change' }],
|
||||
num: [{ required: true, message: '请输入存酒数量', trigger: 'change' }],
|
||||
expDay: [{ required: true, message: '请输入存酒有效期', trigger: 'change' }],
|
||||
}
|
||||
|
||||
// 确认存酒
|
||||
const confirmLoading = ref(false);
|
||||
function confirmHandle() {
|
||||
formRef.value.validate(async vaild => {
|
||||
try {
|
||||
if (vaild) {
|
||||
confirmLoading.value = true;
|
||||
await shopStoragePost(form.value);
|
||||
ElMessage.success('存酒成功');
|
||||
dialogVisible.value = false;
|
||||
shopStorageGetAjax(); // 刷新存酒商品列表
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('存酒失败:', error);
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 查看记录
|
||||
const showRecordDialogVisible = ref(false);
|
||||
const recordList = ref([]);
|
||||
async function viewRecord(row) {
|
||||
try {
|
||||
showRecordDialogVisible.value = true;
|
||||
const res = await shopStorageRecord({
|
||||
id: row.id,
|
||||
page: 1,
|
||||
size: 999,
|
||||
});
|
||||
recordList.value = res || [];
|
||||
} catch (error) {
|
||||
console.error('获取存取酒记录失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const takeWineDialogVisible = ref(false);
|
||||
const takeWineForm = ref({
|
||||
id: '', // 存酒记录ID
|
||||
num: 1,
|
||||
})
|
||||
const takeWineRules = {
|
||||
num: [{ required: true, message: '请输入取酒数量', trigger: 'change' }],
|
||||
}
|
||||
const maxTakeNum = ref(1);
|
||||
const takeWineConfirmLoading = ref(false);
|
||||
|
||||
function confirmTakeWineHandle() {
|
||||
shopStoragePutAjax();
|
||||
}
|
||||
|
||||
// 存酒取酒 num 必需 正数为存酒反之为取酒
|
||||
async function shopStoragePutAjax() {
|
||||
try {
|
||||
takeWineConfirmLoading.value = true;
|
||||
await shopStoragePut({
|
||||
id: takeWineForm.value.id,
|
||||
num: -takeWineForm.value.num, // 取酒数量为负数
|
||||
});
|
||||
ElMessage.success('取酒成功');
|
||||
takeWineDialogVisible.value = false;
|
||||
shopStorageGetAjax(); // 刷新存酒记录列表
|
||||
} catch (error) {
|
||||
console.error('取酒失败:', error);
|
||||
} finally {
|
||||
takeWineConfirmLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
shopStorageGetAjax()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.tab_wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.top_wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
padding-top: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
104
src/views/store_wine/index.vue
Normal file
104
src/views/store_wine/index.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="drawer_wrap">
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<div class="return" @click="router.back()">
|
||||
<el-icon size="26" color="#555">
|
||||
<Back />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="menu_wrap">
|
||||
<el-radio-group v-model="pageType">
|
||||
<el-radio-button label="存酒记录" :value="1"></el-radio-button>
|
||||
<el-radio-button label="可存酒管理" :value="2"></el-radio-button>
|
||||
<el-radio-button label="存酒统计" :value="3"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pay_wrap">
|
||||
<!-- 存酒记录 -->
|
||||
<record name="record" key="record" v-if="pageType == 1" />
|
||||
<!-- 存酒管理 -->
|
||||
<managePage name="managePage" key="managePage" v-if="pageType == 2" />
|
||||
<!-- 存酒统计 -->
|
||||
<countPage name="countPage" key="countPage" v-if="pageType == 3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter } from 'vue-router'
|
||||
import record from "./components/record.vue";
|
||||
import countPage from "./components/countPage.vue";
|
||||
import managePage from "./components/managePage.vue";
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const pageType = ref(1)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: var(--el-font-size-base);
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.drawer_wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 var(--el-font-size-base);
|
||||
background-color: #fff;
|
||||
padding: var(--el-font-size-base);
|
||||
border-radius: var(--el-font-size-base);
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.return {
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.3s;
|
||||
padding: 10px 8px 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.user_info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.menu_wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pay_wrap {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
border-radius: var(--el-font-size-base);
|
||||
padding: var(--el-font-size-base);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user