930 lines
31 KiB
Vue
930 lines
31 KiB
Vue
<template>
|
||
<div class="customer-page">
|
||
<div class="customer-toolbar boxshadow">
|
||
<div class="customer-search-group">
|
||
<el-form-item label="关键字:" label-width="70px">
|
||
<el-input style="min-width: 120px" v-model="keyword" placeholder="请输入关键字" />
|
||
</el-form-item>
|
||
</div>
|
||
</div>
|
||
<div class="boxshadow">
|
||
<ElRow>
|
||
<div style="width: 12px"></div>
|
||
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
|
||
<ElButton @click="showDialog('add')" v-if="hasAuth('item_list@add')" v-ripple
|
||
>新增</ElButton
|
||
>
|
||
</ElCol>
|
||
</ElRow>
|
||
<ArtTable
|
||
ref="tableRef"
|
||
row-key="id"
|
||
:loading="loading"
|
||
:data="tableData"
|
||
:currentPage="pagination.currentPage"
|
||
:pageSize="pagination.pageSize"
|
||
:total="pagination.total"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
>
|
||
<template #default>
|
||
<ElTableColumn label="ID" prop="id" width="80" />
|
||
<ElTableColumn label="公司" prop="company_name" />
|
||
<ElTableColumn label="名称" prop="item_name" />
|
||
<ElTableColumn label="物品管理员" prop="manage_user_name" />
|
||
<ElTableColumn label="备注" prop="remark" />
|
||
<ElTableColumn label="库存数量" prop="stock_qty" />
|
||
<ElTableColumn label="扫码领取" prop="allow_qr_claim">
|
||
<template #default="scope">
|
||
<ElTag :type="scope.row.allow_qr_claim ? 'primary' : 'info'">
|
||
{{ scope.row.allow_qr_claim ? '是' : '否' }}
|
||
</ElTag>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="领取限制数量" prop="qr_code_num">
|
||
<template #default="scope">
|
||
{{ scope.row.qr_code_num === 0 ? '不限制' : scope.row.qr_code_num }}
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="是否耗材" prop="is_consumable" width="180">
|
||
<template #default="scope">
|
||
<ElTag :type="scope.row.is_consumable ? 'primary' : 'info'">
|
||
{{ scope.row.is_consumable ? '是' : '否' }}
|
||
</ElTag>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="状态" prop="status">
|
||
<template #default="scope">
|
||
<ElTag :type="scope.row.status ? 'primary' : 'info'">
|
||
{{ scope.row.status ? '启用' : '禁用' }}
|
||
</ElTag>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="创建时间" prop="created_at" />
|
||
<ElTableColumn fixed="right" label="操作" width="160" align="center">
|
||
<template #default="scope">
|
||
<ElButton link type="primary" @click="showDialog('edit', scope.row)" v-if="hasAuth('item_list@edit')">
|
||
编辑
|
||
</ElButton>
|
||
<ElDropdown trigger="click">
|
||
<ElButton link type="primary">
|
||
更多
|
||
<el-icon class="el-icon--right">
|
||
<arrow-down />
|
||
</el-icon>
|
||
</ElButton>
|
||
<template #dropdown>
|
||
<ElDropdownMenu>
|
||
<ElDropdownItem @click="generateQrCode(scope.row)">
|
||
<el-icon><Document /></el-icon>
|
||
{{ scope.row.qr_code_pull ? '查看二维码' : '生成二维码' }}
|
||
</ElDropdownItem>
|
||
<ElDropdownItem @click="showProxyClaimDialog(scope.row)">
|
||
<el-icon><User /></el-icon>
|
||
管理员代领
|
||
</ElDropdownItem>
|
||
<ElDropdownItem @click="showStockLogDialog(scope.row)">
|
||
<el-icon><List /></el-icon>
|
||
库存记录
|
||
</ElDropdownItem>
|
||
<ElDropdownItem @click="showQrClaimsDialog(scope.row)">
|
||
<el-icon><Tickets /></el-icon>
|
||
领取记录
|
||
</ElDropdownItem>
|
||
<ElDropdownItem v-if="scope.row.qr_code_pull" @click="deleteQrCode(scope.row)">
|
||
<el-icon><Delete /></el-icon>
|
||
删除二维码
|
||
</ElDropdownItem>
|
||
<ElDropdownItem divided @click="deleteRole(scope.row)" v-if="hasAuth('item_list@del')">
|
||
<el-icon style="color: #f56c6c"><Delete /></el-icon>
|
||
<span style="color: #f56c6c">删除物品</span>
|
||
</ElDropdownItem>
|
||
</ElDropdownMenu>
|
||
</template>
|
||
</ElDropdown>
|
||
</template>
|
||
</ElTableColumn>
|
||
</template>
|
||
</ArtTable>
|
||
</div>
|
||
<ElDialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增' : '编辑'" align-center>
|
||
<ElForm
|
||
ref="formRef"
|
||
:model="form"
|
||
:rules="rules"
|
||
style="padding: 5px 20px"
|
||
label-width="100px"
|
||
>
|
||
<ElFormItem label="公司" prop="company_id">
|
||
<ElSelect
|
||
v-model="form.company_id"
|
||
placeholder="请选择公司"
|
||
filterable
|
||
style="width: 100%"
|
||
>
|
||
<ElOption
|
||
v-for="item in companyList"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
</ElSelect>
|
||
</ElFormItem>
|
||
<ElFormItem label="名称" prop="item_name">
|
||
<ElInput v-model="form.item_name" placeholder="请输入名称" />
|
||
</ElFormItem>
|
||
<ElFormItem label="物品管理员" prop="manage_user_id">
|
||
<ElSelect
|
||
v-model="form.manage_user_id"
|
||
placeholder="请选择负责人"
|
||
filterable
|
||
style="width: 100%"
|
||
>
|
||
<ElOption
|
||
v-for="item in manageUserList"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
</ElSelect>
|
||
</ElFormItem>
|
||
<!-- <ElFormItem label="规格型号" prop="spec_model">
|
||
<ElInput v-model="form.spec_model" placeholder="请输入规格型号" />
|
||
</ElFormItem>
|
||
<ElFormItem label="计量单位" prop="unit">
|
||
<ElInput v-model="form.unit" placeholder="请输入计量单位" />
|
||
</ElFormItem> -->
|
||
<ElFormItem label="是否耗材" prop="is_consumable">
|
||
<el-radio-group v-model="form.is_consumable">
|
||
<el-radio :label="1">是</el-radio>
|
||
<el-radio :label="0">否</el-radio>
|
||
</el-radio-group>
|
||
</ElFormItem>
|
||
<ElFormItem label="备注" prop="remark">
|
||
<ElInput v-model="form.remark" placeholder="请输入备注" />
|
||
</ElFormItem>
|
||
<ElFormItem label="库存数量" prop="stock_qty">
|
||
<ElInputNumber
|
||
v-model="form.stock_qty"
|
||
:min="0"
|
||
placeholder="请输入库存数量"
|
||
style="width: 100%"
|
||
/>
|
||
</ElFormItem>
|
||
<ElFormItem label="扫码领取" prop="allow_qr_claim">
|
||
<el-radio-group v-model="form.allow_qr_claim">
|
||
<el-radio :label="0">否</el-radio>
|
||
<el-radio :label="1">是</el-radio>
|
||
</el-radio-group>
|
||
</ElFormItem>
|
||
<ElFormItem v-if="form.allow_qr_claim === 1" label="单人领取限制" prop="qr_code_num">
|
||
<ElInputNumber
|
||
v-model="form.qr_code_num"
|
||
:min="0"
|
||
placeholder="0为不限制"
|
||
style="width: 100%"
|
||
/>
|
||
<span style="margin-left: 8px; color: var(--el-text-color-secondary); font-size: 12px">
|
||
单人扫码领取数量限制,0为不限制
|
||
</span>
|
||
</ElFormItem>
|
||
<ElFormItem label="状态" prop="status">
|
||
<ElSwitch v-model="form.status" :active-value="1" :inactive-value="0" />
|
||
</ElFormItem>
|
||
</ElForm>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="dialogVisible = false">取消</ElButton>
|
||
<ElButton type="primary" @click="handleSubmit(formRef)">提交</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
|
||
<!-- 二维码弹窗 -->
|
||
<ElDialog v-model="qrCodeDialogVisible" title="物品二维码" width="400px" align-center>
|
||
<div class="qr-code-container">
|
||
<div v-if="qrCodeData" class="qr-code-wrapper">
|
||
<img :src="qrCodeData" alt="二维码" class="qr-code-image" />
|
||
<p class="qr-code-desc">扫描二维码领取物品</p>
|
||
</div>
|
||
<div v-else-if="qrCodeLoading" class="qr-code-loading">
|
||
<el-icon class="is-loading" :size="40">
|
||
<Loading />
|
||
</el-icon>
|
||
<p>生成中...</p>
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="closeQrCodeDialog">{{ qrCodeData ? '关闭' : '取消' }}</ElButton>
|
||
<ElButton v-if="qrCodeData" type="primary" @click="downloadQrCode">下载二维码</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
|
||
<!-- 管理员代领弹窗 -->
|
||
<ElDialog v-model="proxyClaimDialogVisible" title="管理员代领" width="500px" align-center>
|
||
<ElForm ref="proxyClaimFormRef" :model="proxyClaimForm" label-width="100px">
|
||
<ElFormItem label="选择用户" prop="target_user_ids">
|
||
<ElSelect
|
||
v-model="proxyClaimForm.target_user_ids"
|
||
placeholder="请选择用户"
|
||
filterable
|
||
multiple
|
||
style="width: 100%"
|
||
>
|
||
<ElOption v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
|
||
</ElSelect>
|
||
</ElFormItem>
|
||
</ElForm>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="proxyClaimDialogVisible = false">取消</ElButton>
|
||
<ElButton type="primary" @click="handleProxyClaimSubmit">确定</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
|
||
<!-- 库存记录弹窗 -->
|
||
<ElDialog v-model="stockLogDialogVisible" title="库存变化记录" width="80%" align-center>
|
||
<!-- 搜索表单 -->
|
||
<ElForm :model="stockLogSearchForm" inline style="margin-bottom: 16px">
|
||
<ElFormItem label="变动类型">
|
||
<ElSelect
|
||
v-model="stockLogSearchForm.change_type"
|
||
placeholder="请选择变动类型"
|
||
clearable
|
||
style="width: 150px"
|
||
>
|
||
<ElOption label="入库" :value="1" />
|
||
<ElOption label="出库(领用)" :value="2" />
|
||
<ElOption label="出库(损耗)" :value="3" />
|
||
<ElOption label="入库(归还)" :value="4" />
|
||
</ElSelect>
|
||
</ElFormItem>
|
||
<ElFormItem>
|
||
<ElButton type="primary" @click="searchStockLog">查询</ElButton>
|
||
<ElButton @click="resetStockLogSearch">重置</ElButton>
|
||
</ElFormItem>
|
||
</ElForm>
|
||
|
||
<ElTable :data="stockLogList" :loading="stockLogLoading" max-height="400">
|
||
<ElTableColumn label="物品名称" prop="item_name" />
|
||
<ElTableColumn label="变化类型" prop="change_type_text" />
|
||
<ElTableColumn label="变化数量" prop="change_qty">
|
||
<template #default="scope">
|
||
<span :style="{ color: scope.row.change_qty > 0 ? '#67C23A' : '#F56C6C' }">
|
||
{{ scope.row.change_qty > 0 ? '+' : '' }}{{ scope.row.change_qty }}
|
||
</span>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="变化前" prop="before_qty"/>
|
||
<ElTableColumn label="变化后" prop="after_qty" />
|
||
<ElTableColumn label="业务类型" prop="biz_type_text" />
|
||
<ElTableColumn label="操作人" prop="operator_name" />
|
||
<ElTableColumn label="备注" prop="remark" min-width="120" />
|
||
<ElTableColumn label="创建时间" prop="created_at"/>
|
||
</ElTable>
|
||
|
||
<!-- 分页 -->
|
||
<div style="margin-top: 16px; display: flex; justify-content: flex-end">
|
||
<ElPagination
|
||
v-model:current-page="stockLogPagination.currentPage"
|
||
v-model:page-size="stockLogPagination.pageSize"
|
||
:total="stockLogPagination.total"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="handleStockLogSizeChange"
|
||
@current-change="handleStockLogCurrentChange"
|
||
/>
|
||
</div>
|
||
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="stockLogDialogVisible = false">关闭</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
|
||
<!-- 领取记录弹窗 -->
|
||
<ElDialog v-model="qrClaimsDialogVisible" title="领取记录" width="80%" align-center>
|
||
<!-- 搜索表单 -->
|
||
<ElForm :model="qrClaimsSearchForm" inline style="margin-bottom: 16px">
|
||
<ElFormItem label="领取方式">
|
||
<ElSelect
|
||
v-model="qrClaimsSearchForm.claim_type"
|
||
placeholder="请选择领取方式"
|
||
clearable
|
||
style="width: 150px"
|
||
>
|
||
<ElOption label="扫码领取" :value="2" />
|
||
<ElOption label="管理员代领" :value="3" />
|
||
</ElSelect>
|
||
</ElFormItem>
|
||
<ElFormItem label="开始时间">
|
||
<ElDatePicker
|
||
v-model="qrClaimsSearchForm.start_time"
|
||
type="datetime"
|
||
placeholder="请选择开始时间"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
style="width: 180px"
|
||
/>
|
||
</ElFormItem>
|
||
<ElFormItem label="结束时间">
|
||
<ElDatePicker
|
||
v-model="qrClaimsSearchForm.end_time"
|
||
type="datetime"
|
||
placeholder="请选择结束时间"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
style="width: 180px"
|
||
/>
|
||
</ElFormItem>
|
||
<ElFormItem>
|
||
<ElButton type="primary" @click="searchQrClaims">查询</ElButton>
|
||
<ElButton @click="resetQrClaimsSearch">重置</ElButton>
|
||
</ElFormItem>
|
||
</ElForm>
|
||
|
||
<ElTable :data="qrClaimsList" :loading="qrClaimsLoading" max-height="400">
|
||
<ElTableColumn label="物品">
|
||
<template #default="scope">
|
||
<span v-if="scope.row.items && scope.row.items.length > 0">
|
||
<template v-for="(item, index) in scope.row.items" :key="index">
|
||
{{ item.item_name_snap }}<span v-if="Number(index) < scope.row.items.length - 1">, </span>
|
||
</template>
|
||
</span>
|
||
<span v-else>-</span>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="数量">
|
||
<template #default="scope">
|
||
<span v-if="scope.row.items && scope.row.items.length > 0">
|
||
<template v-for="(item, index) in scope.row.items" :key="index">
|
||
{{ item.approved_qty }}<span v-if="Number(index) < scope.row.items.length - 1">, </span>
|
||
</template>
|
||
</span>
|
||
<span v-else>-</span>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="领取人" prop="applicant_name" />
|
||
<ElTableColumn label="领取类型" prop="claim_type_text" />
|
||
<ElTableColumn label="领取时间" prop="created_at" />
|
||
<ElTableColumn label="代领人" prop="proxy_claim_user_name">
|
||
<template #default="scope">
|
||
{{ scope.row.proxy_claim_user_name || '-' }}
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="领取方式" prop="borrow_reason" />
|
||
<ElTableColumn label="备注" prop="remark" />
|
||
</ElTable>
|
||
|
||
<!-- 分页 -->
|
||
<div style="margin-top: 16px; display: flex; justify-content: flex-end">
|
||
<ElPagination
|
||
v-model:current-page="qrClaimsPagination.currentPage"
|
||
v-model:page-size="qrClaimsPagination.pageSize"
|
||
:total="qrClaimsPagination.total"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="handleQrClaimsSizeChange"
|
||
@current-change="handleQrClaimsCurrentChange"
|
||
/>
|
||
</div>
|
||
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="qrClaimsDialogVisible = false">关闭</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { Loading, ArrowDown, Document, User, List, Tickets, Delete } from '@element-plus/icons-vue'
|
||
import type { FormInstance, FormRules } from 'element-plus'
|
||
import { invitemService } from '@/api/admin/Itemrequisition'
|
||
import { manageService } from '@/api/adminApi'
|
||
import { UserService } from '@/api/usersApi'
|
||
import { useAuth } from '@/composables/useAuth'
|
||
const { hasAuth } = useAuth()
|
||
defineOptions({ name: 'ItemList' })
|
||
const keyword = ref<string>('')
|
||
const loading = ref(false)
|
||
const dialogVisible = ref(false)
|
||
const qrCodeDialogVisible = ref(false)
|
||
const qrCodeData = ref('')
|
||
const qrCodeLoading = ref(false)
|
||
const proxyClaimDialogVisible = ref(false)
|
||
const stockLogDialogVisible = ref(false)
|
||
const stockLogList = ref<any[]>([])
|
||
const stockLogLoading = ref(false)
|
||
const currentStockLogItemId = ref<number | null>(null)
|
||
const stockLogSearchForm = reactive({
|
||
change_type: undefined as number | undefined
|
||
})
|
||
const stockLogPagination = reactive({
|
||
currentPage: 1,
|
||
pageSize: 10,
|
||
total: 0
|
||
})
|
||
const qrClaimsDialogVisible = ref(false)
|
||
const qrClaimsList = ref<any[]>([])
|
||
const qrClaimsLoading = ref(false)
|
||
const currentQrClaimsItemId = ref<number | null>(null)
|
||
const qrClaimsSearchForm = reactive({
|
||
claim_type: undefined as number | undefined,
|
||
start_time: '',
|
||
end_time: ''
|
||
})
|
||
const qrClaimsPagination = reactive({
|
||
currentPage: 1,
|
||
pageSize: 10,
|
||
total: 0
|
||
})
|
||
const proxyClaimFormRef = ref<FormInstance>()
|
||
const formRef = ref<FormInstance>()
|
||
const rules = reactive<FormRules>({
|
||
company_id: [{ required: true, message: '请选择公司', trigger: 'change' }],
|
||
item_name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||
manage_user_id: [{ required: true, message: '请选择负责人', trigger: 'change' }]
|
||
})
|
||
|
||
const form = reactive({
|
||
company_id: '',
|
||
manage_user_id: '',
|
||
remark: '',
|
||
item_name: '',
|
||
stock_qty: 0,
|
||
allow_qr_claim: 0,
|
||
is_consumable: 0,
|
||
qr_code_num: 0,
|
||
status: 1,
|
||
id: ''
|
||
})
|
||
const pagination = reactive({
|
||
currentPage: 1,
|
||
pageSize: 10,
|
||
total: 0
|
||
})
|
||
const companyList = ref<any[]>([])
|
||
const getcompanyList = async () => {
|
||
const response = await UserService.getCompanyList()
|
||
const list = (response as any)?.data ?? (response as any)?.records ?? response
|
||
companyList.value = Array.isArray(list) ? list : []
|
||
}
|
||
const manageUserList = ref<any>()
|
||
// 获取用户列表
|
||
const getCompanyUserList = async () => {
|
||
const response = await manageService.presetusers()
|
||
manageUserList.value = response || []
|
||
}
|
||
|
||
// 管理员代领相关
|
||
const proxyClaimForm = reactive({
|
||
item_id: '',
|
||
target_user_ids: [] as number[]
|
||
})
|
||
const userList = ref<any[]>([])
|
||
// 获取所有用户列表
|
||
const getAllUserList = async () => {
|
||
try {
|
||
const response = await manageService.presetusers()
|
||
userList.value = response || []
|
||
} catch (error) {
|
||
console.error('获取用户列表失败:', error)
|
||
}
|
||
}
|
||
// 表格数据
|
||
const tableData = ref<any[]>([])
|
||
|
||
// 表格实例引用
|
||
const tableRef = ref()
|
||
|
||
onMounted(() => {
|
||
getWorkList()
|
||
getcompanyList()
|
||
getCompanyUserList()
|
||
getAllUserList()
|
||
})
|
||
watch([keyword], () => {
|
||
pagination.currentPage = 1
|
||
getWorkList()
|
||
})
|
||
// 获取列表数据
|
||
const getWorkList = async () => {
|
||
loading.value = true
|
||
try {
|
||
const { currentPage, pageSize } = pagination
|
||
const params: any = {
|
||
current: currentPage,
|
||
size: pageSize
|
||
}
|
||
if (keyword.value) {
|
||
params.keyword = keyword.value
|
||
}
|
||
const { records, current, size, total } = await invitemService.getinvitemlist(params)
|
||
tableData.value = records.map((item: any, index: number) => ({
|
||
...item
|
||
}))
|
||
Object.assign(pagination, { currentPage: current, pageSize: size, total })
|
||
} catch (error) {
|
||
console.error('获取列表失败:', error)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
// 处理表格分页变化
|
||
const handleSizeChange = (newPageSize: number) => {
|
||
pagination.pageSize = newPageSize
|
||
getWorkList()
|
||
}
|
||
const handleCurrentChange = (newCurrentPage: number) => {
|
||
pagination.currentPage = newCurrentPage
|
||
getWorkList()
|
||
}
|
||
|
||
const dialogType = ref('add')
|
||
|
||
const showDialog = (type: string, row?: any) => {
|
||
dialogVisible.value = true
|
||
dialogType.value = type
|
||
|
||
if (type === 'edit' && row) {
|
||
// 编辑模式,填充所有字段
|
||
Object.assign(form, {
|
||
company_id: row.company_id,
|
||
item_name: row.item_name,
|
||
manage_user_id: row.manage_user_id,
|
||
remark: row.remark,
|
||
stock_qty: row.stock_qty ?? 0,
|
||
is_consumable: row.is_consumable ?? 0,
|
||
allow_qr_claim: row.allow_qr_claim ?? 0,
|
||
qr_code_num: row.qr_code_num ?? 0,
|
||
status: row.status,
|
||
id: row.id
|
||
})
|
||
} else {
|
||
// 新增模式,重置所有字段
|
||
Object.assign(form, {
|
||
company_id: '',
|
||
item_name: '',
|
||
manage_user_id: '',
|
||
remark: '',
|
||
stock_qty: 0,
|
||
is_consumable: 0,
|
||
allow_qr_claim: 0,
|
||
qr_code_num: 0,
|
||
status: 1,
|
||
id: ''
|
||
})
|
||
}
|
||
}
|
||
const deleteRole = (row?: any) => {
|
||
ElMessageBox.confirm('确定删除吗?', '删除确认', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'error'
|
||
}).then(async () => {
|
||
const { message } = await invitemService.invitemdelete({
|
||
id: row.id
|
||
})
|
||
ElMessage.success(message)
|
||
getWorkList()
|
||
})
|
||
}
|
||
|
||
// 删除二维码
|
||
const deleteQrCode = (row: any) => {
|
||
ElMessageBox.confirm('确定删除该物品的二维码吗?', '删除确认', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(async () => {
|
||
const { message } = await invitemService.deleteQrCode({
|
||
id: row.id
|
||
})
|
||
ElMessage.success(message)
|
||
getWorkList()
|
||
})
|
||
}
|
||
|
||
const handleSubmit = async (formEl: FormInstance | undefined) => {
|
||
if (!formEl) return
|
||
await formEl.validate(async (valid) => {
|
||
if (valid) {
|
||
if (dialogType.value === 'add') {
|
||
const { message } = await invitemService.invitemadd({
|
||
company_id: form.company_id,
|
||
item_name: form.item_name,
|
||
manage_user_id: form.manage_user_id,
|
||
remark: form.remark,
|
||
stock_qty: form.stock_qty,
|
||
is_consumable: form.is_consumable,
|
||
allow_qr_claim: form.allow_qr_claim,
|
||
qr_code_num: form.qr_code_num || 0,
|
||
status: form.status
|
||
})
|
||
ElMessage.success(message)
|
||
} else {
|
||
const { message } = await invitemService.invitemupdate({
|
||
id: form.id,
|
||
company_id: form.company_id,
|
||
item_name: form.item_name,
|
||
manage_user_id: form.manage_user_id,
|
||
remark: form.remark,
|
||
stock_qty: form.stock_qty,
|
||
is_consumable: form.is_consumable,
|
||
allow_qr_claim: form.allow_qr_claim,
|
||
qr_code_num: form.qr_code_num || 0,
|
||
status: form.status
|
||
})
|
||
ElMessage.success(message)
|
||
}
|
||
dialogVisible.value = false
|
||
getWorkList()
|
||
}
|
||
})
|
||
}
|
||
|
||
// 生成/查看二维码
|
||
const generateQrCode = async (row: any) => {
|
||
qrCodeDialogVisible.value = true
|
||
|
||
// 如果已有二维码URL,直接使用
|
||
if (row.qr_code_pull) {
|
||
qrCodeData.value = row.qr_code_pull
|
||
qrCodeLoading.value = false
|
||
return
|
||
}
|
||
|
||
// 没有二维码URL,调用接口生成
|
||
qrCodeLoading.value = true
|
||
qrCodeData.value = ''
|
||
|
||
try {
|
||
const response = await invitemService.getQrCode({ id: row.id })
|
||
qrCodeData.value = (response as any)?.data?.qr_code_url || ''
|
||
ElMessage.success('二维码生成成功')
|
||
// 刷新列表以更新 qr_code_pull
|
||
getWorkList()
|
||
} catch (error) {
|
||
console.error('生成二维码失败:', error)
|
||
ElMessage.error('生成二维码失败')
|
||
} finally {
|
||
qrCodeLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 关闭二维码弹窗
|
||
const closeQrCodeDialog = () => {
|
||
qrCodeDialogVisible.value = false
|
||
qrCodeData.value = ''
|
||
qrCodeLoading.value = false
|
||
}
|
||
|
||
// 下载二维码
|
||
const downloadQrCode = () => {
|
||
if (!qrCodeData.value) {
|
||
ElMessage.warning('暂无二维码可下载')
|
||
return
|
||
}
|
||
|
||
const link = document.createElement('a')
|
||
link.href = qrCodeData.value
|
||
link.download = `item-qr-code-${Date.now()}.png`
|
||
link.click()
|
||
ElMessage.success('二维码下载成功')
|
||
}
|
||
|
||
// 显示管理员代领弹窗
|
||
const showProxyClaimDialog = (row: any) => {
|
||
proxyClaimDialogVisible.value = true
|
||
proxyClaimForm.item_id = row.id
|
||
proxyClaimForm.target_user_ids = []
|
||
}
|
||
|
||
// 提交管理员代领
|
||
const handleProxyClaimSubmit = async () => {
|
||
if (!proxyClaimForm.target_user_ids || proxyClaimForm.target_user_ids.length === 0) {
|
||
ElMessage.warning('请选择用户')
|
||
return
|
||
}
|
||
|
||
try {
|
||
const { message } = await invitemService.proxyClaim({
|
||
item_id: proxyClaimForm.item_id,
|
||
target_user_id: proxyClaimForm.target_user_ids.join(',')
|
||
})
|
||
ElMessage.success(message)
|
||
proxyClaimDialogVisible.value = false
|
||
getWorkList()
|
||
} catch (error) {
|
||
console.error('管理员代领失败:', error)
|
||
ElMessage.error('操作失败')
|
||
}
|
||
}
|
||
|
||
// 显示库存记录弹窗
|
||
const showStockLogDialog = async (row: any) => {
|
||
currentStockLogItemId.value = row.id
|
||
stockLogDialogVisible.value = true
|
||
// 重置搜索条件和分页
|
||
stockLogSearchForm.change_type = undefined
|
||
stockLogPagination.currentPage = 1
|
||
stockLogPagination.pageSize = 10
|
||
await getStockLogList()
|
||
}
|
||
|
||
// 获取库存记录列表
|
||
const getStockLogList = async () => {
|
||
if (!currentStockLogItemId.value) return
|
||
|
||
stockLogLoading.value = true
|
||
stockLogList.value = []
|
||
|
||
try {
|
||
const params: any = {
|
||
item_id: currentStockLogItemId.value,
|
||
current: stockLogPagination.currentPage,
|
||
size: stockLogPagination.pageSize
|
||
}
|
||
if (stockLogSearchForm.change_type) {
|
||
params.change_type = stockLogSearchForm.change_type
|
||
}
|
||
|
||
const response = await invitemService.getStockLogList(params)
|
||
const records = (response as any)?.data || (response as any)?.records || []
|
||
stockLogList.value = Array.isArray(records) ? records : []
|
||
stockLogPagination.total = (response as any)?.total || 0
|
||
} catch (error) {
|
||
console.error('获取库存记录失败:', error)
|
||
ElMessage.error('获取库存记录失败')
|
||
} finally {
|
||
stockLogLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 搜索库存记录
|
||
const searchStockLog = () => {
|
||
stockLogPagination.currentPage = 1
|
||
getStockLogList()
|
||
}
|
||
|
||
// 重置搜索条件
|
||
const resetStockLogSearch = () => {
|
||
stockLogSearchForm.change_type = undefined
|
||
stockLogPagination.currentPage = 1
|
||
getStockLogList()
|
||
}
|
||
|
||
// 分页大小变化
|
||
const handleStockLogSizeChange = (newPageSize: number) => {
|
||
stockLogPagination.pageSize = newPageSize
|
||
getStockLogList()
|
||
}
|
||
|
||
// 当前页变化
|
||
const handleStockLogCurrentChange = (newCurrentPage: number) => {
|
||
stockLogPagination.currentPage = newCurrentPage
|
||
getStockLogList()
|
||
}
|
||
|
||
// 显示扫码记录弹窗
|
||
const showQrClaimsDialog = async (row: any) => {
|
||
currentQrClaimsItemId.value = row.id
|
||
qrClaimsDialogVisible.value = true
|
||
// 重置搜索条件和分页
|
||
qrClaimsSearchForm.claim_type = undefined
|
||
qrClaimsSearchForm.start_time = ''
|
||
qrClaimsSearchForm.end_time = ''
|
||
qrClaimsPagination.currentPage = 1
|
||
qrClaimsPagination.pageSize = 10
|
||
await getQrClaimsList()
|
||
}
|
||
|
||
// 获取扫码记录列表
|
||
const getQrClaimsList = async () => {
|
||
if (!currentQrClaimsItemId.value) return
|
||
|
||
qrClaimsLoading.value = true
|
||
qrClaimsList.value = []
|
||
|
||
try {
|
||
const params: any = {
|
||
item_id: currentQrClaimsItemId.value,
|
||
current: qrClaimsPagination.currentPage,
|
||
size: qrClaimsPagination.pageSize
|
||
}
|
||
if (qrClaimsSearchForm.claim_type) {
|
||
params.claim_type = qrClaimsSearchForm.claim_type
|
||
}
|
||
if (qrClaimsSearchForm.start_time) {
|
||
params.start_time = qrClaimsSearchForm.start_time
|
||
}
|
||
if (qrClaimsSearchForm.end_time) {
|
||
params.end_time = qrClaimsSearchForm.end_time
|
||
}
|
||
|
||
const response = await invitemService.getQrClaimsList(params)
|
||
const records = (response as any)?.data || (response as any)?.records || []
|
||
qrClaimsList.value = Array.isArray(records) ? records : []
|
||
qrClaimsPagination.total = (response as any)?.total || 0
|
||
} catch (error) {
|
||
console.error('获取扫码记录失败:', error)
|
||
ElMessage.error('获取扫码记录失败')
|
||
} finally {
|
||
qrClaimsLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 搜索扫码记录
|
||
const searchQrClaims = () => {
|
||
qrClaimsPagination.currentPage = 1
|
||
getQrClaimsList()
|
||
}
|
||
|
||
// 重置搜索条件
|
||
const resetQrClaimsSearch = () => {
|
||
qrClaimsSearchForm.claim_type = undefined
|
||
qrClaimsSearchForm.start_time = ''
|
||
qrClaimsSearchForm.end_time = ''
|
||
qrClaimsPagination.currentPage = 1
|
||
getQrClaimsList()
|
||
}
|
||
|
||
// 分页大小变化
|
||
const handleQrClaimsSizeChange = (newPageSize: number) => {
|
||
qrClaimsPagination.pageSize = newPageSize
|
||
getQrClaimsList()
|
||
}
|
||
|
||
// 当前页变化
|
||
const handleQrClaimsCurrentChange = (newCurrentPage: number) => {
|
||
qrClaimsPagination.currentPage = newCurrentPage
|
||
getQrClaimsList()
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
:deep(.el-table__empty-block) {
|
||
height: 100% !important;
|
||
min-height: 200px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.page-content {
|
||
.svg-icon {
|
||
width: 1.8em;
|
||
height: 1.8em;
|
||
overflow: hidden;
|
||
vertical-align: -8px;
|
||
fill: currentcolor;
|
||
}
|
||
}
|
||
.customer-page {
|
||
background: var(--art-main-bg-color);
|
||
min-height: 100vh;
|
||
}
|
||
.customer-search-group {
|
||
display: flex;
|
||
gap: 12px;
|
||
}
|
||
.qr-code-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-height: 300px;
|
||
}
|
||
.qr-code-wrapper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 16px;
|
||
}
|
||
.qr-code-image {
|
||
width: 280px;
|
||
height: 280px;
|
||
object-fit: contain;
|
||
}
|
||
.qr-code-desc {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
color: var(--el-text-color-secondary);
|
||
}
|
||
.qr-code-loading {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 16px;
|
||
color: var(--el-text-color-secondary);
|
||
p {
|
||
margin: 0;
|
||
}
|
||
}
|
||
</style>
|