|
|
@@ -0,0 +1,721 @@
|
|
|
+<template>
|
|
|
+ <view class="page-wrap">
|
|
|
+ <!-- <cu-custom :backUrl="'/pages/index/index'" :isBack="true" bgColor="bg-gradual-blue">
|
|
|
+ <block slot="content">入库列表</block>
|
|
|
+ </cu-custom> -->
|
|
|
+
|
|
|
+ <view class="search-panel">
|
|
|
+ <u-search :show-action="false" v-model="searchForm.wareHouseNumber" placeholder="搜索入库编号"
|
|
|
+ @search="refreshList" @clear="refreshList"></u-search>
|
|
|
+ <view class="filter-grid">
|
|
|
+ <view class="filter-field">
|
|
|
+ <text class="filter-label">入库名称</text>
|
|
|
+ <u--input v-model="searchForm.wareHouseName" placeholder="请输入入库名称" clearable></u--input>
|
|
|
+ </view>
|
|
|
+ <view class="filter-field" @tap="openSupplierPicker">
|
|
|
+ <text class="filter-label">供应商</text>
|
|
|
+ <text class="filter-value">{{ searchForm.supplierName || '全部' }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="filter-field">
|
|
|
+ <text class="filter-label">状态</text>
|
|
|
+ <jp-picker placeholder="全部" v-model="searchForm.status" rangeKey="label" rangeValue="value"
|
|
|
+ :range="statusOptions"></jp-picker>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="action-row">
|
|
|
+ <el-button class="action-button" type="primary" @click="refreshList">查询</el-button>
|
|
|
+ <el-button class="action-button" plain @click="resetSearch">重置</el-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="summary-row">
|
|
|
+ <text>共 {{ tablePage.total }} 条入库记录</text>
|
|
|
+ <text v-if="loading">加载中...</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="!loading && dataList.length === 0" class="empty-state">暂无入库数据</view>
|
|
|
+
|
|
|
+ <view v-for="(item, index) in dataList" :key="item.id || index" class="warehouse-card">
|
|
|
+ <view class="card-head">
|
|
|
+ <view class="warehouse-number" @tap="viewDetail(item)">{{ item.wareHouseNumber || '-' }}</view>
|
|
|
+ 修改申请状态:
|
|
|
+ <view class="status-badge" :class="statusClass(item.status)">{{ statusLabel(item.status) }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="warehouse-name">{{ item.wareHouseName || '-' }}</view>
|
|
|
+
|
|
|
+ <view class="info-grid">
|
|
|
+ <view class="info-item">
|
|
|
+ <text class="info-label">入库时间</text>
|
|
|
+ <text class="info-value">{{ item.wareHouseDate || '-' }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-item">
|
|
|
+ <text class="info-label">经办人</text>
|
|
|
+ <text class="info-value">{{ item.handleByName || item.handledBy || '-' }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-item">
|
|
|
+ <text class="info-label">经办部门</text>
|
|
|
+ <text class="info-value">{{ item.handledByOfficeName || '-' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="card-actions">
|
|
|
+ <el-button class="card-button" plain @click="viewDetail(item)">查看</el-button>
|
|
|
+ <el-button v-if="canApplyUpdate(item)" class="card-button" type="primary" plain
|
|
|
+ @click="pushUpdate(item)">申请修改</el-button>
|
|
|
+ <el-button v-if="canRevoke(item)" class="card-button" type="primary" plain
|
|
|
+ @click="revokeUpdate(item)">撤回</el-button>
|
|
|
+ <el-button v-if="canCancelUpdate(item)" class="card-button" type="danger" plain
|
|
|
+ @click="cancelUpdate(item)">取消修改</el-button>
|
|
|
+ <el-button v-if="canAdjust(item)" class="card-button" type="primary" plain
|
|
|
+ @click="adjustUpdate(item)">驳回调整</el-button>
|
|
|
+ <el-button v-if="canAudit(item)" class="card-button" type="primary" plain
|
|
|
+ @click="auditUpdate(item)">审核</el-button>
|
|
|
+ <el-button v-if="canDelete(item)" class="card-button" type="danger" plain
|
|
|
+ @click="deleteRow(item)">删除</el-button>
|
|
|
+ <el-button v-if="canShowFlowDetail(item)" class="card-button" plain @click="flowDetail(item)">
|
|
|
+ 流程详情
|
|
|
+ </el-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="dataList.length" class="load-more">
|
|
|
+ <text v-if="loadingMore">加载中...</text>
|
|
|
+ <text v-else-if="dataList.length >= tablePage.total">没有更多了</text>
|
|
|
+ <text v-else @tap="loadMore">加载更多</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <ware-house-supplier-picker ref="supplierPicker" @selected="selectSupplier" @clear="clearSupplier">
|
|
|
+ </ware-house-supplier-picker>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { mapState } from 'vuex'
|
|
|
+import WareHouseService from '@/api/psi/WareHouseService'
|
|
|
+import processService from '@/api/flowable/processService'
|
|
|
+import taskService from '@/api/flowable/taskService'
|
|
|
+import userService from '@/api/sys/userService'
|
|
|
+import WareHouseSupplierPicker from '../wareHouseSummary/WareHouseSupplierPicker.vue'
|
|
|
+
|
|
|
+const BUSINESS_TABLE = 'psi_management_warehouse_basics'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'WareHouseList',
|
|
|
+ components: {
|
|
|
+ WareHouseSupplierPicker
|
|
|
+ },
|
|
|
+ computed: mapState({
|
|
|
+ userInfo: (state) => state.user.userInfo
|
|
|
+ }),
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: false,
|
|
|
+ loadingMore: false,
|
|
|
+ isAdmin: false,
|
|
|
+ localUserInfo: null,
|
|
|
+ processDefinitionAuditId: '',
|
|
|
+ procDefAuditKey: '',
|
|
|
+ searchForm: this.createSearchForm(),
|
|
|
+ dataList: [],
|
|
|
+ tablePage: {
|
|
|
+ total: 0,
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ orders: []
|
|
|
+ },
|
|
|
+ statusOptions: [
|
|
|
+ { label: '未发起', value: '0' },
|
|
|
+ { label: '暂存', value: '1' },
|
|
|
+ { label: '审核中', value: '2' },
|
|
|
+ { label: '已撤回', value: '3' },
|
|
|
+ { label: '已驳回', value: '4' },
|
|
|
+ { label: '已完成', value: '5' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ wareHouseService: null,
|
|
|
+ created() {
|
|
|
+ this.wareHouseService = new WareHouseService()
|
|
|
+ this.initPage()
|
|
|
+ },
|
|
|
+ onPullDownRefresh() {
|
|
|
+ this.refreshList().finally(() => {
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onReachBottom() {
|
|
|
+ this.loadMore()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async initPage() {
|
|
|
+ await this.ensureUserInfo()
|
|
|
+ await Promise.all([
|
|
|
+ this.loadProcessDefinition(),
|
|
|
+ this.checkIsAdmin()
|
|
|
+ ])
|
|
|
+ this.refreshList()
|
|
|
+ },
|
|
|
+ createSearchForm() {
|
|
|
+ return {
|
|
|
+ wareHouseName: '',
|
|
|
+ status: '',
|
|
|
+ wareHouseNumber: '',
|
|
|
+ handledBy: '',
|
|
|
+ handledByOffice: '',
|
|
|
+ wareHouseDates: [],
|
|
|
+ procurementType: '',
|
|
|
+ createBy: '',
|
|
|
+ supplierId: '',
|
|
|
+ supplierName: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async loadProcessDefinition() {
|
|
|
+ try {
|
|
|
+ const data = await processService.getByName('进销存-入库修改')
|
|
|
+ this.processDefinitionAuditId = data && data.id
|
|
|
+ this.procDefAuditKey = data && data.key
|
|
|
+ } catch (e) {
|
|
|
+ this.processDefinitionAuditId = ''
|
|
|
+ this.procDefAuditKey = ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async checkIsAdmin() {
|
|
|
+ try {
|
|
|
+ this.isAdmin = await userService.is() === true
|
|
|
+ } catch (e) {
|
|
|
+ this.isAdmin = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async ensureUserInfo() {
|
|
|
+ if (this.currentUserId()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const data = await userService.info()
|
|
|
+ this.localUserInfo = data && data.user
|
|
|
+ if (this.localUserInfo) {
|
|
|
+ this.$store.commit('SET_USERINFO', this.localUserInfo)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this.localUserInfo = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async refreshList() {
|
|
|
+ this.tablePage.currentPage = 1
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const data = await this.wareHouseService.wareHouseList({
|
|
|
+ current: this.tablePage.currentPage,
|
|
|
+ size: this.tablePage.pageSize,
|
|
|
+ orders: this.tablePage.orders,
|
|
|
+ ...this.searchForm
|
|
|
+ })
|
|
|
+ this.dataList = (data && data.records) || []
|
|
|
+ this.tablePage.total = (data && data.total) || 0
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async loadMore() {
|
|
|
+ if (this.loading || this.loadingMore || this.dataList.length >= this.tablePage.total) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.loadingMore = true
|
|
|
+ try {
|
|
|
+ const nextPage = this.tablePage.currentPage + 1
|
|
|
+ const data = await this.wareHouseService.wareHouseList({
|
|
|
+ current: nextPage,
|
|
|
+ size: this.tablePage.pageSize,
|
|
|
+ orders: this.tablePage.orders,
|
|
|
+ ...this.searchForm
|
|
|
+ })
|
|
|
+ this.dataList = this.dataList.concat((data && data.records) || [])
|
|
|
+ this.tablePage.currentPage = nextPage
|
|
|
+ this.tablePage.total = (data && data.total) || this.tablePage.total
|
|
|
+ } finally {
|
|
|
+ this.loadingMore = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ resetSearch() {
|
|
|
+ this.searchForm = this.createSearchForm()
|
|
|
+ this.refreshList()
|
|
|
+ },
|
|
|
+ openSupplierPicker() {
|
|
|
+ this.$refs.supplierPicker.open()
|
|
|
+ },
|
|
|
+ selectSupplier(item) {
|
|
|
+ this.searchForm.supplierId = item.id || ''
|
|
|
+ this.searchForm.supplierName = item.name || ''
|
|
|
+ this.refreshList()
|
|
|
+ },
|
|
|
+ clearSupplier() {
|
|
|
+ this.searchForm.supplierId = ''
|
|
|
+ this.searchForm.supplierName = ''
|
|
|
+ this.refreshList()
|
|
|
+ },
|
|
|
+ viewDetail(row) {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/psiManagement/wareHouse/WareHouseUpdateForm?id=${row.id}&method=view&readOnly=true`
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async pushUpdate(row) {
|
|
|
+ await this.ensureRowStatus(row, ['0', '3', '4', '5'])
|
|
|
+ const status = this.normalizeStatus(row.status) === '4' ? 'reapplyFlag' : 'startAndClose'
|
|
|
+ await this.openStartTask(row, status)
|
|
|
+ },
|
|
|
+ async adjustUpdate(row) {
|
|
|
+ await this.ensureRowStatus(row, ['4'])
|
|
|
+ await this.openTodoTask(row)
|
|
|
+ },
|
|
|
+ async auditUpdate(row) {
|
|
|
+ await this.ensureRowStatus(row, ['2'])
|
|
|
+ await this.openTodoTask(row)
|
|
|
+ },
|
|
|
+ async openStartTask(row, status) {
|
|
|
+ await this.ensureProcessDefinition()
|
|
|
+ const data = await taskService.getTaskDef({
|
|
|
+ procDefId: this.processDefinitionAuditId,
|
|
|
+ businessId: row.id,
|
|
|
+ businessTable: BUSINESS_TABLE
|
|
|
+ })
|
|
|
+ const title = '发起流程【入库修改】'
|
|
|
+ const processTitle = `${this.currentUserName()} 在 ${this.formatMinute(new Date())} 发起了[入库修改]`
|
|
|
+ const flow = {
|
|
|
+ ...this.pickTaskDef(data),
|
|
|
+ procDefId: this.processDefinitionAuditId,
|
|
|
+ procDefKey: this.procDefAuditKey,
|
|
|
+ title,
|
|
|
+ formType: data.formType,
|
|
|
+ formUrl: data.formUrl,
|
|
|
+ formTitle: processTitle,
|
|
|
+ businessTable: BUSINESS_TABLE,
|
|
|
+ businessId: row.id,
|
|
|
+ isShow: 'false',
|
|
|
+ status,
|
|
|
+ routePath: '/psiManagement/wareHouse/WareHouseList',
|
|
|
+ wareHouseId: row.id
|
|
|
+ }
|
|
|
+ this.navigateTaskForm(flow)
|
|
|
+ },
|
|
|
+ async openTodoTask(row) {
|
|
|
+ const data = await taskService.getTaskDefInfo({
|
|
|
+ taskId: row.taskId
|
|
|
+ })
|
|
|
+ const flow = {
|
|
|
+ ...this.pickTaskDef(data),
|
|
|
+ isShow: false,
|
|
|
+ formReadOnly: true,
|
|
|
+ formTitle: `${data.taskName || ''}`,
|
|
|
+ cUser: false,
|
|
|
+ title: `审批【${data.taskName || ''}】`,
|
|
|
+ routePath: '/psiManagement/wareHouse/WareHouseList',
|
|
|
+ wareHouseId: row.id,
|
|
|
+ businessId: data.businessId || row.id
|
|
|
+ }
|
|
|
+ this.navigateTaskForm(flow)
|
|
|
+ },
|
|
|
+ navigateTaskForm(flow) {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/workbench/task/TaskForm?flow=${encodeURIComponent(JSON.stringify(flow))}`
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async flowDetail(row) {
|
|
|
+ await this.ensureProcessDefinition()
|
|
|
+ const data = await taskService.getTaskDef({
|
|
|
+ procInsId: row.procInsId,
|
|
|
+ procDefId: this.processDefinitionAuditId
|
|
|
+ })
|
|
|
+ const flow = {
|
|
|
+ ...this.pickTaskDef(data),
|
|
|
+ isShow: 'false',
|
|
|
+ readOnly: true,
|
|
|
+ title: '入库修改流程详情',
|
|
|
+ formTitle: '入库修改流程详情',
|
|
|
+ businessId: row.id,
|
|
|
+ status: 'reback',
|
|
|
+ wareHouseId: row.id
|
|
|
+ }
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/workbench/task/TaskFormDetail?flow=${encodeURIComponent(JSON.stringify(flow))}`
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async revokeUpdate(row) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '确定要撤回该申请吗?',
|
|
|
+ success: async res => {
|
|
|
+ if (!res.confirm) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ await this.ensureRowStatus(row, ['2'])
|
|
|
+ const msg = await processService.revokeProcIns(row.procInsId)
|
|
|
+ await this.wareHouseService.updateStatusById({
|
|
|
+ status: '3',
|
|
|
+ id: row.id
|
|
|
+ })
|
|
|
+ uni.showToast({
|
|
|
+ title: msg || '撤回成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+ this.refreshList()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async cancelUpdate(row) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '确定要取消修改申请吗?',
|
|
|
+ success: async res => {
|
|
|
+ if (!res.confirm) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ await this.ensureRowStatus(row, ['3'])
|
|
|
+ const data = await this.wareHouseService.backSourceData(row.id)
|
|
|
+ uni.showToast({
|
|
|
+ title: data && data.result === 'success' ? '取消修改申请成功' : '取消修改申请失败',
|
|
|
+ icon: data && data.result === 'success' ? 'success' : 'none'
|
|
|
+ })
|
|
|
+ this.refreshList()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async deleteRow(row) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '确定删除该入库记录吗?',
|
|
|
+ success: async res => {
|
|
|
+ if (!res.confirm) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const msg = await this.wareHouseService.remove(row.id)
|
|
|
+ uni.showToast({
|
|
|
+ title: msg || '删除成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+ this.refreshList()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async ensureRowStatus(row, allowedStatuses) {
|
|
|
+ const data = await this.wareHouseService.findById(row.id)
|
|
|
+ if (!allowedStatuses.includes(this.normalizeStatus(data.status))) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '数据已发生改变或不存在,请刷新数据1',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ this.refreshList()
|
|
|
+ throw new Error('invalid status')
|
|
|
+ }
|
|
|
+ return data
|
|
|
+ },
|
|
|
+ async ensureProcessDefinition() {
|
|
|
+ if (!this.processDefinitionAuditId) {
|
|
|
+ await this.loadProcessDefinition()
|
|
|
+ }
|
|
|
+ if (!this.processDefinitionAuditId) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '未找到入库修改流程',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ throw new Error('missing process definition')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ pickTaskDef(data) {
|
|
|
+ const keys = ['formType', 'formUrl', 'procDefKey', 'taskDefKey', 'procInsId', 'procDefId', 'taskId', 'status', 'title']
|
|
|
+ return keys.reduce((target, key) => {
|
|
|
+ if (data && Object.prototype.hasOwnProperty.call(data, key)) {
|
|
|
+ target[key] = data[key]
|
|
|
+ }
|
|
|
+ return target
|
|
|
+ }, {})
|
|
|
+ },
|
|
|
+ currentUser() {
|
|
|
+ return this.localUserInfo || this.userInfo || {}
|
|
|
+ },
|
|
|
+ normalizeId(id) {
|
|
|
+ if (id === null || id === undefined) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ return String(id)
|
|
|
+ },
|
|
|
+ normalizeStatus(status) {
|
|
|
+ if (status === null || status === undefined) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ return String(status)
|
|
|
+ },
|
|
|
+ currentUserId() {
|
|
|
+ const user = this.currentUser()
|
|
|
+ return this.normalizeId(user.id || user.userId)
|
|
|
+ },
|
|
|
+ currentUserName() {
|
|
|
+ const user = this.currentUser()
|
|
|
+ return user.name || user.realname || ''
|
|
|
+ },
|
|
|
+ statusLabel(status) {
|
|
|
+ const item = this.statusOptions.find(option => option.value === this.normalizeStatus(status))
|
|
|
+ return item ? item.label : '-'
|
|
|
+ },
|
|
|
+ statusClass(status) {
|
|
|
+ const currentStatus = this.normalizeStatus(status)
|
|
|
+ return {
|
|
|
+ 'status-badge--draft': currentStatus === '0' || currentStatus === '1',
|
|
|
+ 'status-badge--audit': currentStatus === '2',
|
|
|
+ 'status-badge--revoke': currentStatus === '3',
|
|
|
+ 'status-badge--reject': currentStatus === '4',
|
|
|
+ 'status-badge--done': currentStatus === '5'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ canApplyUpdate(row) {
|
|
|
+ const status = this.normalizeStatus(row.status)
|
|
|
+ return this.isCreatedByMe(row) && ['0', '3', '5'].includes(status)
|
|
|
+ },
|
|
|
+ canRevoke(row) {
|
|
|
+ return this.isCreatedByMe(row) && this.normalizeStatus(row.status) === '2'
|
|
|
+ },
|
|
|
+ canCancelUpdate(row) {
|
|
|
+ return this.isCreatedByMe(row) && this.normalizeStatus(row.status) === '3'
|
|
|
+ },
|
|
|
+ canAdjust(row) {
|
|
|
+ return this.isCreatedByMe(row) && this.normalizeStatus(row.status) === '4'
|
|
|
+ },
|
|
|
+ canAudit(row) {
|
|
|
+ return this.normalizeStatus(row.status) === '2' && this.isAuditUser(row)
|
|
|
+ },
|
|
|
+ canDelete(row) {
|
|
|
+ return this.isAdmin && ['0', '5'].includes(this.normalizeStatus(row.status))
|
|
|
+ },
|
|
|
+ canShowFlowDetail(row) {
|
|
|
+ const status = this.normalizeStatus(row.status)
|
|
|
+ return status && !['0', '1'].includes(status)
|
|
|
+ },
|
|
|
+ isCreatedByMe(row) {
|
|
|
+ const createBy = row.createBy || row.createById || row.userId || row.handledById
|
|
|
+ return this.normalizeId(createBy) === this.currentUserId()
|
|
|
+ },
|
|
|
+ isAuditUser(row) {
|
|
|
+ const userId = this.currentUserId()
|
|
|
+ if (!userId) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const auditUserIds = Array.isArray(row.auditUserIds)
|
|
|
+ ? row.auditUserIds
|
|
|
+ : String(row.auditUserIds || '').split(',')
|
|
|
+ return auditUserIds.some(id => this.normalizeId(id).trim() === userId)
|
|
|
+ },
|
|
|
+ formatMinute(date) {
|
|
|
+ const d = new Date(date)
|
|
|
+ const year = d.getFullYear()
|
|
|
+ const month = `${d.getMonth() + 1}`.padStart(2, '0')
|
|
|
+ const day = `${d.getDate()}`.padStart(2, '0')
|
|
|
+ const hour = `${d.getHours()}`.padStart(2, '0')
|
|
|
+ const minute = `${d.getMinutes()}`.padStart(2, '0')
|
|
|
+ return `${year}-${month}-${day} ${hour}:${minute}`
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.page-wrap {
|
|
|
+ min-height: 100vh;
|
|
|
+ padding: 20rpx 24rpx 48rpx;
|
|
|
+ background: #f6f8fb;
|
|
|
+}
|
|
|
+
|
|
|
+.search-panel {
|
|
|
+ padding: 22rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 18rpx;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.05);
|
|
|
+}
|
|
|
+
|
|
|
+.filter-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
|
+ gap: 16rpx;
|
|
|
+ margin-top: 18rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-field {
|
|
|
+ min-width: 0;
|
|
|
+ padding: 18rpx 20rpx;
|
|
|
+ background: #f8fafc;
|
|
|
+ border-radius: 14rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-label {
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: #64748b;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-value {
|
|
|
+ display: block;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #0f172a;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.action-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 16rpx;
|
|
|
+ margin-top: 18rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.action-button {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.action-row /deep/ .el-button {
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.action-row /deep/ .el-button+.el-button {
|
|
|
+ margin-left: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.summary-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 22rpx 4rpx 12rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #64748b;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state {
|
|
|
+ padding: 120rpx 0;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #94a3b8;
|
|
|
+}
|
|
|
+
|
|
|
+.warehouse-card {
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ padding: 24rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 18rpx;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.05);
|
|
|
+}
|
|
|
+
|
|
|
+.card-head {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.warehouse-number {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #2979ff;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+
|
|
|
+.warehouse-name {
|
|
|
+ margin-top: 12rpx;
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #0f172a;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge {
|
|
|
+ padding: 8rpx 16rpx;
|
|
|
+ border-radius: 999rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
+ font-weight: 700;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge--draft {
|
|
|
+ color: #475569;
|
|
|
+ background: #e2e8f0;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge--audit {
|
|
|
+ color: #1d4ed8;
|
|
|
+ background: #dbeafe;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge--revoke {
|
|
|
+ color: #92400e;
|
|
|
+ background: #fef3c7;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge--reject {
|
|
|
+ color: #b91c1c;
|
|
|
+ background: #fee2e2;
|
|
|
+}
|
|
|
+
|
|
|
+.status-badge--done {
|
|
|
+ color: #166534;
|
|
|
+ background: #dcfce7;
|
|
|
+}
|
|
|
+
|
|
|
+.info-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
|
+ gap: 14rpx;
|
|
|
+ margin-top: 18rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.info-item {
|
|
|
+ padding: 16rpx 18rpx;
|
|
|
+ background: #f8fafc;
|
|
|
+ border-radius: 14rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.info-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: #64748b;
|
|
|
+}
|
|
|
+
|
|
|
+.info-value {
|
|
|
+ display: block;
|
|
|
+ margin-top: 8rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #0f172a;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+
|
|
|
+.card-actions {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
+ gap: 14rpx;
|
|
|
+ margin-top: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.card-button {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.card-actions /deep/ .el-button {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 64rpx;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0 12rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ line-height: 1.2;
|
|
|
+}
|
|
|
+
|
|
|
+.card-actions /deep/ .el-button+.el-button {
|
|
|
+ margin-left: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.load-more {
|
|
|
+ padding: 24rpx 0;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #64748b;
|
|
|
+}
|
|
|
+</style>
|