| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- <template>
- <div :style="{ backgroundColor: bgColor }">
- <q-dialog
- v-model="storage_dialog"
- transition-show="jump-down"
- transition-hide="jump-up"
- @show="prepareDialog()"
- >
- <q-card style="min-width: 1000px">
- <q-bar
- class="bg-light-blue-10 text-white rounded-borders"
- style="height: 50px"
- >
- <div>
- {{ "托盘" }}
- </div>
- <q-space></q-space>
- {{ containerCode }}
- </q-bar>
- <q-card-section class="q-pt-md">
- <q-tabs v-model="activeTab">
- <q-tab name="tab2" label="托盘信息" />
- <q-tab name="tab3" label="托盘详情" />
- <q-tab name="tab1" label="操作记录" />
- </q-tabs>
- </q-card-section>
- <q-tab-panels v-model="activeTab" animated>
- <q-tab-panel name="tab2" style="height: 600px">
- <template>
- <div class="text-h6 q-mb-md">{{ "托盘信息" }}</div>
- <q-table
- v-if="storage_form.length > 0"
- :data="storage_form"
- :columns="columns_batch"
- row-key="id"
- flat
- bordered
- hide-pagination
- class="my-sticky-table scrollable-table"
- :style="{ 'max-height': '400px' }"
- :container-style="{ height: 'auto' }"
- :pagination="{ rowsPerPage: 0 }"
- >
- </q-table>
- <div style="float: right; min-width: 100%" flow="row wrap">
- <q-card class="q-mb-md" bordered>
- <q-card-actions
- class="q-px-none"
- style="
- position: absolute;
- right: 20px;
- top: 10px;
- z-index: 100;
- "
- >
- <q-btn
- flat
- dense
- color="primary"
- @click="showInventoryDetails = !showInventoryDetails"
- >
- {{ showInventoryDetails ? "收起" : "展开" }}
- </q-btn>
- </q-card-actions>
- <q-card-section>
- <div class="text-h6 q-mb-md">
- {{ "物料详情" }}
- </div>
- <q-table
- v-if="showInventoryDetails"
- :data="results"
- :columns="columns_results"
- row-key="id"
- flat
- bordered
- hide-pagination
- class="my-sticky-table scrollable-table"
- :style="{ 'max-height': '400px' }"
- :container-style="{ height: 'auto' }"
- :pagination="{ rowsPerPage: 0 }"
- >
- </q-table>
- </q-card-section>
- </q-card>
- </div>
- </template>
- </q-tab-panel>
- <q-tab-panel name="tab3" style="height: 600px">
- <q-table
- :data="container_table"
- :columns="coloums_container"
- row-key="id"
- flat
- bordered
- hide-pagination
- class="my-sticky-table scrollable-table"
- :style="{ 'max-height': '600px' }"
- :container-style="{ height: 'auto' }"
- :pagination="{ rowsPerPage: 0 }"
- >
- <template v-slot:body-cell-actions="props">
- <q-td :props="props">
- <q-btn
- dense
- round
- color="primary"
- icon="edit"
- @click="handleRowEdit(props.row)"
- >
- <q-tooltip>编辑该行数据</q-tooltip>
- </q-btn>
- <q-btn
- dense
- round
- color="primary"
- icon="delete"
- @click="handleRowdelete(props.row)"
- >
- <q-tooltip>删除该行数据</q-tooltip>
- </q-btn>
- </q-td>
- </template>
- </q-table>
- </q-tab-panel>
- <q-tab-panel name="tab1" style="height: 600px">
- <div
- style="
- float: right;
- padding: 15px 15px 50px 15px;
- min-width: 100%;
- "
- flow="row wrap"
- >
- <q-card class="q-mb-md" bordered>
- <q-card-section>
- <template>
- <div
- class="text-h6 q-mb-md"
- style="display: flex; justify-content: space-between"
- >
- {{ "操作记录" }}
- </div>
- <q-btn
- class="q-ml-sm"
- color="primary"
- icon="event"
- @click="sortoperatedetail"
- >近一个月操作记录</q-btn
- >
- <template v-if="listSize > 0">
- <q-list bordered class="rounded-borders">
- <q-expansion-item
- v-for="(node, index) in nodeList"
- v-if="node.value && node.value.length > 0"
- :key="index"
- group="op-group"
- :caption="`操作类型: ${formatType(
- node.value[0].operation_type
- )} ----- 操作时间:${node.value[0].timestamp}`"
- >
- <q-card>
- <q-card-section>
- <q-table
- :data="node.value"
- :columns="columns_operate"
- row-key="id"
- flat
- bordered
- hide-pagination
- class="my-sticky-table scrollable-table"
- :style="{ 'max-height': '400px' }"
- :container-style="{ height: 'auto' }"
- :pagination="{ rowsPerPage: 0 }"
- >
- </q-table>
- </q-card-section>
- </q-card>
- </q-expansion-item>
- </q-list>
- </template>
- <div v-else class="text-grey-8">暂无操作记录</div>
- </template>
- </q-card-section>
- </q-card>
- </div>
- </q-tab-panel>
- </q-tab-panels>
- <div style="float: right; padding: 15px 15px 15px 0">
- <q-btn
- color="primary"
- text-color="white"
- style="margin-right: 25px"
- @click="handleEdit()"
- >
- {{
- can_edit_detail
- ? $t("stock.shelf.shelf_edit")
- : $t("stock.shelf.shelf_confirm")
- }}</q-btn
- >
- </div>
- </q-card>
- </q-dialog>
- </div>
- </template>
- <script>
- class ListNode {
- constructor (value) {
- this.value = value
- this.next = null
- }
- }
- class LinkedList {
- constructor () {
- this.head = null
- this.size = 0
- }
- append (value) {
- const newNode = new ListNode(value)
- if (!this.head) {
- this.head = newNode
- } else {
- let current = this.head
- while (current.next) {
- current = current.next
- }
- current.next = newNode
- }
- this.size++
- }
- delete (value) {
- if (!this.head) return
- if (this.head.value === value) {
- this.head = this.head.next
- this.size--
- return
- }
- let current = this.head
- while (current.next) {
- if (current.next.value === value) {
- current.next = current.next.next
- this.size--
- return
- }
- current = current.next
- }
- }
- toArray () {
- const result = []
- let current = this.head
- while (current) {
- result.push({ value: current.value })
- current = current.next
- }
- return result
- }
- clear () {
- this.head = null
- this.size = 0
- }
- }
- import { getauth, putauth, deleteauth } from 'boot/axios_request'
- import { LocalStorage } from 'quasar'
- export default {
- props: {
- containerCode: Number,
- containerNumber: Number
- },
- data () {
- return {
- pathnamecontainer: 'container/locationdetail/',
- pathnamecontainer_detail: 'container/containerdetail/',
- container_id: 123456,
- results: [],
- container_table: [],
- storage_form: [],
- showInventoryDetails: true,
- columns_batch: [
- {
- name: 'bound_number',
- label: '批次',
- field: (row) => row.bound_number,
- align: 'center'
- },
- {
- name: 'plan_weight',
- label: '当前库位容纳重量',
- field: (row) => row.total_batch_qty,
- align: 'center'
- }
- ],
- columns_results: [
- {
- label: '物料编码',
- field: (row) => row.goods_code,
- align: 'center'
- },
- {
- label: '物料名称',
- field: (row) => row.goods_desc,
- align: 'center'
- },
- {
- label: '物料批次',
- field: (row) => row.bound_number,
- align: 'center'
- },
- {
- label: '件数',
- field: (row) => row.group_qty,
- align: 'center'
- },
- {
- label: '每件重量',
- field: (row) => row.goods_qty,
- align: 'center'
- },
- {
- label: '批次计划重量',
- field: (row) => row.batch_total_qty,
- align: 'center'
- },
- {
- label: '在库重量',
- field: (row) => row.batch_total_in_qty,
- align: 'center'
- },
- {
- label: '录入时间',
- field: (row) => row.create_time.slice(0, 10),
- align: 'center'
- }
- ],
- coloums_container: [
- {
- label: '物料编码',
- field: (row) => row.goods_code,
- align: 'center'
- },
- {
- label: '物料名称',
- field: (row) => row.goods_desc,
- align: 'center'
- },
- {
- label: '物料批次',
- field: (row) => row.batch,
- align: 'center'
- },
- {
- label: '入库重量',
- field: (row) => row.goods_qty,
- align: 'center',
- sortable: true
- },
- {
- label: '出库重量',
- field: (row) => row.goods_out_qty,
- align: 'center',
- sortable: true
- },
- {
- label: '编辑',
- name: 'actions', // 必须与插槽名对应
- align: 'center',
- field: 'actions', // 指向数据字段(可为空)
- sortable: false, // 禁用排序
- headerStyle: 'width: 80px' // 固定列宽
- }
- ],
- columns_operate: [
- {
- name: 'timestamp',
- label: '操作时间',
- field: (row) => row.timestamp,
- align: 'center'
- },
- {
- name: 'operator',
- label: '经手人',
- field: (row) => row.operator,
- align: 'center'
- },
- {
- name: 'batch',
- label: '批次',
- field: (row) => row.batch.bound_number,
- align: 'center'
- },
- {
- name: 'memo',
- label: '备注',
- field: (row) => row.memo,
- align: 'center'
- },
- {
- label: '当前位置',
- field: (row) => row.from_location,
- align: 'center'
- },
- {
- label: '目标位置',
- field: (row) => row.to_location,
- align: 'center'
- }
- ],
- user_id: '',
- auth_id: '',
- can_edit_detail: false,
- storage_dialog: false,
- bgColor: 'transparent',
- error1: this.$t('stock.shelf.error1'),
- shelfLocal: '',
- activeTab: 'tab2',
- operate_detail: [],
- linkedList: new LinkedList()
- }
- },
- created () {
- this.handleclick()
- },
- computed: {
- nodeList () {
- return this.linkedList.toArray()
- },
- listSize () {
- return this.linkedList.size
- }
- },
- methods: {
- sortoperatedetail () {
- var _this = this
- console.log('近一个月操作记录', _this.nodeList)
- },
- formatType (type) {
- switch (type) {
- case 'container':
- return '组盘'
- case 'outbound':
- return '出库'
- case 'inbound':
- return '入库'
- case 'adjust':
- return '移库'
- case '5':
- return '调拨'
- case '6':
- return '其他'
- default:
- return '未知'
- }
- },
- getOperationRecord () {
- var _this = this
- _this.operate_detail = []
- var operate_detail_container = []
- _this.linkedList.clear()
- getauth('container/operate/?status=1&container=' + _this.containerNumber)
- .then((res) => {
- _this.operate_detail = res.results
- if (_this.operate_detail.length === 0) return
- // 初始化第一个元素
- operate_detail_container.push(_this.operate_detail[0])
- for (let i = 0; i < _this.operate_detail.length - 1; i++) {
- const current = _this.operate_detail[i]
- const next = _this.operate_detail[i + 1]
- if (current.operation_type === next.operation_type) {
- operate_detail_container.push(next)
- } else {
- _this.linkedList.append([...operate_detail_container])
- operate_detail_container = [next]
- }
- }
- // 添加最后一个分组
- if (operate_detail_container.length > 0) {
- _this.linkedList.append([...operate_detail_container])
- }
- })
- .catch((err) => {
- _this.$q.notify({
- message: err.detail,
- icon: 'close',
- color: 'negative'
- })
- })
- },
- handleRowdelete (rowData) {
- if (this.can_edit_detail === true) {
- console.log('当前行数据:', rowData)
- this.$q
- .dialog({
- title: '删除物料信息',
- message: `确定删除 ${rowData.goods_code} 吗?`,
- ok: { label: '确定', color: 'negative' },
- cancel: { label: '取消', color: 'primary' }
- })
- .onOk(() => {
- this.deleteContainerData(rowData)
- })
- } else {
- this.$q.notify({
- message: '权限不足,请联系管理员',
- icon: 'close',
- color: 'negative'
- })
- }
- },
- async deleteContainerData (rowData) {
- try {
- const res = await deleteauth(`container/detail/${rowData.id}/`)
- this.$q.notify({
- message: '删除成功',
- color: 'positive'
- })
- this.get_container_table() // 刷新数据
- } catch (err) {
- this.$q.notify({
- message: '删除失败: ' + err.message,
- color: 'negative'
- })
- }
- },
- handleRowEdit (rowData) {
- if (this.can_edit_detail === true) {
- console.log('当前行数据:', rowData)
- this.$q
- .dialog({
- title: '编辑物料信息',
- message: `正在编辑 ${rowData.goods_code}`,
- prompt: {
- model: rowData.goods_qty,
- type: 'number',
- label: '入库重量',
- isValid: (val) => val >= 0 // 验证输入
- },
- persistent: true
- })
- .onOk((value) => {
- // 调用API更新数据
- this.updateContainerData(rowData, value)
- })
- } else {
- this.$q.notify({
- message: '权限不足,请联系管理员',
- icon: 'close',
- color: 'negative'
- })
- }
- },
- async updateContainerData (rowData, newValue) {
- try {
- const res = await putauth(`container/detail/${rowData.id}/`, {
- goods_code: rowData.goods_code,
- goods_desc: rowData.goods_desc,
- goods_weight: 1,
- goods_qty: newValue
- })
- this.$q.notify({
- message: '更新成功',
- color: 'positive'
- })
- this.get_container_table() // 刷新数据
- } catch (err) {
- this.$q.notify({
- message: '更新失败: ' + err.message,
- color: 'negative'
- })
- }
- },
- prepareDialog () {
- this.can_edit_detail = false
- },
- handleEdit () {
- console.log('点击', this.can_edit_detail)
- if (this.can_edit_detail === false) {
- this.user_id = LocalStorage.getItem('login_mode')
- this.auth_id = LocalStorage.getItem('auth_edit')
- console.log(this.auth_id)
- if (this.auth_id === true) {
- this.can_edit_detail = true
- } else {
- this.can_edit_detail = false
- }
- if (this.user_id === 'Admin') {
- this.can_edit_detail = true
- }
- }
- if (this.can_edit_detail === true) {
- this.$q.notify({
- message: '开始编辑托盘信息',
- color: 'positive'
- })
- } else {
- this.$q.notify({
- message: '权限不足,请联系管理员',
- icon: 'close',
- color: 'negative'
- })
- }
- },
- handleclick () {
- this.getList()
- this.get_container_table()
- this.getOperationRecord()
- this.storage_dialog = true
- },
- get_container_table () {
- var _this = this
- getauth(
- _this.pathnamecontainer_detail + '?container=' + _this.containerNumber
- ).then((res) => {
- var data = res.data
- this.container_table = data
- })
- },
- getList () {
- var _this = this
- _this.storage_form = []
- _this.results = []
- getauth(
- _this.pathnamecontainer + '?container=' + _this.containerNumber
- ).then((res) => {
- var data = res.data
- this.storage_form = data.batch_totals
- this.results = data.results
- })
- }
- }
- }
- </script>
- <style scoped>
- :deep(.q-field__label) {
- margin-top: 8px;
- align-self: center;
- }
- :deep(.q-field__control-container) {
- padding-left: 50px;
- margin-top: -5px;
- }
- </style>
|