代码提交-对接接口
This commit is contained in:
parent
6a7d5db119
commit
a19f48034d
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,38 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询商品类别列表
|
||||
export function listproductCategory(query) {
|
||||
return request({
|
||||
url: '/api/v1/product-category',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增商品类别
|
||||
export function addProductCategory(data) {
|
||||
return request({
|
||||
url: '/api/v1/product-category',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改商品类别
|
||||
export function updateProductCategory(data) {
|
||||
return request({
|
||||
url: '/api/v1/product-category/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除商品类别
|
||||
export function delProductCategory(data) {
|
||||
return request({
|
||||
url: '/api/v1/product-category',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询客户列表
|
||||
export function listCustomer(query) {
|
||||
return request({
|
||||
url: '/api/v1/customer',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增客户
|
||||
export function addCustomer(data) {
|
||||
return request({
|
||||
url: '/api/v1/customer',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改客户
|
||||
export function updateCustomer(data) {
|
||||
return request({
|
||||
url: '/api/v1/customer/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除客户
|
||||
export function delCustomer(data) {
|
||||
return request({
|
||||
url: '/api/v1/customer',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询价格管理列表
|
||||
export function listPriceIndex(query) {
|
||||
return request({
|
||||
url: '/api/v1/price-index',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增价格管理
|
||||
export function addPriceIndex(data) {
|
||||
return request({
|
||||
url: '/api/v1/price-index',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改价格管理
|
||||
export function updatePriceIndex(data) {
|
||||
return request({
|
||||
url: '/api/v1/price-index/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除价格管理
|
||||
export function delPriceIndex(data) {
|
||||
return request({
|
||||
url: '/api/v1/price-index',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询商品列表
|
||||
export function listproduct(query) {
|
||||
return request({
|
||||
url: '/api/v1/product',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增商品
|
||||
export function addProduct(data) {
|
||||
return request({
|
||||
url: '/api/v1/product',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改商品
|
||||
export function updateProduct(data) {
|
||||
return request({
|
||||
url: '/api/v1/product/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除商品
|
||||
export function delProduct(data) {
|
||||
return request({
|
||||
url: '/api/v1/product',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//上传文件
|
||||
export function uploadFile(data) {
|
||||
return request({
|
||||
url: '/api/v1/public/uploadFile',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
// 关闭防重复提交,避免 FormData 被序列化
|
||||
repeatSubmit: false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询仓库列表
|
||||
export function listWarehouse(query) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增仓库
|
||||
export function addWarehouse(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改仓库
|
||||
export function updateWarehouse(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除仓库
|
||||
export function delWarehouse(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询仓库垛位列表
|
||||
export function listWarehouseStock(query) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse-stock',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增仓库垛位
|
||||
export function addWarehouseStock(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse-stock',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改仓库垛位
|
||||
export function updateWarehouseStock(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse-stock/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除仓库垛位
|
||||
export function delWarehouseStock(data) {
|
||||
return request({
|
||||
url: '/api/v1/warehouse-stock',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询供应商管理列表
|
||||
export function listSupplier(query) {
|
||||
return request({
|
||||
url: '/api/v1/supplier',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增供应商
|
||||
export function addSupplier(data) {
|
||||
return request({
|
||||
url: '/api/v1/supplier',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改供应商
|
||||
export function updateSupplier(data) {
|
||||
return request({
|
||||
url: '/api/v1/supplier/' + data.id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除供应商
|
||||
export function delSupplier(data) {
|
||||
return request({
|
||||
url: '/api/v1/supplier',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询库存报警配置列表
|
||||
export function listInventoryAlertConfig(query) {
|
||||
return request({
|
||||
url: '/api/v1/inventory-alert-config',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 修改库存报警配置
|
||||
export function updateInventoryAlertConfig(data, id) {
|
||||
return request({
|
||||
url: '/api/v1/inventory-alert-config/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除库存报警配置
|
||||
export function delInventoryAlertConfig(data) {
|
||||
return request({
|
||||
url: '/api/v1/inventory-alert-config/' + query.id,
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -78,6 +78,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
|
|||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { listproductCategory, addProductCategory, updateProductCategory, delProductCategory } from '@/api/base/category'
|
||||
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
|
|
@ -114,41 +115,16 @@ const dialogTitle = computed(() => isEdit.value ? '编辑类别' : '新增类别
|
|||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_categories') || '[]')
|
||||
const start = (queryParams.pageNum - 1) * queryParams.pageSize
|
||||
const end = start + queryParams.pageSize
|
||||
categoryList.value = mockData.slice(start, end)
|
||||
total.value = mockData.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateMockData()
|
||||
}
|
||||
const response = await listproductCategory(queryParams)
|
||||
categoryList.value = response.data.list || []
|
||||
total.value = response.count || 0
|
||||
} catch (error) {
|
||||
ElMessage.error('获取类别列表失败:' + error.message)
|
||||
ElMessage.error('获取类别列表失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const generateMockData = () => {
|
||||
setTimeout(() => {
|
||||
const categoryNames = ['动力煤', '焦煤', '无烟煤', '褐煤', '瘦煤', '肥煤', '气煤', '1/3焦煤', '贫煤', '长焰煤', '不粘煤', '弱粘煤', '1/2中粘煤', '中粘煤', '强粘煤', '特强粘煤', '贫瘦煤', '瘦焦煤', '主焦煤', '其他']
|
||||
const newCategories = []
|
||||
const now = Date.now()
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
newCategories.push({
|
||||
id: i,
|
||||
categoryCode: 'CAT' + String(i).padStart(3, '0'),
|
||||
categoryName: categoryNames[i - 1],
|
||||
createTime: new Date(now - i * 30 * 86400000).toISOString(),
|
||||
updateTime: new Date(now - i * 30 * 86400000).toISOString()
|
||||
})
|
||||
}
|
||||
localStorage.setItem('mock_categories', JSON.stringify(newCategories))
|
||||
getList()
|
||||
}, 10)
|
||||
}
|
||||
|
||||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
resetForm()
|
||||
|
|
@ -177,62 +153,24 @@ const resetForm = () => {
|
|||
const handleSubmit = async () => {
|
||||
if (!categoryFormRef.value) return
|
||||
|
||||
await categoryFormRef.value.validate((valid) => {
|
||||
await categoryFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_categories') || '[]')
|
||||
const now = new Date().toISOString()
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑
|
||||
const index = mockData.findIndex(item => item.id === categoryForm.id)
|
||||
if (index !== -1) {
|
||||
// 检查类别编码是否重复(排除当前编辑的项)
|
||||
const codeExists = mockData.find(item =>
|
||||
item.id !== categoryForm.id &&
|
||||
item.categoryCode === categoryForm.categoryCode
|
||||
)
|
||||
if (codeExists) {
|
||||
ElMessage.warning('类别编码已存在')
|
||||
submitLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
mockData[index] = {
|
||||
...mockData[index],
|
||||
categoryCode: categoryForm.categoryCode,
|
||||
categoryName: categoryForm.categoryName,
|
||||
updateTime: now
|
||||
}
|
||||
}
|
||||
await updateProductCategory(categoryForm)
|
||||
ElMessage.success('编辑成功')
|
||||
} else {
|
||||
// 新增
|
||||
// 检查类别编码是否重复
|
||||
const codeExists = mockData.find(item => item.categoryCode === categoryForm.categoryCode)
|
||||
if (codeExists) {
|
||||
ElMessage.warning('类别编码已存在')
|
||||
submitLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1
|
||||
mockData.push({
|
||||
id: newId,
|
||||
categoryCode: categoryForm.categoryCode,
|
||||
categoryName: categoryForm.categoryName,
|
||||
createTime: now,
|
||||
updateTime: now
|
||||
})
|
||||
await addProductCategory(categoryForm)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_categories', JSON.stringify(mockData))
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
ElMessage.error('操作失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
|
|
@ -240,16 +178,19 @@ const handleSubmit = async () => {
|
|||
}
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const Ids = (row.id && [row.id])
|
||||
ElMessageBox.confirm('确定要删除此类别吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const categories = JSON.parse(localStorage.getItem('mock_categories') || '[]')
|
||||
const filtered = categories.filter(c => c.id != row.id)
|
||||
localStorage.setItem('mock_categories', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delProductCategory({ ids: Ids })
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 150px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="正常" value="1" />
|
||||
<el-option label="停用" value="0" />
|
||||
<el-option label="正常" value="正常" />
|
||||
<el-option label="停用" value="停用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
|
@ -27,41 +27,36 @@
|
|||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="customerList" border style="width: 100%; margin-top: 20px;">
|
||||
<el-table-column prop="customerCode" label="客户ID" width="120" />
|
||||
<!-- <el-table-column prop="customerCode" label="客户ID" width="120" /> -->
|
||||
<el-table-column prop="customerName" label="客户名称" width="200" />
|
||||
<el-table-column prop="customerType" label="客户类型" width="120">
|
||||
<template #default="scope">
|
||||
{{ getCustomerTypeName(scope.row.customerType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="contact" label="联系人" width="120" />
|
||||
<el-table-column prop="phone" label="手机号" width="130" />
|
||||
<el-table-column prop="contactPerson" label="联系人" width="120" />
|
||||
<el-table-column prop="mobilePhone" label="手机号" width="130" />
|
||||
<el-table-column prop="email" label="邮箱" width="180" />
|
||||
<el-table-column prop="address" label="详细地址" min-width="200" />
|
||||
<el-table-column prop="detailAddress" label="详细地址" min-width="200" />
|
||||
<el-table-column prop="bankName" label="开户银行" width="150" />
|
||||
<el-table-column prop="bankAccount" label="银行账号" width="180" />
|
||||
<el-table-column prop="taxNumber" label="税号" width="180" />
|
||||
<el-table-column prop="status" label="客户状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'">
|
||||
{{ scope.row.status == 1 ? '正常' : '停用' }}
|
||||
<el-tag :type="scope.row.status == '正常' ? 'success' : 'danger'">
|
||||
{{ scope.row.status == '正常' ? '正常' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="qualificationInfo" label="资质信息" width="150">
|
||||
<!-- <el-table-column prop="qualificationInfo" label="资质信息" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.qualificationInfo && scope.row.qualificationInfo.length > 0"
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleViewQualification(scope.row)"
|
||||
>
|
||||
<el-button v-if="scope.row.qualificationInfo && scope.row.qualificationInfo.length > 0" link type="primary"
|
||||
size="small" @click="handleViewQualification(scope.row)">
|
||||
查看资质({{ scope.row.qualificationInfo.length }})
|
||||
</el-button>
|
||||
<span v-else style="color: #999;">暂无资质</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="操作" width="250" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="handleView(scope.row)">查看</el-button>
|
||||
|
|
@ -71,46 +66,23 @@
|
|||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageIndex"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑客户对话框 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
@close="resetForm"
|
||||
>
|
||||
<el-form
|
||||
ref="customerFormRef"
|
||||
:model="customerForm"
|
||||
:rules="customerFormRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="800px" :close-on-click-modal="false"
|
||||
@close="resetForm">
|
||||
<el-form ref="customerFormRef" :model="customerForm" :rules="customerFormRules" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户名称" prop="customerName">
|
||||
<el-input
|
||||
v-model="customerForm.customerName"
|
||||
placeholder="请输入客户名称"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="customerForm.customerName" placeholder="请输入客户名称" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户类型" prop="customerType">
|
||||
<el-select
|
||||
v-model="customerForm.customerType"
|
||||
placeholder="请选择客户类型"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-select v-model="customerForm.customerType" placeholder="请选择客户类型" style="width: 100%">
|
||||
<el-option label="发电厂" value="power_plant" />
|
||||
<el-option label="炼钢厂" value="steel_plant" />
|
||||
<el-option label="经销商" value="dealer" />
|
||||
|
|
@ -123,93 +95,56 @@
|
|||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人" prop="contact">
|
||||
<el-input
|
||||
v-model="customerForm.contact"
|
||||
placeholder="请输入联系人"
|
||||
maxlength="20"
|
||||
/>
|
||||
<el-form-item label="联系人" prop="contactPerson">
|
||||
<el-input v-model="customerForm.contactPerson" placeholder="请输入联系人" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input
|
||||
v-model="customerForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
maxlength="11"
|
||||
/>
|
||||
<el-form-item label="手机号" prop="mobilePhone">
|
||||
<el-input v-model="customerForm.mobilePhone" placeholder="请输入手机号" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input
|
||||
v-model="customerForm.email"
|
||||
placeholder="请输入邮箱"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="customerForm.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="详细地址" prop="address">
|
||||
<el-input
|
||||
v-model="customerForm.address"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="请输入详细地址"
|
||||
maxlength="200"
|
||||
/>
|
||||
<el-form-item label="详细地址" prop="detailAddress">
|
||||
<el-input v-model="customerForm.detailAddress" type="textarea" :rows="2" placeholder="请输入详细地址" maxlength="200" />
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开户银行" prop="bankName">
|
||||
<el-input
|
||||
v-model="customerForm.bankName"
|
||||
placeholder="请输入开户银行"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="customerForm.bankName" placeholder="请输入开户银行" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="银行账号" prop="bankAccount">
|
||||
<el-input
|
||||
v-model="customerForm.bankAccount"
|
||||
placeholder="请输入银行账号"
|
||||
maxlength="30"
|
||||
/>
|
||||
<el-input v-model="customerForm.bankAccount" placeholder="请输入银行账号" maxlength="30" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="税号" prop="taxNumber">
|
||||
<el-input
|
||||
v-model="customerForm.taxNumber"
|
||||
placeholder="请输入税号"
|
||||
maxlength="30"
|
||||
/>
|
||||
<el-input v-model="customerForm.taxNumber" placeholder="请输入税号" maxlength="30" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户状态" prop="status">
|
||||
<el-radio-group v-model="customerForm.status">
|
||||
<el-radio :label="1">正常</el-radio>
|
||||
<el-radio :label="0">停用</el-radio>
|
||||
<el-radio :label="'正常'">正常</el-radio>
|
||||
<el-radio :label="'停用'">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="资质信息" prop="qualificationInfo">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove"
|
||||
:multiple="true"
|
||||
accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png"
|
||||
>
|
||||
<!-- <el-form-item label="资质信息" prop="qualificationInfo">
|
||||
<el-upload ref="uploadRef" :file-list="fileList" :auto-upload="false" :on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove" :multiple="true" accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png">
|
||||
<el-button type="primary">选择文件</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
|
|
@ -217,14 +152,15 @@
|
|||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<div v-if="customerForm.qualificationInfo && customerForm.qualificationInfo.length > 0" style="margin-top: 10px;">
|
||||
<div v-if="customerForm.qualificationInfo && customerForm.qualificationInfo.length > 0"
|
||||
style="margin-top: 10px;">
|
||||
<div v-for="(file, index) in customerForm.qualificationInfo" :key="index" style="margin-bottom: 5px;">
|
||||
<el-button link type="primary" size="small" @click="handleViewQualificationFile(file)">
|
||||
{{ file.name }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
|
|
@ -237,28 +173,25 @@
|
|||
</el-dialog>
|
||||
|
||||
<!-- 查看客户对话框 -->
|
||||
<el-dialog
|
||||
v-model="viewDialogVisible"
|
||||
title="查看客户"
|
||||
width="800px"
|
||||
>
|
||||
<el-dialog v-model="viewDialogVisible" title="查看客户" width="800px">
|
||||
<el-descriptions :column="2" border v-if="currentCustomer">
|
||||
<el-descriptions-item label="客户ID">{{ currentCustomer.customerCode }}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label="客户ID">{{ currentCustomer.customerCode }}</el-descriptions-item> -->
|
||||
<el-descriptions-item label="客户名称">{{ currentCustomer.customerName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户类型">{{ getCustomerTypeName(currentCustomer.customerType) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户类型">{{ getCustomerTypeName(currentCustomer.customerType)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户状态">
|
||||
<el-tag :type="currentCustomer.status == 1 ? 'success' : 'danger'">
|
||||
{{ currentCustomer.status == 1 ? '正常' : '停用' }}
|
||||
<el-tag :type="currentCustomer.status == '正常' ? 'success' : 'danger'">
|
||||
{{ currentCustomer.status == '正常' ? '正常' : '停用' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人">{{ currentCustomer.contact }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ currentCustomer.phone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人">{{ currentCustomer.contactPerson }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ currentCustomer.mobilePhone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱">{{ currentCustomer.email || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="详细地址" :span="2">{{ currentCustomer.address }}</el-descriptions-item>
|
||||
<el-descriptions-item label="详细地址" :span="2">{{ currentCustomer.detailAddress }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开户银行">{{ currentCustomer.bankName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="银行账号">{{ currentCustomer.bankAccount || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="税号" :span="2">{{ currentCustomer.taxNumber || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="资质信息" :span="2">
|
||||
<!-- <el-descriptions-item label="资质信息" :span="2">
|
||||
<div v-if="currentCustomer.qualificationInfo && currentCustomer.qualificationInfo.length > 0">
|
||||
<div v-for="(file, index) in currentCustomer.qualificationInfo" :key="index" style="margin-bottom: 5px;">
|
||||
<el-button link type="primary" size="small" @click="handleViewQualificationFile(file)">
|
||||
|
|
@ -267,28 +200,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<span v-else style="color: #999;">暂无资质</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions-item> -->
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查看资质文件对话框 -->
|
||||
<el-dialog
|
||||
v-model="qualificationDialogVisible"
|
||||
title="查看资质文件"
|
||||
width="900px"
|
||||
>
|
||||
<el-dialog v-model="qualificationDialogVisible" title="查看资质文件" width="900px">
|
||||
<div v-if="currentQualificationFile" style="text-align: center;">
|
||||
<iframe
|
||||
v-if="currentQualificationFile.type === 'pdf'"
|
||||
:src="currentQualificationFile.url"
|
||||
style="width: 100%; height: 600px; border: none;"
|
||||
></iframe>
|
||||
<img
|
||||
v-else-if="currentQualificationFile.type === 'image'"
|
||||
:src="currentQualificationFile.url"
|
||||
style="max-width: 100%; max-height: 600px;"
|
||||
alt="资质文件"
|
||||
/>
|
||||
<iframe v-if="currentQualificationFile.type === 'pdf'" :src="currentQualificationFile.url"
|
||||
style="width: 100%; height: 600px; border: none;"></iframe>
|
||||
<img v-else-if="currentQualificationFile.type === 'image'" :src="currentQualificationFile.url"
|
||||
style="max-width: 100%; max-height: 600px;" alt="资质文件" />
|
||||
<div v-else>
|
||||
<el-button type="primary" @click="handleDownloadQualificationFile(currentQualificationFile)">
|
||||
下载文件
|
||||
|
|
@ -304,7 +226,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
|
|||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { formatMoney } from '@/utils/business'
|
||||
import Pagination from '@/components/Pagination'
|
||||
|
||||
import { listCustomer, addCustomer, updateCustomer, delCustomer } from '@/api/base/customer'
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const customerList = ref([])
|
||||
|
|
@ -320,7 +242,7 @@ const currentCustomer = ref(null)
|
|||
const currentQualificationFile = ref(null)
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
customerType: '',
|
||||
status: ''
|
||||
|
|
@ -331,15 +253,15 @@ const customerForm = reactive({
|
|||
customerCode: '',
|
||||
customerName: '',
|
||||
customerType: '',
|
||||
contact: '',
|
||||
phone: '',
|
||||
contactPerson: '',
|
||||
mobilePhone: '',
|
||||
email: '',
|
||||
address: '',
|
||||
detailAddress: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
taxNumber: '',
|
||||
qualificationInfo: [],
|
||||
status: 1
|
||||
status: '正常'
|
||||
})
|
||||
|
||||
const customerFormRules = {
|
||||
|
|
@ -350,17 +272,17 @@ const customerFormRules = {
|
|||
customerType: [
|
||||
{ required: true, message: '请选择客户类型', trigger: 'change' }
|
||||
],
|
||||
contact: [
|
||||
contactPerson: [
|
||||
{ required: true, message: '请输入联系人', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
mobilePhone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
||||
],
|
||||
address: [
|
||||
detailAddress: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' }
|
||||
],
|
||||
bankName: [
|
||||
|
|
@ -394,20 +316,15 @@ const getCustomerTypeName = (type) => {
|
|||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_customers') || '[]')
|
||||
let filtered = mockData.filter(item => {
|
||||
if (queryParams.customerType && item.customerType !== queryParams.customerType) return false
|
||||
if (queryParams.status !== '' && item.status != queryParams.status) return false
|
||||
return true
|
||||
const res = await listCustomer({
|
||||
pageIndex: queryParams.pageIndex,
|
||||
pageSize: queryParams.pageSize,
|
||||
customerType: queryParams.customerType,
|
||||
status: queryParams.status
|
||||
})
|
||||
const start = (queryParams.pageNum - 1) * queryParams.pageSize
|
||||
const end = start + queryParams.pageSize
|
||||
customerList.value = filtered.slice(start, end)
|
||||
total.value = filtered.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateMockData()
|
||||
}
|
||||
// 根据你后台返回结构微调这两行
|
||||
customerList.value =res.data.list || []
|
||||
total.value = res.count || customerList.value.length
|
||||
} catch (error) {
|
||||
ElMessage.error('获取客户列表失败:' + error.message)
|
||||
} finally {
|
||||
|
|
@ -446,10 +363,10 @@ const generateMockData = () => {
|
|||
customerCode: 'C' + String(i).padStart(3, '0'),
|
||||
customerName: (customerTypeNames[customerType] || '客户') + (i <= 6 ? String.fromCharCode(64 + i) : String(i)),
|
||||
customerType: customerType,
|
||||
contact: surnames[Math.floor(Math.random() * surnames.length)] + names[Math.floor(Math.random() * names.length)],
|
||||
phone: '139' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0'),
|
||||
contactPerson: surnames[Math.floor(Math.random() * surnames.length)] + names[Math.floor(Math.random() * names.length)],
|
||||
mobilePhone: '139' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0'),
|
||||
email: `customer${i}@example.com`,
|
||||
address: city + district + 'xxx路xxx号',
|
||||
detailAddress: city + district + 'xxx路xxx号',
|
||||
taxNumber: '91140000' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0') + String.fromCharCode(65 + Math.floor(Math.random() * 26)),
|
||||
bankName: banks[Math.floor(Math.random() * banks.length)],
|
||||
bankAccount: '622' + String(Math.floor(Math.random() * 10000000000000000)).padStart(16, '0'),
|
||||
|
|
@ -465,7 +382,7 @@ const generateMockData = () => {
|
|||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNum = 1
|
||||
queryParams.pageIndex = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
|
|
@ -510,17 +427,17 @@ const handleEdit = (row) => {
|
|||
customerCode: row.customerCode,
|
||||
customerName: row.customerName,
|
||||
customerType: row.customerType,
|
||||
contact: row.contact,
|
||||
phone: row.phone,
|
||||
contactPerson: row.contactPerson,
|
||||
mobilePhone: row.mobilePhone,
|
||||
email: row.email || '',
|
||||
address: row.address,
|
||||
detailAddress: row.detailAddress,
|
||||
taxNumber: row.taxNumber || '',
|
||||
bankName: row.bankName || '',
|
||||
bankAccount: row.bankAccount || '',
|
||||
qualificationInfo: row.qualificationInfo || [],
|
||||
status: row.status
|
||||
})
|
||||
|
||||
|
||||
// 设置文件列表
|
||||
if (row.qualificationInfo && row.qualificationInfo.length > 0) {
|
||||
fileList.value = row.qualificationInfo.map(file => ({
|
||||
|
|
@ -530,21 +447,25 @@ const handleEdit = (row) => {
|
|||
} else {
|
||||
fileList.value = []
|
||||
}
|
||||
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const Ids = (row.id && [row.id])
|
||||
ElMessageBox.confirm('确定要删除此客户吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const customers = JSON.parse(localStorage.getItem('mock_customers') || '[]')
|
||||
const filtered = customers.filter(c => c.id != row.id)
|
||||
localStorage.setItem('mock_customers', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
}).then(async () => {
|
||||
try {
|
||||
// 看你后端怎么约定参数,比如传 id 或 id 数组
|
||||
await delCustomer({ ids: Ids })
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + error.message)
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
|
|
@ -554,15 +475,15 @@ const resetForm = () => {
|
|||
customerCode: '',
|
||||
customerName: '',
|
||||
customerType: '',
|
||||
contact: '',
|
||||
phone: '',
|
||||
contactPerson: '',
|
||||
mobilePhone: '',
|
||||
email: '',
|
||||
address: '',
|
||||
detailAddress: '',
|
||||
taxNumber: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
qualificationInfo: [],
|
||||
status: 1
|
||||
status: '正常'
|
||||
})
|
||||
fileList.value = []
|
||||
customerFormRef.value?.clearValidate()
|
||||
|
|
@ -577,7 +498,7 @@ const handleFileChange = (file, fileList) => {
|
|||
uploadRef.value?.handleRemove(file)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 读取文件并转换为 base64
|
||||
if (file.raw) {
|
||||
const reader = new FileReader()
|
||||
|
|
@ -589,14 +510,14 @@ const handleFileChange = (file, fileList) => {
|
|||
} else if (fileType.includes('image')) {
|
||||
type = 'image'
|
||||
}
|
||||
|
||||
|
||||
const newFile = {
|
||||
name: file.name,
|
||||
url: e.target.result,
|
||||
type: type,
|
||||
size: file.raw.size
|
||||
}
|
||||
|
||||
|
||||
// 检查是否已存在同名文件
|
||||
const exists = customerForm.qualificationInfo.find(f => f.name === file.name)
|
||||
if (!exists) {
|
||||
|
|
@ -634,82 +555,20 @@ const handleDownloadQualificationFile = (file) => {
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (!customerFormRef.value) return
|
||||
|
||||
await customerFormRef.value.validate((valid) => {
|
||||
|
||||
await customerFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_customers') || '[]')
|
||||
const now = new Date().toISOString()
|
||||
|
||||
let res
|
||||
if (isEdit.value) {
|
||||
// 编辑
|
||||
const index = mockData.findIndex(item => item.id === customerForm.id)
|
||||
if (index !== -1) {
|
||||
// 检查客户ID是否重复(排除当前编辑的项)
|
||||
const codeExists = mockData.find(item =>
|
||||
item.id !== customerForm.id &&
|
||||
item.customerCode === customerForm.customerCode
|
||||
)
|
||||
if (codeExists) {
|
||||
ElMessage.warning('客户ID已存在')
|
||||
submitLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
mockData[index] = {
|
||||
...mockData[index],
|
||||
customerCode: customerForm.customerCode,
|
||||
customerName: customerForm.customerName,
|
||||
customerType: customerForm.customerType,
|
||||
contact: customerForm.contact,
|
||||
phone: customerForm.phone,
|
||||
email: customerForm.email,
|
||||
address: customerForm.address,
|
||||
taxNumber: customerForm.taxNumber,
|
||||
bankName: customerForm.bankName,
|
||||
bankAccount: customerForm.bankAccount,
|
||||
qualificationInfo: customerForm.qualificationInfo,
|
||||
status: customerForm.status,
|
||||
updateTime: now
|
||||
}
|
||||
}
|
||||
res = await updateCustomer(customerForm)
|
||||
} else {
|
||||
// 新增
|
||||
// 确保客户ID是生成的(防止手动修改)
|
||||
if (!customerForm.customerCode || !customerForm.customerCode.match(/^C\d{3}$/)) {
|
||||
customerForm.customerCode = generateCustomerCode()
|
||||
}
|
||||
|
||||
// 检查客户ID是否重复(虽然自动生成,但以防万一)
|
||||
const codeExists = mockData.find(item => item.customerCode === customerForm.customerCode)
|
||||
if (codeExists) {
|
||||
// 如果重复,重新生成
|
||||
customerForm.customerCode = generateCustomerCode()
|
||||
}
|
||||
|
||||
const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1
|
||||
mockData.push({
|
||||
id: newId,
|
||||
customerCode: customerForm.customerCode,
|
||||
customerName: customerForm.customerName,
|
||||
customerType: customerForm.customerType,
|
||||
contact: customerForm.contact,
|
||||
phone: customerForm.phone,
|
||||
email: customerForm.email,
|
||||
address: customerForm.address,
|
||||
creditCode: customerForm.creditCode,
|
||||
bankName: customerForm.bankName,
|
||||
bankAccount: customerForm.bankAccount,
|
||||
qualificationInfo: customerForm.qualificationInfo,
|
||||
status: customerForm.status,
|
||||
createTime: now,
|
||||
updateTime: now
|
||||
})
|
||||
res = await addCustomer(customerForm)
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_customers', JSON.stringify(mockData))
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
|
|
|
|||
|
|
@ -1,29 +1,59 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<div class="filter-toolbar">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="价格类型" prop="indexType">
|
||||
<el-select
|
||||
v-model="queryParams.indexType"
|
||||
placeholder="全部"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="CCI价" value="CCI价" />
|
||||
<el-option label="神华外购石炭价" value="神华外购石炭价" />
|
||||
<el-option label="神华外购价" value="神华外购价" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" @click="handleAdd">新增价格配置</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="priceList" border style="width: 100%; margin-top: 20px;">
|
||||
<el-table-column prop="name" label="价格类型" />
|
||||
<el-table-column prop="type" label="类型" width="150">
|
||||
<!-- <el-table-column prop="name" label="价格类型" /> -->
|
||||
<el-table-column prop="indexType" label="价格类型" width="150">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.type">{{ scope.row.type }}</span>
|
||||
<span v-if="scope.row.indexType">{{ scope.row.indexType }}</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="heatValue" label="热值" />
|
||||
<el-table-column prop="price" label="价格" align="right">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.price !== null && scope.row.price !== undefined">{{ formatMoney(scope.row.price) }}</span>
|
||||
<span v-if="scope.row.price !== null && scope.row.price !== undefined">{{ formatMoney(scope.row.price)
|
||||
}}</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="berthDayCCI" label="靠泊日CCI" align="right">
|
||||
<el-table-column prop="publishDate" label="发布日期">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.berthDayCCI !== null && scope.row.berthDayCCI !== undefined">{{ formatMoney(scope.row.berthDayCCI) }}</span>
|
||||
<span>{{ formatDate(scope.row.publishDate) }}</span>
|
||||
</template>
|
||||
</el-table-column> <!-- <el-table-column prop="berthDayCCI" label="靠泊日CCI" align="right">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.berthDayCCI !== null && scope.row.berthDayCCI !== undefined">{{
|
||||
formatMoney(scope.row.berthDayCCI) }}</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="weeklyCCIAvg" label="靠泊日当周CCI平均价" align="right">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.weeklyCCIAvg !== null && scope.row.weeklyCCIAvg !== undefined">{{ formatMoney(scope.row.weeklyCCIAvg) }}</span>
|
||||
<span v-if="scope.row.weeklyCCIAvg !== null && scope.row.weeklyCCIAvg !== undefined">{{
|
||||
formatMoney(scope.row.weeklyCCIAvg) }}</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -35,153 +65,79 @@
|
|||
</el-table-column>
|
||||
<el-table-column prop="downRange" label="下浮范围(%)" width="150" align="right">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.downRange !== null && scope.row.downRange !== undefined">{{ scope.row.downRange }}%</span>
|
||||
<span v-if="scope.row.downRange !== null && scope.row.downRange !== undefined">{{ scope.row.downRange
|
||||
}}%</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" fixed="right" align="center">
|
||||
</el-table-column> -->
|
||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 编辑价格对话框 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="700px"
|
||||
:close-on-click-modal="false"
|
||||
@close="resetForm"
|
||||
>
|
||||
<el-form
|
||||
ref="priceFormRef"
|
||||
:model="priceForm"
|
||||
:rules="dynamicRules"
|
||||
label-width="160px"
|
||||
>
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px" :close-on-click-modal="false"
|
||||
@close="resetForm">
|
||||
<el-form ref="priceFormRef" :model="priceForm" :rules="dynamicRules" label-width="160px">
|
||||
<el-form-item label="价格类型">
|
||||
<el-input v-model="priceForm.name" disabled />
|
||||
<!-- <el-input v-model="priceForm.name" disabled /> -->
|
||||
<el-select v-model="priceForm.indexType" placeholder="请选择价格类型" style="width: 100%">
|
||||
<el-option label="CCI价" value="CCI价" />
|
||||
<el-option label="神华外购石炭价" value="神华外购石炭价" />
|
||||
<el-option label="神华外购价" value="神华外购价" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- CCI 类型 -->
|
||||
<template v-if="priceForm.priceType === 'cci'">
|
||||
<el-form-item label="靠泊日CCI" prop="berthDayCCI">
|
||||
<el-input-number
|
||||
v-model="priceForm.berthDayCCI"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入靠泊日CCI"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="靠泊日当周CCI平均价" prop="weeklyCCIAvg">
|
||||
<el-input-number
|
||||
v-model="priceForm.weeklyCCIAvg"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入靠泊日当周CCI平均价"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="上浮范围(%)" prop="upRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.upRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入上浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="下浮范围(%)" prop="downRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.downRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入下浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="热值" prop="heatValue">
|
||||
<el-input-number v-model="priceForm.heatValue" :min="0" :precision="2" placeholder="请输入热值"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="发布日期" prop="publishDate">
|
||||
<el-date-picker v-model="priceForm.publishDate" type="date" placeholder="请选择发布日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number v-model="priceForm.price" :min="0" :precision="2" placeholder="请输入价格" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input v-model="priceForm.unit" disabled style="width: 100%" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 神华外购石炭价 -->
|
||||
<template v-else-if="priceForm.priceType === 'shenhua_stone'">
|
||||
<el-form-item label="类型">
|
||||
<el-input v-model="priceForm.type" disabled />
|
||||
</el-form-item>
|
||||
<!-- 神华外购石炭价价 -->
|
||||
<!-- <template v-else-if="priceForm.indexType === '神华外购石炭价'">
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number
|
||||
v-model="priceForm.price"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入价格"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.price" :min="0" :precision="2" placeholder="请输入价格"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上浮范围(%)" prop="upRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.upRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入上浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.upRange" :min="0" :max="100" :precision="2" placeholder="请输入上浮范围"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="下浮范围(%)" prop="downRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.downRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入下浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.downRange" :min="0" :max="100" :precision="2" placeholder="请输入下浮范围"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template> -->
|
||||
|
||||
<!-- 神华外购价 -->
|
||||
<template v-else-if="priceForm.priceType === 'shenhua_purchase'">
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-input
|
||||
v-model="priceForm.type"
|
||||
placeholder="请输入类型"
|
||||
maxlength="50"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 神华外购价价 -->
|
||||
<!-- <template v-else-if="priceForm.indexType === '神华外购价'">
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number
|
||||
v-model="priceForm.price"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入价格"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.price" :min="0" :precision="2" placeholder="请输入价格"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上浮范围(%)" prop="upRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.upRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入上浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.upRange" :min="0" :max="100" :precision="2" placeholder="请输入上浮范围"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="下浮范围(%)" prop="downRange">
|
||||
<el-input-number
|
||||
v-model="priceForm.downRange"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入下浮范围"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="priceForm.downRange" :min="0" :max="100" :precision="2" placeholder="请输入下浮范围"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
|
|
@ -197,28 +153,45 @@
|
|||
|
||||
<script setup name="Price">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { formatMoney } from '@/utils/business'
|
||||
import { listPriceIndex, addPriceIndex, updatePriceIndex, delPriceIndex } from '@/api/base/price'
|
||||
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const priceList = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
const priceFormRef = ref(null)
|
||||
const isEdit = ref(false)
|
||||
|
||||
// 查询参数
|
||||
const queryParams = reactive({
|
||||
indexType: ''
|
||||
})
|
||||
|
||||
const priceForm = reactive({
|
||||
id: null,
|
||||
priceType: '',
|
||||
indexType: '',
|
||||
name: '',
|
||||
type: '',
|
||||
heatValue: null,
|
||||
publishDate: null,
|
||||
price: null,
|
||||
berthDayCCI: null,
|
||||
weeklyCCIAvg: null,
|
||||
upRange: null,
|
||||
downRange: null
|
||||
downRange: null,
|
||||
unit: '吨'
|
||||
})
|
||||
|
||||
const baseRules = {
|
||||
heatValue: [
|
||||
{ required: true, message: '请输入热值', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '热值必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
publishDate: [
|
||||
{ required: true, message: '请选择发布日期', trigger: 'change' }
|
||||
],
|
||||
berthDayCCI: [
|
||||
{ required: true, message: '请输入靠泊日CCI', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: 'CCI必须大于等于0', trigger: 'blur' }
|
||||
|
|
@ -246,42 +219,39 @@ const baseRules = {
|
|||
|
||||
const dynamicRules = computed(() => {
|
||||
const rules = {}
|
||||
|
||||
if (priceForm.priceType === 'cci') {
|
||||
// CCI类型:验证靠泊日CCI、靠泊日当周CCI平均价、上浮下浮范围
|
||||
rules.berthDayCCI = baseRules.berthDayCCI
|
||||
rules.weeklyCCIAvg = baseRules.weeklyCCIAvg
|
||||
rules.upRange = baseRules.upRange
|
||||
rules.downRange = baseRules.downRange
|
||||
} else if (priceForm.priceType === 'shenhua_stone') {
|
||||
// 神华外购石炭价:验证价格、上浮下浮范围
|
||||
|
||||
if (priceForm.indexType === 'CCI价') {
|
||||
// CCI类型:验证类型、热值、发布日期、价格
|
||||
rules.type = baseRules.type
|
||||
rules.heatValue = baseRules.heatValue
|
||||
rules.publishDate = baseRules.publishDate
|
||||
rules.price = baseRules.price
|
||||
} else if (priceForm.indexType === 'shenhua_stone') {
|
||||
// 神华外购石炭价价:验证价格、上浮下浮范围
|
||||
rules.price = baseRules.price
|
||||
rules.upRange = baseRules.upRange
|
||||
rules.downRange = baseRules.downRange
|
||||
} else if (priceForm.priceType === 'shenhua_purchase') {
|
||||
// 神华外购价:验证类型、价格、上浮下浮范围
|
||||
} else if (priceForm.indexType === 'shenhua_purchase') {
|
||||
// 神华外购价价:验证类型、价格、上浮下浮范围
|
||||
rules.type = baseRules.type
|
||||
rules.price = baseRules.price
|
||||
rules.upRange = baseRules.upRange
|
||||
rules.downRange = baseRules.downRange
|
||||
}
|
||||
|
||||
|
||||
return rules
|
||||
})
|
||||
|
||||
const dialogTitle = computed(() => '编辑价格配置')
|
||||
const dialogTitle = computed(() => (isEdit.value ? '编辑价格配置' : '新增价格配置'))
|
||||
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_price_configs') || '[]')
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateMockData()
|
||||
return
|
||||
}
|
||||
|
||||
priceList.value = mockData
|
||||
const res = await listPriceIndex({
|
||||
indexType: queryParams.indexType || undefined
|
||||
})
|
||||
// 根据后端返回结构微调这一行
|
||||
priceList.value = (res && (res.data?.list || res.data || res.list)) || []
|
||||
} catch (error) {
|
||||
ElMessage.error('获取价格配置失败:' + error.message)
|
||||
} finally {
|
||||
|
|
@ -289,56 +259,35 @@ const getList = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const generateMockData = () => {
|
||||
setTimeout(() => {
|
||||
const defaultConfigs = [
|
||||
{
|
||||
id: 1,
|
||||
priceType: 'cci',
|
||||
name: 'CCI(煤炭价格指数网)',
|
||||
type: null,
|
||||
price: null,
|
||||
berthDayCCI: 550.00,
|
||||
weeklyCCIAvg: 545.50,
|
||||
upRange: 5.00,
|
||||
downRange: 3.00
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
priceType: 'shenhua_stone',
|
||||
name: '神华外购石炭价',
|
||||
type: '石炭',
|
||||
price: 570.00,
|
||||
berthDayCCI: null,
|
||||
weeklyCCIAvg: null,
|
||||
upRange: 8.00,
|
||||
downRange: 5.00
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
priceType: 'shenhua_purchase',
|
||||
name: '神华外购价',
|
||||
type: '标准煤',
|
||||
price: 580.00,
|
||||
berthDayCCI: null,
|
||||
weeklyCCIAvg: null,
|
||||
upRange: 10.00,
|
||||
downRange: 6.00
|
||||
}
|
||||
]
|
||||
|
||||
localStorage.setItem('mock_price_configs', JSON.stringify(defaultConfigs))
|
||||
priceList.value = defaultConfigs
|
||||
loading.value = false
|
||||
}, 10)
|
||||
// 查询
|
||||
const handleQuery = () => {
|
||||
getList()
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
queryParams.indexType = ''
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
resetForm()
|
||||
// 默认新增一条 CCI 配置,可按需修改
|
||||
priceForm.indexType = 'CCI价'
|
||||
priceForm.name = 'CCI(煤炭价格指数网)'
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleEdit = (row) => {
|
||||
isEdit.value = true
|
||||
Object.assign(priceForm, {
|
||||
id: row.id,
|
||||
priceType: row.priceType,
|
||||
indexType: row.indexType,
|
||||
name: row.name,
|
||||
type: row.priceType === 'shenhua_stone' ? '石炭' : (row.type || ''),
|
||||
type: row.indexType === 'shenhua_stone' ? '石炭' : (row.type || ''),
|
||||
heatValue: row.heatValue,
|
||||
publishDate: row.publishDate,
|
||||
price: row.price,
|
||||
berthDayCCI: row.berthDayCCI,
|
||||
weeklyCCIAvg: row.weeklyCCIAvg,
|
||||
|
|
@ -348,12 +297,33 @@ const handleEdit = (row) => {
|
|||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const ids = row.id ? [row.id] : []
|
||||
if (!ids.length) return
|
||||
|
||||
ElMessageBox.confirm('确定要删除该价格配置吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delPriceIndex({ ids })
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + error.message)
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
Object.assign(priceForm, {
|
||||
id: null,
|
||||
priceType: '',
|
||||
indexType: '',
|
||||
name: '',
|
||||
type: '',
|
||||
heatValue: null,
|
||||
publishDate: null,
|
||||
price: null,
|
||||
berthDayCCI: null,
|
||||
weeklyCCIAvg: null,
|
||||
|
|
@ -365,30 +335,18 @@ const resetForm = () => {
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (!priceFormRef.value) return
|
||||
|
||||
await priceFormRef.value.validate((valid) => {
|
||||
|
||||
await priceFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_price_configs') || '[]')
|
||||
const index = mockData.findIndex(item => item.id === priceForm.id)
|
||||
|
||||
if (index !== -1) {
|
||||
mockData[index] = {
|
||||
...mockData[index],
|
||||
type: priceForm.priceType === 'shenhua_stone' ? '石炭' : (priceForm.type || null),
|
||||
price: priceForm.price,
|
||||
berthDayCCI: priceForm.berthDayCCI,
|
||||
weeklyCCIAvg: priceForm.weeklyCCIAvg,
|
||||
upRange: priceForm.upRange,
|
||||
downRange: priceForm.downRange,
|
||||
updateTime: new Date().toISOString()
|
||||
}
|
||||
if (isEdit.value) {
|
||||
await updatePriceIndex(priceForm)
|
||||
} else {
|
||||
await addPriceIndex(priceForm)
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_price_configs', JSON.stringify(mockData))
|
||||
ElMessage.success('编辑成功')
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
|
|
@ -398,6 +356,15 @@ const handleSubmit = async () => {
|
|||
}
|
||||
})
|
||||
}
|
||||
const formatDate = (value) => {
|
||||
if (!value) return '-'
|
||||
const d = new Date(value)
|
||||
if (Number.isNaN(d.getTime())) return value
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
|
|
@ -419,4 +386,3 @@ onMounted(() => getList())
|
|||
padding-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,19 +3,18 @@
|
|||
<el-card>
|
||||
<div class="filter-toolbar">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="商品类别" prop="category">
|
||||
<el-select v-model="queryParams.category" placeholder="全部" clearable style="width: 150px">
|
||||
<el-form-item label="商品类别" prop="categoryId">
|
||||
<el-select v-model="queryParams.categoryId" placeholder="全部" clearable style="width: 150px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="动力煤" value="动力煤" />
|
||||
<el-option label="焦煤" value="焦煤" />
|
||||
<el-option label="无烟煤" value="无烟煤" />
|
||||
<el-option v-for="category in categoryOptions" :key="category.id" :label="category.categoryName"
|
||||
:value="category.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 150px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="启用" value="1" />
|
||||
<el-option label="禁用" value="0" />
|
||||
<el-option label="启用" value="启用" />
|
||||
<el-option label="禁用" value="禁用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
|
@ -27,46 +26,45 @@
|
|||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="productList" border style="width: 100%; margin-top: 20px;">
|
||||
<el-table-column prop="productCode" label="商品编码" width="120" />
|
||||
<el-table-column prop="productCode" label="商品编码" width="200" />
|
||||
<el-table-column prop="productName" label="商品名称" width="200" />
|
||||
<el-table-column prop="specification" label="规格型号" width="150" />
|
||||
<el-table-column prop="categoryName" label="商品类别" width="120" />
|
||||
<el-table-column prop="purchaseUnit" label="采购单位" width="120" />
|
||||
<el-table-column prop="salesUnit" label="销售单位" width="120" />
|
||||
<el-table-column prop="stockUnit" label="库存单位" width="120" />
|
||||
<el-table-column prop="defaultCostPrice" label="默认成本价(元/吨)" width="160" align="right">
|
||||
<el-table-column prop="specification" label="规格型号" width="200" />
|
||||
<el-table-column prop="categoryName" label="商品类别" width="200">
|
||||
<template #default="scope">
|
||||
{{ scope.row.categoryName || scope.row.categoryId || scope.row.categoryId || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="计量单位" width="200" />
|
||||
<!-- <el-table-column prop="salesUnit" label="销售单位" width="120" />
|
||||
<el-table-column prop="stockUnit" label="库存单位" width="120" /> -->
|
||||
<!-- <el-table-column prop="defaultCostPrice" label="默认成本价(元/吨)" width="160" align="right">
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.defaultCostPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="defaultSalesPrice" label="默认销售价(元/吨)" width="160" align="right">
|
||||
<template #default="scope">
|
||||
</el-table-column>
|
||||
<el-table-column prop="defaultSalesPrice" label="默认销售价(元/吨)" width="160" align="right">
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.defaultSalesPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="calorificValue" label="热值(kcal/kg)" width="150" align="right" />
|
||||
<el-table-column prop="qualityReport" label="质检报告" width="150">
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="standardHeatValue" label="热值(kcal/kg)" width="200" />
|
||||
<!-- <el-table-column prop="qualityReport" label="质检报告" width="">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.qualityReport"
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleViewReport(scope.row)"
|
||||
>
|
||||
<el-button v-if="scope.row.qualityReport" link type="primary" size="small"
|
||||
@click="handleViewReport(scope.row)">
|
||||
查看报告
|
||||
</el-button>
|
||||
<span v-else style="color: #999;">暂无报告</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="status" label="状态" width="200">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'">
|
||||
{{ scope.row.status == 1 ? '启用' : '禁用' }}
|
||||
<el-tag :type="scope.row.status == '启用' ? 'success' : 'danger'">
|
||||
{{ scope.row.status == '启用' ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<el-table-column label="操作" width="" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
|
||||
|
|
@ -74,162 +72,91 @@
|
|||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageIndex"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑商品对话框 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
@close="resetForm"
|
||||
>
|
||||
<el-form
|
||||
ref="productFormRef"
|
||||
:model="productForm"
|
||||
:rules="productFormRules"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="800px" :close-on-click-modal="false"
|
||||
@close="resetForm">
|
||||
<el-form ref="productFormRef" :model="productForm" :rules="productFormRules" label-width="140px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品编码" prop="productCode">
|
||||
<el-input
|
||||
v-model="productForm.productCode"
|
||||
placeholder="请输入商品编码"
|
||||
:disabled="isEdit"
|
||||
maxlength="30"
|
||||
/>
|
||||
<el-input v-model="productForm.productCode" placeholder="请输入商品编码" :disabled="isEdit" maxlength="30" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品名称" prop="productName">
|
||||
<el-input
|
||||
v-model="productForm.productName"
|
||||
placeholder="请输入商品名称"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="productForm.productName" placeholder="请输入商品名称" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规格型号" prop="specification">
|
||||
<el-input
|
||||
v-model="productForm.specification"
|
||||
placeholder="请输入规格型号"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="productForm.specification" placeholder="请输入规格型号" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品类别" prop="categoryName">
|
||||
<el-select
|
||||
v-model="productForm.categoryName"
|
||||
placeholder="请选择商品类别"
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="category in categoryOptions"
|
||||
:key="category"
|
||||
:label="category"
|
||||
:value="category"
|
||||
/>
|
||||
<el-form-item label="商品类别" prop="categoryId">
|
||||
<el-select v-model="productForm.categoryId" placeholder="请选择商品类别" filterable style="width: 100%">
|
||||
<el-option v-for="category in categoryOptions" :key="category.id" :label="category.categoryName"
|
||||
:value="category.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="采购单位" prop="purchaseUnit">
|
||||
<el-input
|
||||
v-model="productForm.purchaseUnit"
|
||||
placeholder="请输入采购单位"
|
||||
maxlength="10"
|
||||
/>
|
||||
<el-form-item label="计量单位" prop="unit">
|
||||
<el-input v-model="productForm.purchaseUnit" disabled placeholder="请输入计量单位" maxlength="10" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="销售单位" prop="salesUnit">
|
||||
<el-input
|
||||
v-model="productForm.salesUnit"
|
||||
placeholder="请输入销售单位"
|
||||
maxlength="10"
|
||||
/>
|
||||
<el-input v-model="productForm.salesUnit" placeholder="请输入销售单位" maxlength="10" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="库存单位" prop="stockUnit">
|
||||
<el-input
|
||||
v-model="productForm.stockUnit"
|
||||
placeholder="请输入库存单位"
|
||||
maxlength="10"
|
||||
/>
|
||||
<el-input v-model="productForm.stockUnit" placeholder="请输入库存单位" maxlength="10" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<!-- <el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认成本价(元/吨)" prop="defaultCostPrice">
|
||||
<el-input-number
|
||||
v-model="productForm.defaultCostPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入默认成本价"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="productForm.defaultCostPrice" :min="0" :precision="2" placeholder="请输入默认成本价"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认销售价(元/吨)" prop="defaultSalesPrice">
|
||||
<el-input-number
|
||||
v-model="productForm.defaultSalesPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入默认销售价"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input-number v-model="productForm.defaultSalesPrice" :min="0" :precision="2" placeholder="请输入默认销售价"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row> -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="热值(kcal/kg)" prop="calorificValue">
|
||||
<el-input-number
|
||||
v-model="productForm.calorificValue"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入热值"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-form-item label="热值(kcal/kg)" prop="standardHeatValue">
|
||||
<el-input-number v-model="productForm.standardHeatValue" :min="0" :precision="0" placeholder="请输入热值"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="productForm.status">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
<el-radio :label="'启用'">启用</el-radio>
|
||||
<el-radio :label="'禁用'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="质检报告" prop="qualityReport">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove"
|
||||
:limit="1"
|
||||
accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png"
|
||||
>
|
||||
<!-- <el-form-item label="质检报告" prop="qualityReport">
|
||||
<el-upload ref="uploadRef" :file-list="fileList" :auto-upload="false" :on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove" :limit="1" accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png">
|
||||
<el-button type="primary">选择文件</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
|
|
@ -242,7 +169,7 @@
|
|||
查看当前报告
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
|
|
@ -255,23 +182,12 @@
|
|||
</el-dialog>
|
||||
|
||||
<!-- 查看质检报告对话框 -->
|
||||
<el-dialog
|
||||
v-model="reportDialogVisible"
|
||||
title="质检报告"
|
||||
width="900px"
|
||||
>
|
||||
<el-dialog v-model="reportDialogVisible" title="质检报告" width="900px">
|
||||
<div v-if="currentReport" style="text-align: center;">
|
||||
<iframe
|
||||
v-if="currentReport.type === 'pdf'"
|
||||
:src="currentReport.url"
|
||||
style="width: 100%; height: 600px; border: none;"
|
||||
></iframe>
|
||||
<img
|
||||
v-else-if="currentReport.type === 'image'"
|
||||
:src="currentReport.url"
|
||||
style="max-width: 100%; max-height: 600px;"
|
||||
alt="质检报告"
|
||||
/>
|
||||
<iframe v-if="currentReport.type === 'pdf'" :src="currentReport.url"
|
||||
style="width: 100%; height: 600px; border: none;"></iframe>
|
||||
<img v-else-if="currentReport.type === 'image'" :src="currentReport.url"
|
||||
style="max-width: 100%; max-height: 600px;" alt="质检报告" />
|
||||
<div v-else>
|
||||
<el-button type="primary" @click="handleDownloadReport(currentReport)">
|
||||
下载报告
|
||||
|
|
@ -287,6 +203,8 @@ import { ref, reactive, computed, onMounted } from 'vue'
|
|||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { formatMoney } from '@/utils/business'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { listproductCategory } from '@/api/base/category'
|
||||
import { listproduct, addProduct, updateProduct, delProduct } from '@/api/base/product'
|
||||
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
|
|
@ -301,28 +219,33 @@ const fileList = ref([])
|
|||
const currentReport = ref(null)
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
category: '',
|
||||
status: ''
|
||||
})
|
||||
|
||||
const categoryOptions = ref(['动力煤', '焦煤', '无烟煤', '褐煤', '瘦煤', '肥煤', '气煤', '1/3焦煤', '贫煤', '长焰煤', '不粘煤', '弱粘煤', '1/2中粘煤', '中粘煤', '强粘煤', '特强粘煤', '贫瘦煤', '瘦焦煤', '主焦煤', '其他'])
|
||||
const categoryOptions = ref([])
|
||||
const categoryMap = computed(() => {
|
||||
const map = {}
|
||||
categoryOptions.value.forEach((item) => {
|
||||
map[item.id] = item.categoryName
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
const productForm = reactive({
|
||||
id: null,
|
||||
productCode: '',
|
||||
productName: '',
|
||||
specification: '',
|
||||
categoryName: '',
|
||||
purchaseUnit: '吨',
|
||||
salesUnit: '吨',
|
||||
stockUnit: '吨',
|
||||
categoryId: '',
|
||||
unit: '吨',
|
||||
defaultCostPrice: 0,
|
||||
defaultSalesPrice: 0,
|
||||
calorificValue: 0,
|
||||
standardHeatValue: 0,
|
||||
qualityReport: null,
|
||||
status: 1
|
||||
status: '启用'
|
||||
})
|
||||
|
||||
const productFormRules = {
|
||||
|
|
@ -334,13 +257,13 @@ const productFormRules = {
|
|||
{ required: true, message: '请输入商品名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
categoryName: [
|
||||
categoryId: [
|
||||
{ required: true, message: '请选择商品类别', trigger: 'change' }
|
||||
],
|
||||
purchaseUnit: [
|
||||
{ required: true, message: '请输入采购单位', trigger: 'blur' }
|
||||
],
|
||||
salesUnit: [
|
||||
unit: [
|
||||
{ required: true, message: '请输入销售单位', trigger: 'blur' }
|
||||
],
|
||||
stockUnit: [
|
||||
|
|
@ -354,7 +277,7 @@ const productFormRules = {
|
|||
{ required: true, message: '请输入默认销售价', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '销售价必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
calorificValue: [
|
||||
standardHeatValue: [
|
||||
{ required: true, message: '请输入热值', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '热值必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
|
|
@ -365,25 +288,37 @@ const productFormRules = {
|
|||
|
||||
const dialogTitle = computed(() => isEdit.value ? '编辑商品' : '新增商品')
|
||||
|
||||
// 获取商品类别列表
|
||||
const appendCategoryName = (list = []) => {
|
||||
return list.map((item) => ({
|
||||
...item,
|
||||
categoryName: categoryMap.value[item.categoryId] || categoryMap.value[item.categoryId] || item.categoryName || ''
|
||||
}))
|
||||
}
|
||||
|
||||
const getCategoryList = async () => {
|
||||
try {
|
||||
const response = await listproductCategory({ pageIndex: 1, pageSize: 1000 })
|
||||
categoryOptions.value = response.data?.list || []
|
||||
// 类目更新后同步已有列表的类目名称
|
||||
productList.value = appendCategoryName(productList.value)
|
||||
// categoryOptions.value = categories.map(item => item.categoryName).filter(Boolean)
|
||||
console.log(categoryOptions.value, ' categoryOptions.value ');
|
||||
|
||||
} catch (error) {
|
||||
ElMessage.error('获取商品类别列表失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_products') || '[]')
|
||||
let filtered = mockData.filter(item => {
|
||||
if (queryParams.category && item.categoryName !== queryParams.category) return false
|
||||
if (queryParams.status !== '' && item.status != queryParams.status) return false
|
||||
return true
|
||||
})
|
||||
const start = (queryParams.pageNum - 1) * queryParams.pageSize
|
||||
const end = start + queryParams.pageSize
|
||||
productList.value = filtered.slice(start, end)
|
||||
total.value = filtered.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateMockData()
|
||||
}
|
||||
const response = await listproduct(queryParams)
|
||||
const list = response.data?.list || response.rows || []
|
||||
productList.value = appendCategoryName(list)
|
||||
total.value = response.data?.count || response.total || 0
|
||||
} catch (error) {
|
||||
ElMessage.error('获取商品列表失败:' + error.message)
|
||||
ElMessage.error('获取商品列表失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
|
@ -399,7 +334,7 @@ const generateMockData = () => {
|
|||
for (let i = 1; i <= 20; i++) {
|
||||
const costPrice = Math.floor(Math.random() * 300) + 400
|
||||
const salesPrice = costPrice + Math.floor(Math.random() * 100) + 50
|
||||
const calorificValue = Math.floor(Math.random() * 2000) + 4000
|
||||
const standardHeatValue = Math.floor(Math.random() * 2000) + 4000
|
||||
newProducts.push({
|
||||
id: i,
|
||||
productCode: 'PM' + String(i).padStart(3, '0'),
|
||||
|
|
@ -411,7 +346,7 @@ const generateMockData = () => {
|
|||
stockUnit: '吨',
|
||||
defaultCostPrice: costPrice,
|
||||
defaultSalesPrice: salesPrice,
|
||||
calorificValue: calorificValue,
|
||||
standardHeatValue: standardHeatValue,
|
||||
qualityReport: i <= 5 ? { name: `质检报告_${productNames[i - 1]}.pdf`, url: '#', type: 'pdf' } : null,
|
||||
status: Math.random() > 0.1 ? 1 : 0,
|
||||
createTime: new Date(now - i * 30 * 86400000).toISOString(),
|
||||
|
|
@ -424,12 +359,12 @@ const generateMockData = () => {
|
|||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNum = 1
|
||||
queryParams.pageIndex = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
const resetQuery = () => {
|
||||
queryParams.category = ''
|
||||
queryParams.categoryId = ''
|
||||
queryParams.status = ''
|
||||
handleQuery()
|
||||
}
|
||||
|
|
@ -447,17 +382,17 @@ const handleEdit = (row) => {
|
|||
productCode: row.productCode,
|
||||
productName: row.productName,
|
||||
specification: row.specification || '',
|
||||
categoryName: row.categoryName,
|
||||
categoryId: row.categoryId,
|
||||
purchaseUnit: row.purchaseUnit,
|
||||
salesUnit: row.salesUnit,
|
||||
stockUnit: row.stockUnit,
|
||||
defaultCostPrice: row.defaultCostPrice,
|
||||
defaultSalesPrice: row.defaultSalesPrice,
|
||||
calorificValue: row.calorificValue || 0,
|
||||
standardHeatValue: row.standardHeatValue || 0,
|
||||
qualityReport: row.qualityReport,
|
||||
status: row.status
|
||||
})
|
||||
|
||||
|
||||
// 设置文件列表
|
||||
if (row.qualityReport) {
|
||||
fileList.value = [{
|
||||
|
|
@ -467,22 +402,25 @@ const handleEdit = (row) => {
|
|||
} else {
|
||||
fileList.value = []
|
||||
}
|
||||
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const Ids = (row.id && [row.id])
|
||||
ElMessageBox.confirm('确定要删除此商品吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const products = JSON.parse(localStorage.getItem('mock_products') || '[]')
|
||||
const filtered = products.filter(p => p.id != row.id)
|
||||
localStorage.setItem('mock_products', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
}).catch(() => {})
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delProduct({ ids: Ids })
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
|
|
@ -497,9 +435,9 @@ const resetForm = () => {
|
|||
stockUnit: '吨',
|
||||
defaultCostPrice: 0,
|
||||
defaultSalesPrice: 0,
|
||||
calorificValue: 0,
|
||||
standardHeatValue: 0,
|
||||
qualityReport: null,
|
||||
status: 1
|
||||
status: '启用'
|
||||
})
|
||||
fileList.value = []
|
||||
productFormRef.value?.clearValidate()
|
||||
|
|
@ -514,7 +452,7 @@ const handleFileChange = (file) => {
|
|||
uploadRef.value?.handleRemove(file)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 读取文件并转换为 base64 或保存文件信息
|
||||
if (file.raw) {
|
||||
const reader = new FileReader()
|
||||
|
|
@ -526,7 +464,7 @@ const handleFileChange = (file) => {
|
|||
} else if (fileType.includes('image')) {
|
||||
type = 'image'
|
||||
}
|
||||
|
||||
|
||||
productForm.qualityReport = {
|
||||
name: file.name,
|
||||
url: e.target.result,
|
||||
|
|
@ -565,90 +503,35 @@ const handleDownloadReport = (report) => {
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (!productFormRef.value) return
|
||||
|
||||
await productFormRef.value.validate((valid) => {
|
||||
|
||||
await productFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_products') || '[]')
|
||||
const now = new Date().toISOString()
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑
|
||||
const index = mockData.findIndex(item => item.id === productForm.id)
|
||||
if (index !== -1) {
|
||||
// 检查商品编码是否重复(排除当前编辑的项)
|
||||
const codeExists = mockData.find(item =>
|
||||
item.id !== productForm.id &&
|
||||
item.productCode === productForm.productCode
|
||||
)
|
||||
if (codeExists) {
|
||||
ElMessage.warning('商品编码已存在')
|
||||
submitLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
mockData[index] = {
|
||||
...mockData[index],
|
||||
productCode: productForm.productCode,
|
||||
productName: productForm.productName,
|
||||
specification: productForm.specification,
|
||||
categoryName: productForm.categoryName,
|
||||
purchaseUnit: productForm.purchaseUnit,
|
||||
salesUnit: productForm.salesUnit,
|
||||
stockUnit: productForm.stockUnit,
|
||||
defaultCostPrice: productForm.defaultCostPrice,
|
||||
defaultSalesPrice: productForm.defaultSalesPrice,
|
||||
calorificValue: productForm.calorificValue,
|
||||
qualityReport: productForm.qualityReport,
|
||||
status: productForm.status,
|
||||
updateTime: now
|
||||
}
|
||||
}
|
||||
await updateProduct(productForm)
|
||||
ElMessage.success('编辑成功')
|
||||
} else {
|
||||
// 新增
|
||||
// 检查商品编码是否重复
|
||||
const codeExists = mockData.find(item => item.productCode === productForm.productCode)
|
||||
if (codeExists) {
|
||||
ElMessage.warning('商品编码已存在')
|
||||
submitLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1
|
||||
mockData.push({
|
||||
id: newId,
|
||||
productCode: productForm.productCode,
|
||||
productName: productForm.productName,
|
||||
specification: productForm.specification,
|
||||
categoryName: productForm.categoryName,
|
||||
purchaseUnit: productForm.purchaseUnit,
|
||||
salesUnit: productForm.salesUnit,
|
||||
stockUnit: productForm.stockUnit,
|
||||
defaultCostPrice: productForm.defaultCostPrice,
|
||||
defaultSalesPrice: productForm.defaultSalesPrice,
|
||||
calorificValue: productForm.calorificValue,
|
||||
qualityReport: productForm.qualityReport,
|
||||
status: productForm.status,
|
||||
createTime: now,
|
||||
updateTime: now
|
||||
})
|
||||
await addProduct(productForm)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_products', JSON.stringify(mockData))
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
ElMessage.error('操作失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
onMounted(() => {
|
||||
getCategoryList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@
|
|||
<div class="filter-toolbar">
|
||||
<el-form :model="warehouseQueryParams" ref="warehouseQueryForm" :inline="true">
|
||||
<el-form-item label="仓库名称" prop="warehouseName">
|
||||
<el-input v-model="warehouseQueryParams.warehouseName" placeholder="请输入仓库名称" clearable style="width: 200px" />
|
||||
<el-input v-model="warehouseQueryParams.warehouseName" placeholder="请输入仓库名称" clearable
|
||||
style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="warehouseQueryParams.status" placeholder="全部" clearable style="width: 150px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="启用" value="1" />
|
||||
<el-option label="禁用" value="0" />
|
||||
<el-option label="启用" value="启用" />
|
||||
<el-option label="禁用" value="禁用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
|
@ -27,19 +28,19 @@
|
|||
<el-table v-loading="warehouseLoading" :data="warehouseList" border style="width: 100%">
|
||||
<el-table-column prop="warehouseCode" label="仓库编码" width="150" />
|
||||
<el-table-column prop="warehouseName" label="仓库名称" />
|
||||
<el-table-column prop="address" label="地址" />
|
||||
<el-table-column prop="manager" label="负责人" width="160" />
|
||||
<el-table-column prop="phone" label="联系电话" width="180">
|
||||
<el-table-column prop="detailAddress" label="地址" />
|
||||
<el-table-column prop="contactPerson" label="联系人" width="160" />
|
||||
<el-table-column prop="contactPhone" label="联系电话" width="180">
|
||||
<template #default="scope">
|
||||
{{ scope.row.phone || '-' }}
|
||||
{{ scope.row.contactPhone || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="capacity" label="容量(吨)" width="120" align="right" />
|
||||
<el-table-column prop="currentStock" label="当前库存(吨)" width="150" align="right" />
|
||||
<!-- <el-table-column prop="stockCapacity" label="容量(吨)" width="120" align="right" />
|
||||
<el-table-column prop="stockInventory" label="当前库存(吨)" width="150" align="right" /> -->
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'">
|
||||
{{ scope.row.status == 1 ? '启用' : '禁用' }}
|
||||
<el-tag :type="scope.row.status == '启用' ? 'success' : 'danger'">
|
||||
{{ scope.row.status == '启用' ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -51,21 +52,16 @@
|
|||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="warehouseTotal > 0"
|
||||
:total="warehouseTotal"
|
||||
v-model:page="warehouseQueryParams.pageNum"
|
||||
v-model:limit="warehouseQueryParams.pageSize"
|
||||
@pagination="getWarehouseList"
|
||||
/>
|
||||
<pagination v-show="warehouseTotal > 0" :total="warehouseTotal" v-model:page="warehouseQueryParams.pageIndex"
|
||||
v-model:limit="warehouseQueryParams.pageSize" @pagination="getWarehouseList" />
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 垛位管理 -->
|
||||
<el-tab-pane label="垛位管理" name="stack">
|
||||
<div class="filter-toolbar">
|
||||
<el-form :model="stackQueryParams" ref="stackQueryForm" :inline="true">
|
||||
<el-form-item label="垛位名称" prop="stackName">
|
||||
<el-input v-model="stackQueryParams.stackName" placeholder="请输入垛位名称" clearable style="width: 200px" />
|
||||
<el-form-item label="垛位名称" prop="stockName">
|
||||
<el-input v-model="stackQueryParams.stockName" placeholder="请输入垛位名称" clearable style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleStackQuery">搜索</el-button>
|
||||
|
|
@ -76,17 +72,21 @@
|
|||
</div>
|
||||
|
||||
<el-table v-loading="stackLoading" :data="stackList" border style="width: 100%">
|
||||
<el-table-column prop="stackCode" label="垛位编码" width="150" />
|
||||
<el-table-column prop="stackName" label="垛位名称" width="150" />
|
||||
<el-table-column prop="warehouseName" label="所属仓库" width="150" />
|
||||
<el-table-column prop="capacity" label="容量(吨)" width="120" align="right" />
|
||||
<el-table-column prop="currentStock" label="当前库存(吨)" width="150" align="right" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="180">
|
||||
<el-table-column prop="stockCode" label="垛位编码" width="200" />
|
||||
<el-table-column prop="stockName" label="垛位名称"/>
|
||||
<el-table-column prop="warehouseId" label="所属仓库" width="200">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime) }}
|
||||
{{ scope.row.warehouse.warehouseName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<el-table-column prop="stockCapacity" label="容量(吨)" width="150" align="right" />
|
||||
<el-table-column prop="stockInventory" label="当前库存(吨)" width="200" align="right" />
|
||||
<el-table-column prop="createdAt" label="创建时间" >
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createdAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" size="small" @click="handleStackEdit(scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleStackDelete(scope.row)">删除</el-button>
|
||||
|
|
@ -94,87 +94,53 @@
|
|||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="stackTotal > 0"
|
||||
:total="stackTotal"
|
||||
v-model:page="stackQueryParams.pageNum"
|
||||
v-model:limit="stackQueryParams.pageSize"
|
||||
@pagination="getStackList"
|
||||
/>
|
||||
<pagination v-show="stackTotal > 0" :total="stackTotal" v-model:page="stackQueryParams.pageIndex"
|
||||
v-model:limit="stackQueryParams.pageSize" @pagination="getStackList" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑仓库对话框 -->
|
||||
<el-dialog
|
||||
v-model="warehouseDialogVisible"
|
||||
:title="warehouseDialogTitle"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="warehouseFormRef"
|
||||
:model="warehouseForm"
|
||||
:rules="warehouseFormRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-dialog v-model="warehouseDialogVisible" :title="warehouseDialogTitle" width="600px"
|
||||
:close-on-click-modal="false">
|
||||
<el-form ref="warehouseFormRef" :model="warehouseForm" :rules="warehouseFormRules" label-width="100px">
|
||||
<el-form-item label="仓库编码" prop="warehouseCode">
|
||||
<el-input
|
||||
v-model="warehouseForm.warehouseCode"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
/>
|
||||
<el-input v-model="warehouseForm.warehouseCode" placeholder="系统自动生成" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库名称" prop="warehouseName">
|
||||
<el-input
|
||||
v-model="warehouseForm.warehouseName"
|
||||
placeholder="请输入仓库名称"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-input v-model="warehouseForm.warehouseName" placeholder="请输入仓库名称" maxlength="50" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地址" prop="address">
|
||||
<el-input
|
||||
v-model="warehouseForm.address"
|
||||
placeholder="请输入地址"
|
||||
maxlength="200"
|
||||
/>
|
||||
<el-form-item label="地址" prop="detailAddress">
|
||||
<el-input v-model="warehouseForm.detailAddress" placeholder="请输入地址" maxlength="200" />
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="manager">
|
||||
<el-input
|
||||
v-model="warehouseForm.manager"
|
||||
placeholder="请输入负责人"
|
||||
maxlength="20"
|
||||
/>
|
||||
<el-form-item label="联系人" prop="contactPerson">
|
||||
<el-input v-model="warehouseForm.contactPerson" placeholder="请输入联系人" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input
|
||||
v-model="warehouseForm.phone"
|
||||
placeholder="请输入联系电话"
|
||||
maxlength="20"
|
||||
/>
|
||||
<el-form-item label="联系电话" prop="contactPhone">
|
||||
<el-input v-model="warehouseForm.contactPhone" placeholder="请输入联系电话" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="容量(吨)" prop="capacity">
|
||||
<!-- <el-form-item label="容量(吨)" prop="stockCapacity">
|
||||
<el-input-number
|
||||
v-model="warehouseForm.capacity"
|
||||
v-model="warehouseForm.stockCapacity"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入容量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="当前库存(吨)" prop="currentStock">
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="当前库存(吨)" prop="stockInventory">
|
||||
<el-input-number
|
||||
v-model="warehouseForm.currentStock"
|
||||
v-model="warehouseForm.stockInventory"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入当前库存"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="warehouseForm.status">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
<el-radio :label="'启用'">启用</el-radio>
|
||||
<el-radio :label="'禁用'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
|
@ -189,64 +155,27 @@
|
|||
</el-dialog>
|
||||
|
||||
<!-- 新增/编辑垛位对话框 -->
|
||||
<el-dialog
|
||||
v-model="stackDialogVisible"
|
||||
:title="stackDialogTitle"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="stackFormRef"
|
||||
:model="stackForm"
|
||||
:rules="stackFormRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="垛位编码" prop="stackCode">
|
||||
<el-input
|
||||
v-model="stackForm.stackCode"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
/>
|
||||
<el-dialog v-model="stackDialogVisible" :title="stackDialogTitle" width="600px" :close-on-click-modal="false">
|
||||
<el-form ref="stackFormRef" :model="stackForm" :rules="stackFormRules" label-width="100px">
|
||||
<el-form-item label="垛位编码" prop="stockCode">
|
||||
<el-input v-model="stackForm.stockCode" placeholder="系统自动生成" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="垛位名称" prop="stackName">
|
||||
<el-input
|
||||
v-model="stackForm.stackName"
|
||||
placeholder="请输入垛位名称"
|
||||
maxlength="50"
|
||||
/>
|
||||
<el-form-item label="垛位名称" prop="stockName">
|
||||
<el-input v-model="stackForm.stockName" placeholder="请输入垛位名称" maxlength="50" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属仓库" prop="warehouseName">
|
||||
<el-select
|
||||
v-model="stackForm.warehouseName"
|
||||
placeholder="请选择所属仓库"
|
||||
style="width: 100%"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="warehouse in warehouseOptions"
|
||||
:key="warehouse.warehouseName"
|
||||
:label="warehouse.warehouseName"
|
||||
:value="warehouse.warehouseName"
|
||||
/>
|
||||
<el-form-item label="所属仓库" prop="warehouseId">
|
||||
<el-select v-model="stackForm.warehouseId" placeholder="请选择所属仓库" style="width: 100%" filterable>
|
||||
<el-option v-for="warehouse in warehouseOptions" :key="warehouse.id" :label="warehouse.warehouseName"
|
||||
:value="warehouse.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="容量(吨)" prop="capacity">
|
||||
<el-input-number
|
||||
v-model="stackForm.capacity"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入容量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-form-item label="容量(吨)" prop="stockCapacity">
|
||||
<el-input-number v-model="stackForm.stockCapacity" :min="0" :precision="0" placeholder="请输入容量"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="当前库存(吨)" prop="currentStock">
|
||||
<el-input-number
|
||||
v-model="stackForm.currentStock"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入当前库存"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-form-item label="当前库存(吨)" prop="stockInventory">
|
||||
<el-input-number v-model="stackForm.stockInventory" :min="0" :precision="0" placeholder="请输入当前库存"
|
||||
style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
|
@ -266,6 +195,16 @@ import { ref, reactive, computed, onMounted, watch } from 'vue'
|
|||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import {
|
||||
listWarehouse,
|
||||
addWarehouse,
|
||||
updateWarehouse,
|
||||
delWarehouse,
|
||||
listWarehouseStock,
|
||||
addWarehouseStock,
|
||||
updateWarehouseStock,
|
||||
delWarehouseStock
|
||||
} from '@/api/base/serviceProvider'
|
||||
|
||||
// Tab 管理
|
||||
const activeTab = ref('warehouse')
|
||||
|
|
@ -279,46 +218,55 @@ const warehouseSubmitLoading = ref(false)
|
|||
const warehouseIsEdit = ref(false)
|
||||
const warehouseFormRef = ref(null)
|
||||
|
||||
// 与后端保持一致,使用 pageIndex
|
||||
const warehouseQueryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
warehouseName: '',
|
||||
status: ''
|
||||
})
|
||||
|
||||
const warehouseForm = reactive({
|
||||
id: null,
|
||||
warehouseCode: '',
|
||||
warehouseName: '',
|
||||
address: '',
|
||||
manager: '',
|
||||
phone: '',
|
||||
capacity: null,
|
||||
currentStock: null,
|
||||
status: 1
|
||||
detailAddress: '',
|
||||
contactPerson: '',
|
||||
contactPhone: '',
|
||||
stockCapacity: null,
|
||||
stockInventory: null,
|
||||
status: '启用'
|
||||
})
|
||||
|
||||
// 生成随机仓库编码(前缀 CK + 时间戳后 6 位 + 3 位随机数)
|
||||
const generateWarehouseCode = () => {
|
||||
const prefix = 'CK'
|
||||
const timePart = Date.now().toString().slice(-6)
|
||||
const randomPart = Math.floor(Math.random() * 900 + 100) // 100-999
|
||||
return `${prefix}${timePart}${randomPart}`
|
||||
}
|
||||
|
||||
const warehouseFormRules = {
|
||||
warehouseName: [
|
||||
{ required: true, message: '请输入仓库名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
address: [
|
||||
detailAddress: [
|
||||
{ required: true, message: '请输入地址', trigger: 'blur' },
|
||||
{ max: 200, message: '地址不能超过 200 个字符', trigger: 'blur' }
|
||||
],
|
||||
manager: [
|
||||
{ required: true, message: '请输入负责人', trigger: 'blur' },
|
||||
{ max: 20, message: '负责人姓名不能超过 20 个字符', trigger: 'blur' }
|
||||
contactPerson: [
|
||||
{ required: true, message: '请输入联系人', trigger: 'blur' },
|
||||
{ max: 20, message: '联系人姓名不能超过 20 个字符', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
{ pattern: /^1[3-9]\d{9}$|^$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
contactPhone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||
],
|
||||
capacity: [
|
||||
stockCapacity: [
|
||||
{ required: true, message: '请输入容量', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '容量必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
currentStock: [
|
||||
stockInventory: [
|
||||
{ required: true, message: '请输入当前库存', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '当前库存必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
|
|
@ -332,57 +280,19 @@ const warehouseDialogTitle = computed(() => warehouseIsEdit.value ? '编辑仓
|
|||
const getWarehouseList = async () => {
|
||||
warehouseLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_warehouses') || '[]')
|
||||
let filtered = mockData.filter(item => {
|
||||
if (warehouseQueryParams.warehouseName && !item.warehouseName.includes(warehouseQueryParams.warehouseName)) return false
|
||||
if (warehouseQueryParams.status !== '' && item.status != warehouseQueryParams.status) return false
|
||||
return true
|
||||
})
|
||||
const start = (warehouseQueryParams.pageNum - 1) * warehouseQueryParams.pageSize
|
||||
const end = start + warehouseQueryParams.pageSize
|
||||
warehouseList.value = filtered.slice(start, end)
|
||||
warehouseTotal.value = filtered.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateWarehouseMockData()
|
||||
}
|
||||
const response = await listWarehouse(warehouseQueryParams)
|
||||
const list = response.data?.list || response.rows || []
|
||||
warehouseList.value = list
|
||||
warehouseTotal.value = response.data?.count || response.total || 0
|
||||
} catch (error) {
|
||||
ElMessage.error('获取仓库列表失败:' + error.message)
|
||||
ElMessage.error('获取仓库列表失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
warehouseLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const generateWarehouseMockData = () => {
|
||||
setTimeout(() => {
|
||||
const cities = ['太原市', '大同市', '阳泉市', '长治市', '晋城市', '朔州市', '晋中市', '运城市', '忻州市', '临汾市']
|
||||
const districts = ['xxx区', 'xxx县', 'xxx市']
|
||||
const surnames = ['张', '李', '王', '赵', '刘', '陈', '杨', '黄', '周', '吴']
|
||||
const names = ['三', '四', '五', '六', '七', '明', '强', '伟', '芳', '娜']
|
||||
const newWarehouses = []
|
||||
const now = Date.now()
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
const capacity = Math.floor(Math.random() * 200000) + 50000
|
||||
newWarehouses.push({
|
||||
id: i,
|
||||
warehouseCode: 'WH' + String(i).padStart(3, '0'),
|
||||
warehouseName: '仓库' + i,
|
||||
address: cities[Math.floor(Math.random() * cities.length)] + districts[Math.floor(Math.random() * districts.length)] + 'xxx路xxx号',
|
||||
manager: surnames[Math.floor(Math.random() * surnames.length)] + names[Math.floor(Math.random() * names.length)],
|
||||
phone: '138' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0'),
|
||||
capacity: capacity,
|
||||
currentStock: Math.floor(capacity * (0.3 + Math.random() * 0.4)),
|
||||
status: Math.random() > 0.1 ? 1 : 0,
|
||||
createTime: new Date(now - i * 30 * 86400000).toISOString()
|
||||
})
|
||||
}
|
||||
localStorage.setItem('mock_warehouses', JSON.stringify(newWarehouses))
|
||||
getWarehouseList()
|
||||
}, 10)
|
||||
}
|
||||
|
||||
const handleWarehouseQuery = () => {
|
||||
warehouseQueryParams.pageNum = 1
|
||||
warehouseQueryParams.pageIndex = 1
|
||||
getWarehouseList()
|
||||
}
|
||||
|
||||
|
|
@ -392,19 +302,10 @@ const resetWarehouseQuery = () => {
|
|||
handleWarehouseQuery()
|
||||
}
|
||||
|
||||
const generateWarehouseCode = () => {
|
||||
const warehouses = JSON.parse(localStorage.getItem('mock_warehouses') || '[]')
|
||||
if (warehouses.length === 0) return 'WH001'
|
||||
const codes = warehouses.map(w => w.warehouseCode).filter(code => code.startsWith('WH'))
|
||||
if (codes.length === 0) return 'WH001'
|
||||
const numbers = codes.map(code => parseInt(code.replace('WH', '')) || 0)
|
||||
const maxNum = Math.max(...numbers)
|
||||
return 'WH' + String(maxNum + 1).padStart(3, '0')
|
||||
}
|
||||
|
||||
const handleWarehouseAdd = () => {
|
||||
warehouseIsEdit.value = false
|
||||
resetWarehouseForm()
|
||||
// 每次打开新增仓库时随机生成仓库编码
|
||||
warehouseForm.warehouseCode = generateWarehouseCode()
|
||||
warehouseDialogVisible.value = true
|
||||
}
|
||||
|
|
@ -415,11 +316,11 @@ const handleWarehouseEdit = (row) => {
|
|||
id: row.id,
|
||||
warehouseCode: row.warehouseCode,
|
||||
warehouseName: row.warehouseName,
|
||||
address: row.address,
|
||||
manager: row.manager,
|
||||
phone: row.phone || '',
|
||||
capacity: row.capacity,
|
||||
currentStock: row.currentStock || 0,
|
||||
detailAddress: row.detailAddress,
|
||||
contactPerson: row.contactPerson,
|
||||
contactPhone: row.contactPhone || '',
|
||||
stockCapacity: row.stockCapacity,
|
||||
stockInventory: row.stockInventory || 0,
|
||||
status: row.status
|
||||
})
|
||||
warehouseDialogVisible.value = true
|
||||
|
|
@ -430,65 +331,35 @@ const resetWarehouseForm = () => {
|
|||
id: null,
|
||||
warehouseCode: '',
|
||||
warehouseName: '',
|
||||
address: '',
|
||||
manager: '',
|
||||
phone: '',
|
||||
capacity: null,
|
||||
currentStock: 0,
|
||||
status: 1
|
||||
detailAddress: '',
|
||||
contactPerson: '',
|
||||
contactPhone: '',
|
||||
stockCapacity: null,
|
||||
stockInventory: 0,
|
||||
status: '启用'
|
||||
})
|
||||
warehouseFormRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
const handleWarehouseSubmit = async () => {
|
||||
if (!warehouseFormRef.value) return
|
||||
|
||||
await warehouseFormRef.value.validate((valid) => {
|
||||
|
||||
await warehouseFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
warehouseSubmitLoading.value = true
|
||||
try {
|
||||
const warehouses = JSON.parse(localStorage.getItem('mock_warehouses') || '[]')
|
||||
|
||||
if (warehouseIsEdit.value) {
|
||||
// 编辑
|
||||
const index = warehouses.findIndex(w => w.id === warehouseForm.id)
|
||||
if (index !== -1) {
|
||||
warehouses[index] = {
|
||||
...warehouses[index],
|
||||
warehouseName: warehouseForm.warehouseName,
|
||||
address: warehouseForm.address,
|
||||
manager: warehouseForm.manager,
|
||||
phone: warehouseForm.phone,
|
||||
capacity: warehouseForm.capacity,
|
||||
currentStock: warehouseForm.currentStock,
|
||||
status: warehouseForm.status,
|
||||
updateTime: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
await updateWarehouse(warehouseForm)
|
||||
ElMessage.success('编辑成功')
|
||||
} else {
|
||||
// 新增
|
||||
const newWarehouse = {
|
||||
id: Date.now(),
|
||||
warehouseCode: warehouseForm.warehouseCode,
|
||||
warehouseName: warehouseForm.warehouseName,
|
||||
address: warehouseForm.address,
|
||||
manager: warehouseForm.manager,
|
||||
phone: warehouseForm.phone,
|
||||
capacity: warehouseForm.capacity,
|
||||
currentStock: warehouseForm.currentStock || 0,
|
||||
status: warehouseForm.status,
|
||||
createTime: new Date().toISOString()
|
||||
}
|
||||
warehouses.push(newWarehouse)
|
||||
await addWarehouse(warehouseForm)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_warehouses', JSON.stringify(warehouses))
|
||||
ElMessage.success(warehouseIsEdit.value ? '编辑成功' : '新增成功')
|
||||
warehouseDialogVisible.value = false
|
||||
getWarehouseList()
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
ElMessage.error('操作失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
warehouseSubmitLoading.value = false
|
||||
}
|
||||
|
|
@ -496,17 +367,20 @@ const handleWarehouseSubmit = async () => {
|
|||
}
|
||||
|
||||
const handleWarehouseDelete = (row) => {
|
||||
const ids = row.id ? [row.id] : []
|
||||
ElMessageBox.confirm('确定要删除此仓库吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const warehouses = JSON.parse(localStorage.getItem('mock_warehouses') || '[]')
|
||||
const filtered = warehouses.filter(w => w.id != row.id)
|
||||
localStorage.setItem('mock_warehouses', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getWarehouseList()
|
||||
}).catch(() => {})
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delWarehouse({ ids })
|
||||
ElMessage.success('删除成功')
|
||||
getWarehouseList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
// ==================== 垛位管理 ====================
|
||||
|
|
@ -520,33 +394,33 @@ const stackFormRef = ref(null)
|
|||
const warehouseOptions = ref([])
|
||||
|
||||
const stackQueryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
stackName: ''
|
||||
stockName: ''
|
||||
})
|
||||
|
||||
const stackForm = reactive({
|
||||
id: null,
|
||||
stackCode: '',
|
||||
stackName: '',
|
||||
warehouseId: null,
|
||||
stockCode: '',
|
||||
stockName: '',
|
||||
warehouseName: '',
|
||||
capacity: null,
|
||||
currentStock: null
|
||||
stockCapacity: null,
|
||||
stockInventory: null
|
||||
})
|
||||
|
||||
const stackFormRules = {
|
||||
stackName: [
|
||||
stockName: [
|
||||
{ required: true, message: '请输入垛位名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
warehouseName: [
|
||||
{ required: true, message: '请选择所属仓库', trigger: 'change' }
|
||||
],
|
||||
capacity: [
|
||||
stockCapacity: [
|
||||
{ required: true, message: '请输入容量', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '容量必须大于等于0', trigger: 'blur' }
|
||||
],
|
||||
currentStock: [
|
||||
stockInventory: [
|
||||
{ required: true, message: '请输入当前库存', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '当前库存必须大于等于0', trigger: 'blur' }
|
||||
]
|
||||
|
|
@ -557,82 +431,42 @@ const stackDialogTitle = computed(() => stackIsEdit.value ? '编辑垛位' : '
|
|||
const getStackList = async () => {
|
||||
stackLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_stacks') || '[]')
|
||||
let filtered = mockData.filter(item => {
|
||||
if (stackQueryParams.stackName && !item.stackName.includes(stackQueryParams.stackName)) return false
|
||||
return true
|
||||
})
|
||||
const start = (stackQueryParams.pageNum - 1) * stackQueryParams.pageSize
|
||||
const end = start + stackQueryParams.pageSize
|
||||
stackList.value = filtered.slice(start, end)
|
||||
stackTotal.value = filtered.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateStackMockData()
|
||||
}
|
||||
const response = await listWarehouseStock(stackQueryParams)
|
||||
const list = response.data?.list || response.rows || []
|
||||
stackList.value = list
|
||||
stackTotal.value = response.data?.count || response.total || 0
|
||||
} catch (error) {
|
||||
ElMessage.error('获取垛位列表失败:' + error.message)
|
||||
ElMessage.error('获取垛位列表失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
stackLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const generateStackMockData = () => {
|
||||
setTimeout(() => {
|
||||
const warehouses = ['仓库1', '仓库2', '仓库3']
|
||||
const newStacks = []
|
||||
const now = Date.now()
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
const capacity = Math.floor(Math.random() * 20000) + 5000
|
||||
newStacks.push({
|
||||
id: i,
|
||||
stackCode: 'ST' + String(i).padStart(3, '0'),
|
||||
stackName: i + '号垛位',
|
||||
warehouseName: warehouses[Math.floor(Math.random() * warehouses.length)],
|
||||
capacity: capacity,
|
||||
currentStock: Math.floor(capacity * (0.2 + Math.random() * 0.6)),
|
||||
createTime: new Date(now - i * 30 * 86400000).toISOString()
|
||||
})
|
||||
}
|
||||
localStorage.setItem('mock_stacks', JSON.stringify(newStacks))
|
||||
getStackList()
|
||||
}, 10)
|
||||
}
|
||||
|
||||
const loadWarehouseOptions = () => {
|
||||
const warehouses = JSON.parse(localStorage.getItem('mock_warehouses') || '[]')
|
||||
warehouseOptions.value = warehouses
|
||||
.filter(w => w.status == 1)
|
||||
.map(w => ({
|
||||
warehouseName: w.warehouseName
|
||||
}))
|
||||
}
|
||||
|
||||
const generateStackCode = () => {
|
||||
const stacks = JSON.parse(localStorage.getItem('mock_stacks') || '[]')
|
||||
if (stacks.length === 0) return 'ST001'
|
||||
const codes = stacks.map(s => s.stackCode).filter(code => code.startsWith('ST'))
|
||||
if (codes.length === 0) return 'ST001'
|
||||
const numbers = codes.map(code => parseInt(code.replace('ST', '')) || 0)
|
||||
const maxNum = Math.max(...numbers)
|
||||
return 'ST' + String(maxNum + 1).padStart(3, '0')
|
||||
const loadWarehouseOptions = async () => {
|
||||
try {
|
||||
const response = await listWarehouse({ pageIndex: 1, pageSize: 1000, status: '启用' })
|
||||
warehouseOptions.value = response.data?.list || response.rows || []
|
||||
} catch (error) {
|
||||
ElMessage.error('加载仓库选项失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
|
||||
// 如果需要前端生成垛位编码,这里可以扩展逻辑;暂时保留简单占位
|
||||
const handleStackQuery = () => {
|
||||
stackQueryParams.pageNum = 1
|
||||
stackQueryParams.pageIndex = 1
|
||||
getStackList()
|
||||
}
|
||||
|
||||
const resetStackQuery = () => {
|
||||
stackQueryParams.stackName = ''
|
||||
stackQueryParams.stockName = ''
|
||||
handleStackQuery()
|
||||
}
|
||||
|
||||
const handleStackAdd = () => {
|
||||
stackIsEdit.value = false
|
||||
resetStackForm()
|
||||
stackForm.stackCode = generateStackCode()
|
||||
loadWarehouseOptions()
|
||||
stackForm.stockCode = generateWarehouseCode()
|
||||
stackDialogVisible.value = true
|
||||
}
|
||||
|
||||
|
|
@ -640,11 +474,12 @@ const handleStackEdit = (row) => {
|
|||
stackIsEdit.value = true
|
||||
Object.assign(stackForm, {
|
||||
id: row.id,
|
||||
stackCode: row.stackCode,
|
||||
stackName: row.stackName,
|
||||
stockCode: row.stockCode,
|
||||
stockName: row.stockName,
|
||||
warehouseName: row.warehouseName,
|
||||
capacity: row.capacity,
|
||||
currentStock: row.currentStock || 0
|
||||
stockCapacity: row.stockCapacity,
|
||||
stockInventory: row.stockInventory || 0,
|
||||
warehouseId: row.warehouseId
|
||||
})
|
||||
loadWarehouseOptions()
|
||||
stackDialogVisible.value = true
|
||||
|
|
@ -653,58 +488,34 @@ const handleStackEdit = (row) => {
|
|||
const resetStackForm = () => {
|
||||
Object.assign(stackForm, {
|
||||
id: null,
|
||||
stackCode: '',
|
||||
stackName: '',
|
||||
stockCode: '',
|
||||
stockName: '',
|
||||
warehouseName: '',
|
||||
capacity: null,
|
||||
currentStock: 0
|
||||
stockCapacity: null,
|
||||
stockInventory: 0
|
||||
})
|
||||
stackFormRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
const handleStackSubmit = async () => {
|
||||
if (!stackFormRef.value) return
|
||||
|
||||
await stackFormRef.value.validate((valid) => {
|
||||
|
||||
await stackFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
stackSubmitLoading.value = true
|
||||
try {
|
||||
const stacks = JSON.parse(localStorage.getItem('mock_stacks') || '[]')
|
||||
|
||||
if (stackIsEdit.value) {
|
||||
// 编辑
|
||||
const index = stacks.findIndex(s => s.id === stackForm.id)
|
||||
if (index !== -1) {
|
||||
stacks[index] = {
|
||||
...stacks[index],
|
||||
stackName: stackForm.stackName,
|
||||
warehouseName: stackForm.warehouseName,
|
||||
capacity: stackForm.capacity,
|
||||
currentStock: stackForm.currentStock,
|
||||
updateTime: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
await updateWarehouseStock(stackForm)
|
||||
ElMessage.success('编辑成功')
|
||||
} else {
|
||||
// 新增
|
||||
const newStack = {
|
||||
id: Date.now(),
|
||||
stackCode: stackForm.stackCode,
|
||||
stackName: stackForm.stackName,
|
||||
warehouseName: stackForm.warehouseName,
|
||||
capacity: stackForm.capacity,
|
||||
currentStock: stackForm.currentStock || 0,
|
||||
createTime: new Date().toISOString()
|
||||
}
|
||||
stacks.push(newStack)
|
||||
await addWarehouseStock(stackForm)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_stacks', JSON.stringify(stacks))
|
||||
ElMessage.success(stackIsEdit.value ? '编辑成功' : '新增成功')
|
||||
stackDialogVisible.value = false
|
||||
getStackList()
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
ElMessage.error('操作失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
stackSubmitLoading.value = false
|
||||
}
|
||||
|
|
@ -712,31 +523,38 @@ const handleStackSubmit = async () => {
|
|||
}
|
||||
|
||||
const handleStackDelete = (row) => {
|
||||
const ids = row.id ? [row.id] : []
|
||||
ElMessageBox.confirm('确定要删除此垛位吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const stacks = JSON.parse(localStorage.getItem('mock_stacks') || '[]')
|
||||
const filtered = stacks.filter(s => s.id != row.id)
|
||||
localStorage.setItem('mock_stacks', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getStackList()
|
||||
}).catch(() => {})
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delWarehouseStock({ ids })
|
||||
ElMessage.success('删除成功')
|
||||
getStackList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
// 监听 tab 切换,加载对应数据
|
||||
// 监听 tab 切换,加载对应数据(每次切换都刷新仓库下拉选项)
|
||||
watch(activeTab, (newTab) => {
|
||||
// 每次切换 tab 时,重新通过接口获取仓库列表,刷新 warehouseOptions
|
||||
loadWarehouseOptions()
|
||||
|
||||
if (newTab === 'warehouse') {
|
||||
getWarehouseList()
|
||||
} else if (newTab === 'stack') {
|
||||
getStackList()
|
||||
loadWarehouseOptions()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 初次进入页面时加载默认 tab 的数据
|
||||
getWarehouseList()
|
||||
// 同时初始化一次仓库下拉选项
|
||||
loadWarehouseOptions()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -763,4 +581,3 @@ onMounted(() => {
|
|||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 150px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="正常" value="1" />
|
||||
<el-option label="停用" value="0" />
|
||||
<el-option label="正常" value="正常" />
|
||||
<el-option label="停用" value="停用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
|
@ -19,19 +19,19 @@
|
|||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="supplierList" border style="width: 100%; margin-top: 20px;">
|
||||
<el-table-column prop="supplierCode" label="供应商ID" width="120" />
|
||||
<!-- <el-table-column prop="supplierCode" label="供应商ID" width="120" /> -->
|
||||
<el-table-column prop="supplierName" label="供应商名称" width="200" />
|
||||
<el-table-column prop="supplierType" label="供应商类别" width="150" />
|
||||
<el-table-column prop="contact" label="联系人" width="120" />
|
||||
<el-table-column prop="phone" label="手机号" width="130" />
|
||||
<el-table-column prop="address" label="详细地址" min-width="200" />
|
||||
<el-table-column prop="contactPerson" label="联系人" width="120" />
|
||||
<el-table-column prop="mobilePhone" label="手机号" width="130" />
|
||||
<el-table-column prop="detailAddress" label="详细地址" min-width="200" />
|
||||
<el-table-column prop="bankName" label="开户银行" width="150" />
|
||||
<el-table-column prop="bankAccount" label="银行账号" width="180" />
|
||||
<el-table-column prop="taxNumber" label="税号" width="180" />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'">
|
||||
{{ scope.row.status == 1 ? '正常' : '停用' }}
|
||||
<el-tag :type="scope.row.status == '正常' ? 'success' : 'danger'">
|
||||
{{ scope.row.status == '正常' ? '正常' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:page="queryParams.pageIndex"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
|
@ -94,27 +94,27 @@
|
|||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人" prop="contact">
|
||||
<el-form-item label="联系人" prop="contactPerson">
|
||||
<el-input
|
||||
v-model="supplierForm.contact"
|
||||
v-model="supplierForm.contactPerson"
|
||||
placeholder="请输入联系人"
|
||||
maxlength="20"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-form-item label="手机号" prop="mobilePhone">
|
||||
<el-input
|
||||
v-model="supplierForm.phone"
|
||||
v-model="supplierForm.mobilePhone"
|
||||
placeholder="请输入手机号"
|
||||
maxlength="11"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="详细地址" prop="address">
|
||||
<el-form-item label="详细地址" prop="detailAddress">
|
||||
<el-input
|
||||
v-model="supplierForm.address"
|
||||
v-model="supplierForm.detailAddress"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="请输入详细地址"
|
||||
|
|
@ -154,8 +154,8 @@
|
|||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="supplierForm.status">
|
||||
<el-radio :label="1">正常</el-radio>
|
||||
<el-radio :label="0">停用</el-radio>
|
||||
<el-radio :label="'正常'">正常</el-radio>
|
||||
<el-radio :label="'停用'">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
|
@ -182,13 +182,13 @@
|
|||
<el-descriptions-item label="供应商名称">{{ currentSupplier.supplierName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="供应商类别">{{ currentSupplier.supplierType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="currentSupplier.status == 1 ? 'success' : 'danger'">
|
||||
{{ currentSupplier.status == 1 ? '正常' : '停用' }}
|
||||
<el-tag :type="currentSupplier.status == '正常' ? 'success' : 'danger'">
|
||||
{{ currentSupplier.status == '正常' ? '正常' : '停用' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人">{{ currentSupplier.contact }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ currentSupplier.phone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="详细地址" :span="2">{{ currentSupplier.address }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人">{{ currentSupplier.contactPerson }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ currentSupplier.mobilePhone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="详细地址" :span="2">{{ currentSupplier.detailAddress }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开户银行">{{ currentSupplier.bankName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="银行账号">{{ currentSupplier.bankAccount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="税号" :span="2">{{ currentSupplier.taxNumber }}</el-descriptions-item>
|
||||
|
|
@ -201,6 +201,7 @@
|
|||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { listSupplier, addSupplier, updateSupplier, delSupplier } from '@/api/base/supplier'
|
||||
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
|
|
@ -213,7 +214,7 @@ const supplierFormRef = ref(null)
|
|||
const currentSupplier = ref(null)
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
status: ''
|
||||
})
|
||||
|
|
@ -223,13 +224,13 @@ const supplierForm = reactive({
|
|||
supplierCode: '',
|
||||
supplierName: '',
|
||||
supplierType: '',
|
||||
contact: '',
|
||||
phone: '',
|
||||
address: '',
|
||||
contactPerson: '',
|
||||
mobilePhone: '',
|
||||
detailAddress: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
taxNumber: '',
|
||||
status: 1
|
||||
status: '正常'
|
||||
})
|
||||
|
||||
const supplierFormRules = {
|
||||
|
|
@ -240,14 +241,14 @@ const supplierFormRules = {
|
|||
supplierType: [
|
||||
{ required: true, message: '请选择供应商类别', trigger: 'change' }
|
||||
],
|
||||
contact: [
|
||||
contactPerson: [
|
||||
{ required: true, message: '请输入联系人', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
mobilePhone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||
],
|
||||
address: [
|
||||
detailAddress: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' }
|
||||
],
|
||||
bankName: [
|
||||
|
|
@ -269,74 +270,18 @@ const dialogTitle = computed(() => isEdit.value ? '编辑供应商' : '新增供
|
|||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_suppliers') || '[]')
|
||||
let filtered = mockData.filter(item => {
|
||||
if (queryParams.status !== '' && item.status != queryParams.status) return false
|
||||
return true
|
||||
})
|
||||
const start = (queryParams.pageNum - 1) * queryParams.pageSize
|
||||
const end = start + queryParams.pageSize
|
||||
supplierList.value = filtered.slice(start, end)
|
||||
total.value = filtered.length
|
||||
|
||||
if (mockData.length === 0) {
|
||||
generateMockData()
|
||||
}
|
||||
const res = await listSupplier(queryParams)
|
||||
supplierList.value = res.data?.list || res.rows || []
|
||||
total.value = res.data?.count || res.total || supplierList.value.length
|
||||
} catch (error) {
|
||||
ElMessage.error('获取供应商列表失败:' + error.message)
|
||||
ElMessage.error('获取供应商列表失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const generateMockData = () => {
|
||||
setTimeout(() => {
|
||||
const supplierTypes = ['煤炭供应商', '物流供应商', '设备供应商', '服务供应商']
|
||||
const cities = ['太原市', '大同市', '阳泉市', '长治市', '晋城市', '朔州市', '晋中市', '运城市', '忻州市', '临汾市']
|
||||
const banks = ['中国工商银行', '中国建设银行', '中国农业银行', '中国银行', '交通银行', '招商银行', '浦发银行']
|
||||
const surnames = ['张', '李', '王', '赵', '刘', '陈', '杨', '黄', '周', '吴']
|
||||
const names = ['三', '四', '五', '六', '七', '明', '强', '伟', '芳', '娜']
|
||||
const newSuppliers = []
|
||||
const now = Date.now()
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
newSuppliers.push({
|
||||
id: i,
|
||||
supplierCode: 'S' + String(i).padStart(3, '0'),
|
||||
supplierName: '煤贸商' + String.fromCharCode(64 + i),
|
||||
supplierType: supplierTypes[Math.floor(Math.random() * supplierTypes.length)],
|
||||
contact: surnames[Math.floor(Math.random() * surnames.length)] + names[Math.floor(Math.random() * names.length)],
|
||||
phone: '138' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0'),
|
||||
address: cities[Math.floor(Math.random() * cities.length)] + 'xxx区xxx路xxx号',
|
||||
bankName: banks[Math.floor(Math.random() * banks.length)],
|
||||
bankAccount: '622' + String(Math.floor(Math.random() * 10000000000000000)).padStart(16, '0'),
|
||||
taxNumber: '91140000' + String(Math.floor(Math.random() * 100000000)).padStart(8, '0') + String.fromCharCode(65 + Math.floor(Math.random() * 26)),
|
||||
status: Math.random() > 0.2 ? 1 : 0,
|
||||
createTime: new Date(now - i * 30 * 86400000).toISOString(),
|
||||
updateTime: new Date(now - i * 30 * 86400000).toISOString()
|
||||
})
|
||||
}
|
||||
localStorage.setItem('mock_suppliers', JSON.stringify(newSuppliers))
|
||||
getList()
|
||||
}, 10)
|
||||
}
|
||||
|
||||
const generateSupplierCode = () => {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_suppliers') || '[]')
|
||||
let maxCode = 0
|
||||
mockData.forEach(item => {
|
||||
const match = item.supplierCode.match(/^S(\d+)$/)
|
||||
if (match) {
|
||||
const num = parseInt(match[1])
|
||||
if (num > maxCode) {
|
||||
maxCode = num
|
||||
}
|
||||
}
|
||||
})
|
||||
return 'S' + String(maxCode + 1).padStart(3, '0')
|
||||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNum = 1
|
||||
queryParams.pageIndex = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
|
|
@ -348,8 +293,6 @@ const resetQuery = () => {
|
|||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
resetForm()
|
||||
// 自动生成供应商ID
|
||||
supplierForm.supplierCode = generateSupplierCode()
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
|
|
@ -365,9 +308,9 @@ const handleEdit = (row) => {
|
|||
supplierCode: row.supplierCode,
|
||||
supplierName: row.supplierName,
|
||||
supplierType: row.supplierType,
|
||||
contact: row.contact,
|
||||
phone: row.phone,
|
||||
address: row.address,
|
||||
contactPerson: row.contactPerson,
|
||||
mobilePhone: row.mobilePhone,
|
||||
detailAddress: row.detailAddress,
|
||||
bankName: row.bankName,
|
||||
bankAccount: row.bankAccount,
|
||||
taxNumber: row.taxNumber,
|
||||
|
|
@ -377,16 +320,19 @@ const handleEdit = (row) => {
|
|||
}
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const Ids = row.id ? [row.id] : []
|
||||
ElMessageBox.confirm('确定要删除此供应商吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const suppliers = JSON.parse(localStorage.getItem('mock_suppliers') || '[]')
|
||||
const filtered = suppliers.filter(s => s.id != row.id)
|
||||
localStorage.setItem('mock_suppliers', JSON.stringify(filtered))
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
}).then(async () => {
|
||||
try {
|
||||
await delSupplier({ ids: Ids })
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
|
|
@ -396,13 +342,13 @@ const resetForm = () => {
|
|||
supplierCode: '',
|
||||
supplierName: '',
|
||||
supplierType: '',
|
||||
contact: '',
|
||||
phone: '',
|
||||
address: '',
|
||||
contactPerson: '',
|
||||
mobilePhone: '',
|
||||
detailAddress: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
taxNumber: '',
|
||||
status: 1
|
||||
status: '正常'
|
||||
})
|
||||
supplierFormRef.value?.clearValidate()
|
||||
}
|
||||
|
|
@ -410,70 +356,22 @@ const resetForm = () => {
|
|||
const handleSubmit = async () => {
|
||||
if (!supplierFormRef.value) return
|
||||
|
||||
await supplierFormRef.value.validate((valid) => {
|
||||
await supplierFormRef.value.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_suppliers') || '[]')
|
||||
const now = new Date().toISOString()
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑
|
||||
const index = mockData.findIndex(item => item.id === supplierForm.id)
|
||||
if (index !== -1) {
|
||||
mockData[index] = {
|
||||
...mockData[index],
|
||||
supplierName: supplierForm.supplierName,
|
||||
supplierType: supplierForm.supplierType,
|
||||
contact: supplierForm.contact,
|
||||
phone: supplierForm.phone,
|
||||
address: supplierForm.address,
|
||||
bankName: supplierForm.bankName,
|
||||
bankAccount: supplierForm.bankAccount,
|
||||
taxNumber: supplierForm.taxNumber,
|
||||
status: supplierForm.status,
|
||||
updateTime: now
|
||||
}
|
||||
}
|
||||
await updateSupplier(supplierForm)
|
||||
ElMessage.success('编辑成功')
|
||||
} else {
|
||||
// 新增
|
||||
// 确保供应商ID是生成的(防止手动修改)
|
||||
if (!supplierForm.supplierCode || !supplierForm.supplierCode.match(/^S\d{3}$/)) {
|
||||
supplierForm.supplierCode = generateSupplierCode()
|
||||
}
|
||||
|
||||
// 检查供应商ID是否重复(虽然自动生成,但以防万一)
|
||||
const codeExists = mockData.find(item => item.supplierCode === supplierForm.supplierCode)
|
||||
if (codeExists) {
|
||||
// 如果重复,重新生成
|
||||
supplierForm.supplierCode = generateSupplierCode()
|
||||
}
|
||||
|
||||
const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1
|
||||
mockData.push({
|
||||
id: newId,
|
||||
supplierCode: supplierForm.supplierCode,
|
||||
supplierName: supplierForm.supplierName,
|
||||
supplierType: supplierForm.supplierType,
|
||||
contact: supplierForm.contact,
|
||||
phone: supplierForm.phone,
|
||||
address: supplierForm.address,
|
||||
bankName: supplierForm.bankName,
|
||||
bankAccount: supplierForm.bankAccount,
|
||||
taxNumber: supplierForm.taxNumber,
|
||||
status: supplierForm.status,
|
||||
createTime: now,
|
||||
updateTime: now
|
||||
})
|
||||
await addSupplier(supplierForm)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
localStorage.setItem('mock_suppliers', JSON.stringify(mockData))
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
ElMessage.error('操作失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,46 +2,34 @@
|
|||
<div class="app-container">
|
||||
<el-card>
|
||||
<el-table v-loading="loading" :data="alertConfigList" border style="width: 100%">
|
||||
<el-table-column prop="category" label="报警类别" width="150" align="center">
|
||||
<el-table-column prop="alertType" label="报警类别" width="150" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.category === 'insufficient' ? 'danger' : 'warning'">
|
||||
{{ scope.row.category === 'insufficient' ? '库存不足' : '库存积压' }}
|
||||
<el-tag :type="scope.row.alertType === '库存不足' ? 'danger' : 'warning'">
|
||||
<!-- {{ scope.row.alertType === 'insufficient' ? '库存不足' : '库存积压' }} -->
|
||||
{{ scope.row.alertType }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="level" label="报警级别" width="120" align="center">
|
||||
<el-table-column prop="alertLevel" label="报警级别" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getLevelType(scope.row.level)">
|
||||
{{ getLevelName(scope.row.level) }}
|
||||
<el-tag :type="getLevelType(scope.row.alertLevel)">
|
||||
{{ getLevelName(scope.row.alertLevel) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="threshold" label="阈值" width="200" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.editing">{{ scope.row.threshold }} {{ scope.row.unit }}</span>
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="scope.row.threshold"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
style="width: 120px"
|
||||
/>
|
||||
<el-input-number v-else v-model="scope.row.threshold" :min="0" :precision="2" :controls="false"
|
||||
style="width: 120px" />
|
||||
<span style="margin-left: 8px">{{ scope.row.unit }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="description" label="说明" min-width="200">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.editing">{{ scope.row.description || '-' }}</span>
|
||||
<el-input
|
||||
v-else
|
||||
v-model="scope.row.description"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="请输入说明"
|
||||
maxlength="200"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-input v-else v-model="scope.row.description" type="textarea" :rows="2" placeholder="请输入说明"
|
||||
maxlength="200" style="width: 100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
|
|
@ -55,12 +43,8 @@
|
|||
<template #default="scope">
|
||||
<template v-if="!scope.row.editing">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button
|
||||
link
|
||||
:type="scope.row.status === 1 ? 'warning' : 'success'"
|
||||
size="small"
|
||||
@click="handleToggleStatus(scope.row)"
|
||||
>
|
||||
<el-button link :type="scope.row.status === 1 ? 'warning' : 'success'" size="small"
|
||||
@click="handleToggleStatus(scope.row)">
|
||||
{{ scope.row.status === 1 ? '禁用' : '启用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
|
@ -78,7 +62,7 @@
|
|||
<script setup name="InventoryAlertConfig">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
import { listInventoryAlertConfig, addInventoryAlertConfig, delInventoryAlertConfig } from "@/api/system/inventory-alert"
|
||||
const loading = ref(false)
|
||||
const alertConfigList = ref([])
|
||||
|
||||
|
|
@ -90,8 +74,15 @@ const getLevelName = (level) => {
|
|||
}
|
||||
return levelMap[level] || level
|
||||
}
|
||||
|
||||
const queryParams = reactive({
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
alertType: null,
|
||||
alertLevel: null,
|
||||
status: null
|
||||
})
|
||||
const getLevelType = (level) => {
|
||||
|
||||
const typeMap = {
|
||||
'low': 'info',
|
||||
'medium': 'warning',
|
||||
|
|
@ -104,7 +95,7 @@ const getList = async () => {
|
|||
loading.value = true
|
||||
try {
|
||||
const mockData = JSON.parse(localStorage.getItem('mock_inventory_alert_configs') || '[]')
|
||||
|
||||
|
||||
// 检查数据是否有效,如果数据不完整或格式错误,重新生成
|
||||
if (mockData.length === 0 || !mockData.some(item => item.category === 'insufficient')) {
|
||||
generateDefaultConfigs()
|
||||
|
|
@ -132,71 +123,75 @@ const getList = async () => {
|
|||
}
|
||||
|
||||
const generateDefaultConfigs = () => {
|
||||
const defaultConfigs = [
|
||||
// 库存不足 - 低中高
|
||||
{
|
||||
id: 1,
|
||||
category: 'insufficient',
|
||||
level: 'low',
|
||||
threshold: 100,
|
||||
unit: '吨',
|
||||
description: '库存低于100吨时触发低级别报警',
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
category: 'insufficient',
|
||||
level: 'medium',
|
||||
threshold: 50,
|
||||
unit: '吨',
|
||||
description: '库存低于50吨时触发中级别报警',
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
category: 'insufficient',
|
||||
level: 'high',
|
||||
threshold: 20,
|
||||
unit: '吨',
|
||||
description: '库存低于20吨时触发高级别报警',
|
||||
status: 1
|
||||
},
|
||||
// 库存积压 - 低中高
|
||||
{
|
||||
id: 4,
|
||||
category: 'overstock',
|
||||
level: 'low',
|
||||
threshold: 5000,
|
||||
unit: '吨',
|
||||
description: '库存超过5000吨时触发低级别报警',
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
category: 'overstock',
|
||||
level: 'medium',
|
||||
threshold: 8000,
|
||||
unit: '吨',
|
||||
description: '库存超过8000吨时触发中级别报警',
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
category: 'overstock',
|
||||
level: 'high',
|
||||
threshold: 10000,
|
||||
unit: '吨',
|
||||
description: '库存超过10000吨时触发高级别报警',
|
||||
status: 1
|
||||
}
|
||||
]
|
||||
|
||||
localStorage.setItem('mock_inventory_alert_configs', JSON.stringify(defaultConfigs))
|
||||
alertConfigList.value = defaultConfigs.map(item => ({
|
||||
...item,
|
||||
editing: false,
|
||||
originalData: null
|
||||
}))
|
||||
listInventoryAlertConfig(queryParams).then(response => {
|
||||
alertConfigList.value = response.data.list
|
||||
|
||||
// const defaultConfigs = [
|
||||
// // 库存不足 - 低中高
|
||||
// {
|
||||
// id: 1,
|
||||
// category: 'insufficient',
|
||||
// level: 'low',
|
||||
// threshold: 100,
|
||||
// unit: '吨',
|
||||
// description: '库存低于100吨时触发低级别报警',
|
||||
// status: 1
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// category: 'insufficient',
|
||||
// level: 'medium',
|
||||
// threshold: 50,
|
||||
// unit: '吨',
|
||||
// description: '库存低于50吨时触发中级别报警',
|
||||
// status: 1
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// category: 'insufficient',
|
||||
// level: 'high',
|
||||
// threshold: 20,
|
||||
// unit: '吨',
|
||||
// description: '库存低于20吨时触发高级别报警',
|
||||
// status: 1
|
||||
// },
|
||||
// // 库存积压 - 低中高
|
||||
// {
|
||||
// id: 4,
|
||||
// category: 'overstock',
|
||||
// level: 'low',
|
||||
// threshold: 5000,
|
||||
// unit: '吨',
|
||||
// description: '库存超过5000吨时触发低级别报警',
|
||||
// status: 1
|
||||
// },
|
||||
// {
|
||||
// id: 5,
|
||||
// category: 'overstock',
|
||||
// level: 'medium',
|
||||
// threshold: 8000,
|
||||
// unit: '吨',
|
||||
// description: '库存超过8000吨时触发中级别报警',
|
||||
// status: 1
|
||||
// },
|
||||
// {
|
||||
// id: 6,
|
||||
// category: 'overstock',
|
||||
// level: 'high',
|
||||
// threshold: 10000,
|
||||
// unit: '吨',
|
||||
// description: '库存超过10000吨时触发高级别报警',
|
||||
// status: 1
|
||||
// }
|
||||
// ]
|
||||
|
||||
// localStorage.setItem('mock_inventory_alert_configs', JSON.stringify(defaultConfigs))
|
||||
// alertConfigList.value = defaultConfigs.map(item => ({
|
||||
// ...item,
|
||||
// editing: false,
|
||||
// originalData: null
|
||||
// }))
|
||||
})
|
||||
}
|
||||
|
||||
const handleEdit = (row) => {
|
||||
|
|
@ -206,7 +201,7 @@ const handleEdit = (row) => {
|
|||
handleCancel(item)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
row.editing = true
|
||||
row.originalData = { ...row }
|
||||
}
|
||||
|
|
@ -225,11 +220,11 @@ const handleSave = async (row) => {
|
|||
ElMessage.error('请输入有效的阈值')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const configs = JSON.parse(localStorage.getItem('mock_inventory_alert_configs') || '[]')
|
||||
const index = configs.findIndex(c => c.id === row.id)
|
||||
|
||||
|
||||
if (index !== -1) {
|
||||
configs[index] = {
|
||||
id: row.id,
|
||||
|
|
@ -240,7 +235,7 @@ const handleSave = async (row) => {
|
|||
description: row.description || '',
|
||||
status: row.status
|
||||
}
|
||||
|
||||
|
||||
localStorage.setItem('mock_inventory_alert_configs', JSON.stringify(configs))
|
||||
ElMessage.success('保存成功')
|
||||
row.editing = false
|
||||
|
|
@ -264,21 +259,26 @@ const handleToggleStatus = (row) => {
|
|||
try {
|
||||
const configs = JSON.parse(localStorage.getItem('mock_inventory_alert_configs') || '[]')
|
||||
const index = configs.findIndex(c => c.id === row.id)
|
||||
|
||||
|
||||
if (index !== -1) {
|
||||
configs[index].status = configs[index].status === 1 ? 0 : 1
|
||||
row.status = configs[index].status
|
||||
|
||||
|
||||
localStorage.setItem('mock_inventory_alert_configs', JSON.stringify(configs))
|
||||
ElMessage.success('操作成功')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败:' + error.message)
|
||||
}
|
||||
}).catch(() => {})
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
onMounted(() => getList())
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
generateDefaultConfigs()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -294,4 +294,3 @@ onMounted(() => getList())
|
|||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import { defineConfig, loadEnv } from 'vite'
|
|||
import path from 'path'
|
||||
import createVitePlugins from './vite/plugins'
|
||||
|
||||
const baseUrl = 'http://172.16.1.116:8000/' // 后端接口
|
||||
// const baseUrl = 'http://172.16.1.116:8000/' // 后端接口
|
||||
const baseUrl = 'http://172.16.1.162:40980/' // 后端接口
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue