fix: 入库页面问题修复

main
wx-jincw 7 days ago
parent 38f7ec3bc2
commit 04c4bc9819

@ -47,7 +47,7 @@
"core-js": "^2.6.11",
"crypto-js": "^4.1.1",
"echarts": "4.2.1",
"element-ui": "2.13.0",
"element-ui": "^2.15.14",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"highlight.js": "10.5.0",
@ -60,6 +60,7 @@
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"qrcodejs2": "^0.0.2",
"quill": "1.3.7",
"sass": "1.26.2",
"sass-loader": "^7.2.0",
"screenfull": "4.2.0",
@ -75,8 +76,7 @@
"vuex": "3.1.0",
"wechat-jssdk": "^5.0.4",
"xlsx": "0.14.1",
"xml-js": "1.6.11",
"quill": "1.3.7"
"xml-js": "1.6.11"
},
"devDependencies": {
"@babel/core": "7.0.0",

@ -0,0 +1,457 @@
<template>
<div class="bm-select">
<el-popover
ref="popper"
trigger="manual"
placement="bottom-start"
popper-class="bm-select-popover"
v-model="expand">
<el-input
slot="reference"
ref="input"
v-model="inputLabel"
:disabled="disabled"
:readonly="readonly"
:placeholder="placeholder"
@input="handleInput"
@blur="handleInputBlur"
@focus="handleInputFocus"
@keydown.down.native.prevent="handleNavigate(1)"
@keydown.up.native.prevent="handleNavigate(-1)"
@keydown.enter.native.prevent="handleEnter"
></el-input>
<div v-if="expand" class="option-content" :style="{ maxHeight: maxHeight + 'px' }">
<div v-for="(item, index) in searchOptions" :key="idKey ? item[idKey] : item[valueKey]"
class="option-item"
:class="{ 'option-item-hover': hoverIndex === index }"
@mousedown.prevent="handleSelectOption(item, index)"
>
<span v-if="showValue">{{ item[valueKey] }}-</span>
<span class="option-label">{{ item[labelKey] }}</span>
<span v-if="showSort" class="option-code">{{ item[sortKey] }}</span>
<span v-if="showCode" class="option-code">{{ item[codeKey] }}</span>
</div>
</div>
</el-popover>
</div>
</template>
<script>
export default {
name: 'BMSelect',
props: {
enterIndex: [Number],
value: [String, Number],
options: {
type: Array,
default: () => []
},
// keyvalue
idKey: [String],
valueKey: {
type: String,
default: 'value'
},
labelKey: {
type: String,
default: 'label'
},
codeKey: {
type: String,
default: 'code'
},
sortKey: {
type: String,
default: 'sort'
},
placeholder: {
type: String,
default: ''
},
//
showValue: {
type: Boolean,
default: true
},
//
showCode: {
type: Boolean,
default: false
},
//
showSort: {
type: Boolean,
default: false
},
//
forceOption: {
type: Boolean,
default: true
},
// 使
forceString: {
type: Boolean,
default: true
},
//
maxOptionCount: {
type: Number,
default: 20
},
//
autoSelectText: {
type: Boolean,
default: true
},
disabled: [Boolean],
readonly: [Boolean],
maxHeight: {
type: Number,
default: 320
},
// 使labelKey
inputDisplayKey: {
type: String,
default: '',
}
},
model: {
prop: 'value',
event: 'change'
},
watch: {
value: {
immediate: true,
handler(val) {
let recValue = val;
if (recValue !== undefined && recValue !== null && this.forceString && typeof recValue !== 'string') {
recValue = recValue.toString();
}
if (recValue === this.innerValue) {
return;
}
this.innerValue = recValue || '';
//
this.inputLabel = this.getSelectedLabel();
//
if (!this.inputLabel) {
this.handleSearch();
this.inputLabel = this.getSelectedLabel();
}
this.hoverIndex = this.tempSelectedIndex;
if (this.hoverIndex === -1) {
this.hoverIndex = 0;
}
}
},
options: {
immediate: true,
handler() {
this.handleSearch();
//
if (this.innerValue && !this.inputLabel) {
this.inputLabel = this.getSelectedLabel();
this.hoverIndex = this.tempSelectedIndex;
if (this.hoverIndex === -1) {
this.hoverIndex = 0;
}
}
}
}
},
data () {
return {
expand: false,
//
innerValue: null,
//
inputLabel: null,
//
searchTimer: null,
//
searchOptions: [],
tempSelectedIndex: -1,
hoverIndex: 0,
//
isFocus: false,
};
},
methods: {
getSelectedIndex() {
if (!this.innerValue) {
this.tempSelectedIndex = -1;
return this.tempSelectedIndex;
}
this.tempSelectedIndex = this.searchOptions?.findIndex(item => item[this.valueKey] === this.innerValue);
return this.tempSelectedIndex;
},
getSelectedOption() {
const selectIndex = this.getSelectedIndex();
return selectIndex > -1 ? this.searchOptions?.[selectIndex] : {};
},
getSelectedLabel() {
return this.getSelectedOption()[this.inputDisplayKey || this.labelKey] || '';
},
// getOrgSelectedLabel() {
// const index = this.options?.findIndex(item => item[this.valueKey] === this.innerValue);
// return index > -1 ? this.options?.[index][this.labelKey] : '';
// },
//
handleSelectOption(option, index = this.tempSelectedIndex, blur) {
this.tempSelectedIndex = index;
this.hoverIndex = index;
this.innerValue = option[this.valueKey];
this.inputLabel = option[this.labelKey];
this.handleValueChange(option);
if (blur) {
this.handleBlur();
} else {
this.handleUnexpand();
}
},
//
handleInput() {
if (this.inputLabel.length > 0) {
this.inputLabel = this.inputLabel.trim();
this.handleDelaySearch();
return;
}
if (this.expand) {
this.handleDelaySearch();
}
},
//
handleDelaySearch() {
if (!this.expand) {
this.handleSearch();
this.hoverIndex = 0;
if (this.searchOptions.length > 0) {
this.handleExpand();
}
}
if (this.searchTimer) {
clearTimeout(this.searchTimer);
}
this.searchTimer = setTimeout(() => {
this.handleSearch();
this.hoverIndex = 0;
if (this.searchOptions.length === 0) {
this.handleUnexpand();
if (this.forceOption) {
this.$message.error('没有匹配的选项');
this.inputLabel = '';
this.innerValue = '';
this.handleValueChange();
}
} else if (this.isFocus) {
this.handleExpand();
}
}, 300);
},
//
handleSearch() {
if (!this.inputLabel) {
let orgOption;
if (this.innerValue) {
const orgIndex = this.options?.findIndex(item => item[this.valueKey] === this.innerValue);
if (orgIndex > -1) {
orgOption = this.options[orgIndex];
}
}
const defList = this.options?.slice(0, this.maxOptionCount) || [];
if (orgOption) {
if (defList?.some(val => val[this.valueKey] === orgOption[this.valueKey])) {
this.searchOptions = defList;
} else {
this.searchOptions = [orgOption, ...defList];
}
} else {
this.searchOptions = defList;
}
// console.log(this.searchOptions);
this.handleUpdatePopper();
return;
}
const searchOptions = [];
for (let i = 0; i < this.options?.length; i++) {
const item = this.options[i];
if (this.showValue && item[this.valueKey].includes(this.inputLabel)) {
searchOptions.push(item);
} else if (this.showCode && String(item[this.codeKey] || '').includes(this.inputLabel)) {
searchOptions.push(item);
} else if (this.showSort && String(item[this.sortKey] || '').includes(this.inputLabel)) {
searchOptions.push(item);
} else if (item[this.labelKey].includes(this.inputLabel)) {
searchOptions.push(item);
}
if (searchOptions.length >= this.maxOptionCount) {
break;
}
}
this.searchOptions = searchOptions;
this.handleUpdatePopper();
},
//
handleUpdatePopper() {
if (this.expand && this.$refs.popper) {
this.$nextTick(() => {
this.$refs.popper.updatePopper();
});
}
},
//
handleExpand() {
this.expand = true;
},
//
handleUnexpand() {
this.expand = false;
},
//
handleFocus() {
this.$refs.input.focus();
},
//
focus() {
this.handleFocus();
},
//
handleBlur() {
this.$refs.input.blur();
},
//
blur() {
this.handleBlur();
},
//
handleInputFocus(e) {
this.isFocus = true;
if (this.autoSelectText) {
this.$refs.input.select();
}
this.$emit('focus', e);
},
//
handleInputBlur(e) {
this.isFocus = false;
this.handleUnexpand();
if (this.searchOptions.length > 0 && this.inputLabel) {
this.handleSelectOption(this.searchOptions[this.hoverIndex], this.hoverIndex, true);
} else if (this.innerValue) {
this.innerValue = '';
this.handleValueChange();
}
this.$emit('blur', e);
},
//
handleEnter(e) {
if (this.expand && this.searchOptions.length > 0) {
this.handleSelectOption(this.searchOptions[this.hoverIndex], this.hoverIndex, true);
} else {
this.handleBlur();
}
this.$emit('enter', e);
},
//
handleNavigate(move) {
if (!this.expand) {
this.handleSearch();
if (this.inputLabel) {
this.hoverIndex = this.getSelectedIndex();
if (this.hoverIndex === -1) {
this.hoverIndex = 0;
}
}
if (this.searchOptions.length > 0) {
this.handleExpand();
}
return;
}
if (this.searchOptions.length === 0) {
this.hoverIndex = 0;
this.tempSelectedIndex = -1;
return;
}
let hoverIndex = this.hoverIndex + move;
if (hoverIndex < 0) {
hoverIndex = this.searchOptions.length - 1;
} else if (hoverIndex >= this.searchOptions.length) {
hoverIndex = 0;
}
this.hoverIndex = hoverIndex;
},
handleValueChange(option) {
this.$emit('change', this.innerValue);
this.$emit('itemChange', option);
}
}
}
</script>
<style lang="scss">
.bm-select {
}
.bm-select-popover {
padding: 5px 5px;
}
.option-content {
overflow-x: hidden;
overflow-y: auto;
}
.option-code {
color: #999;
margin-left: 10px;
}
.option-item {
cursor: pointer;
border-bottom: 1px solid #DCDFE6;
border-radius: 2px;
min-height: 32px;
padding: 2px 5px;
display: flex;
align-items: center;
color: #222222;
font-weight: bold;
}
.option-item:hover {
background: #66B1FF;
color: #FFFFFF;
.option-code {
color: #CCCCCC;
}
}
.option-item-hover {
background: #409EFF;
color: #ffffff;
.option-code {
color: #EEEEEE;
}
}
.option-label {
flex: 1;
}
</style>

@ -0,0 +1,70 @@
<template>
<el-input v-model="inputValue" :disabled="disabled" :placeholder="'请输入' + title" @input="inputChange">
<el-tooltip slot="append" v-if="!disabled" effect="dark" :content="'自动生成' + title" placement="top">
<el-button size="mini" :icon="loading ? 'el-icon-loading':'el-icon-refresh'" @click="updateNumber()"></el-button>
</el-tooltip>
</el-input>
</template>
<script>
import { getBillNumber } from "@/api/ckbill";
export default {
name: 'BillNumberInput',
props: {
// RK CK ZC HP TY CY JZ
type: {
type: String,
default: 'RK'
},
title: {
type: String,
default: '单据编号'
},
value: {
type: String | Number,
default: ''
},
disabled: [Boolean],
},
data() {
return {
inputValue: this.value,
loading: false,
}
},
watch: {
value() {
this.inputValue = this.value;
}
},
methods: {
updateNumber(type) {
if (this.loading) {
return;
}
this.loading = true;
return new Promise((resolve, reject) => {
getBillNumber(type || this.type).then(res => {
this.loading = false;
if (res.data) {
this.$emit('input', res.data);
resolve(res.data);
} else {
reject();
}
}).catch(e => {
this.loading = false;
reject();
});
});
},
inputChange(value) {
this.$emit('input', value);
}
}
}
</script>
<style>
</style>

@ -0,0 +1,231 @@
<template>
<div>
<el-form-item class="my-form-item-input" :label="label" :prop="prop" :required="required">
<template v-slot:label v-if="$slots.label">
<slot name="label"></slot>
</template>
<el-input ref="input" class="my-item-input" v-if="type === 'text'" v-model="value_" :disabled="disabled" :readonly="readonly" :placeholder="placeholder_" :clearable="clearable"
:maxlength="maxlength" :minlength="minlength" @change="valueChange" @focus="onFocus" @clear="valueChange('')" @input="valueChange" @blur="onBlur" @keydown.enter.native="keydownEnter"></el-input>
<el-input ref="input" class="my-item-input" v-else-if="type === 'textarea'" type="textarea" :disabled="disabled" :readonly="readonly" v-model="value_" :placeholder="placeholder_"
:maxlength="maxlength" :minlength="minlength" :clearable="clearable" @change="valueChange" @focus="onFocus" @clear="valueChange('')" @input="valueChange" @blur="onBlur"></el-input>
<BMSelect ref="input" v-else-if="type === 'select' && !multiple"
:valueKey="valueKey" :labelKey="labelKey" :idKey="idKey" :inputDisplayKey="inputDisplayKey"
v-model="value_" :placeholder="placeholder_" :options="options"
:disabled="disabled" :readonly="readonly" :showCode="showCode" :showSort="showSort" :maxOptionCount="maxOptionCount"
@change="valueChange" @itemChange="itemChange" @focus="onFocus" @blur="onBlur"></BMSelect>
<el-select ref="input" class="el-icon-arrow-up-none my-item-input" v-else-if="type === 'select'" :disabled="disabled" :readonly="readonly" v-model="value_" :placeholder="placeholder_" :multiple="multiple"
:clearable="clearable" :filterable="filterable" @change="valueChange" @blur="onBlur">
<template v-if="options && options.length > 0">
<el-option v-for="item in options" :key="item[valueKey]" :label="getLabel(item)" :value="item[valueKey]">
{{getOptionLabel(item)}}
</el-option>
</template>
<slot></slot>
</el-select>
<el-date-picker
ref="input"
class="my-item-input"
:disabled="disabled"
:readonly="readonly"
v-else-if="dateTypes.includes(type)"
v-model="value_"
:type="type"
:format="format"
:value-format="dateFormat || dateFormats[type]"
:placeholder="placeholder_"
:clearable="clearable"
@change="valueChange"
@blur="onBlur"
></el-date-picker>
<template v-else>
<slot></slot>
</template>
</el-form-item>
</div>
</template>
<script>
import BMSelect from '../BMSelect';
export default {
name: 'MyFormItemInput',
components: {
BMSelect,
},
props: {
enterIndex: [Number],
label: [String],
prop: [String],
value: {
type: [String, Number, Array],
default: null
},
placeholder: [String],
showDefPLH: [Boolean],
type: {
type: String,
default: ''
},
multiple: [Boolean],
clearable: {
type: Boolean,
default: false
},
options: [Array],
required: [Boolean],
readonly: [Boolean],
minlength: [Number],
maxlength: [Number],
disabled: [Boolean],
filterable: {
type: Boolean,
default: true
},
showValue: {
type: Boolean,
default: true
},
showOptionsSort: [Boolean],
dateFormat: [String],
format: {
type: String,
default: 'yyyy-MM-dd'
},
maxOptionCount: {
type: Number,
default: 20
},
showCode: {
type: Boolean,
default: false
},
//
showSort: {
type: Boolean,
default: false
},
// keyvalue
idKey: [String],
valueKey: {
type: String,
default: 'value'
},
labelKey: {
type: String,
default: 'label'
},
// 使labelKey
inputDisplayKey: {
type: String,
default: '',
}
},
model: {
prop: 'value',
event: 'change'
},
data() {
return {
value_: this.value,
dateTypes: ['year','month','date','dates','months','years','week','datetime','datetimerange','daterange','monthrange'],
dateFormats: {
year: 'yyyy',
month: 'yyyy-MM',
date: 'yyyy-MM-dd',
dates: 'yyyy-MM-dd',
months: 'yyyy-MM',
years: 'yyyy',
week: 'yyyy-ww',
datetime: 'yyyy-MM-dd HH:mm:ss',
datetimerange: 'yyyy-MM-dd HH:mm:ss',
daterange: 'yyyy-MM-dd',
monthrange: 'yyyy-MM'
}
}
},
watch: {
value(val) {
this.value_ = val;
},
},
computed: {
placeholder_() {
if (this.placeholder) {
return this.placeholder;
}
if (!this.showDefPLH) {
return '';
}
const label = this.label || '';
if (this.type === 'text' || this.type === 'textarea') {
return '请输入' + label;
}
return '请选择' + label;
},
},
methods: {
getLabel(item) {
return this.showValue ? (item[this.valueKey] + '-' + item[this.labelKey]) : item[this.labelKey];
},
getOptionLabel(item) {
let label = '';
if (this.showOptionsSort && item.raw?.dictSort) {
label = item.raw?.dictSort + '-';
}
if (this.showValue) {
label = label + item[this.valueKey] + '-';
}
return label + item[this.labelKey];
},
valueChange(data) {
if (typeof data === 'string') {
this.value_ = data.trim();
}
this.$emit('change', this.value_);
},
itemChange(data) {
this.$emit('itemChange', data);
},
focus() {
this.$refs.input?.focus();
},
blur() {
this.$refs.input?.blur();
},
onFocus(e) {
this.$emit('focus', e);
},
onBlur(e) {
this.$emit('blur', e);
},
keydownEnter(e) {
this.$emit('keydownEnter', e);
}
}
}
</script>
<style lang="scss">
.my-form-item-input {
.my-item-input {
width: 100%;
}
.el-form-item__label {
padding-bottom: 0;
}
}
.el-form-item--mini.el-form-item {
margin-bottom: 6px;
}
.el-form-item--small.el-form-item {
margin-bottom: 8px;
}
.el-form-item {
margin-bottom: 10px;
}
</style>

@ -0,0 +1,16 @@
<template>
<span class="require-dot">*</span>
</template>
<script>
export default {
name: 'Rq',
}
</script>
<style lang="scss" scoped>
.require-dot {
color: red;
font-size: 18px;
}
</style>

@ -317,3 +317,4 @@ export default {
}
}
};
</script>

@ -55,7 +55,7 @@ import './icons' // icon
import './permission' // permission control
import './utils/error-log' // error integralLog
import * as filters from './filters' // global filters
import { parseQuery } from "@/utils";
import { parseQuery, sortBy } from "@/utils";
import * as Auth from '@/libs/wechat';
import * as constants from '@/utils/constants.js'
import * as selfUtil from '@/utils/ZBKJIutil.js';
@ -117,7 +117,7 @@ Vue.prototype.handleTree = handleTree
Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange
Vue.prototype.$sortBy = sortBy
let cookieName = "VCONSOLE";
let query = parseQuery();
let urlSpread = query["spread"];

@ -532,3 +532,17 @@ export function datePickerOpts() {
}]
}
}
/**
* 获取排序字段
* @param col
* @param sortBy
*/
export function sortBy(col, sortBy) {
sortBy.sortOrder = col.order === 'ascending' ? 'asc' : 'desc'
sortBy.sortField = col.prop;
if (col.order == null) {
sortBy.sortOrder = null;
sortBy.sortField = null;
}
}

@ -8,7 +8,7 @@
<el-table-column label='序号' type='index' width='50'></el-table-column>
<el-table-column :label="tableReadonly ? '查看入库信息' : '填写入库信息'" align="center">
<template slot-scope="scope">
<el-form :ref="'form' + scope.$index" :model="scope.row" :rules="rules" :show-message="false" v-enterboard>
<el-form :ref="'form' + scope.$index" :model="scope.row" :rules="rules" :show-message="false" >
<el-descriptions class="desc-table" :column="4" border>
<el-descriptions-item>
<template slot="label">货物名称<rq></rq></template>
@ -231,7 +231,7 @@
</el-table>
<div style="display: flex;align-items: center;">
<el-form ref="form" style="flex: 1;margin-top: 25px;" :model="form" :rules="rules"
label-width="80px" v-enterboard>
label-width="80px" >
<el-row>
<el-col :span="8">
<el-form-item label="单据编号" prop="billNumber" >
@ -280,11 +280,17 @@ import { ckbillDetailApi as getCkbillInfo, putBill } from '@/api/ckbill';
import { ckbillcargoDeleteApi as delCkcargo, recallPutBill } from '@/api/ckbillcargo';
// import { listVessel } from "@/api/jxc/vessel";
import FileUpload from "@/components/FileUploadVO";
import MyFormItemInput from "@/components/MyFormItemInput";
import rq from "@/components/Rq";
import BillNumberInput from "@/components/BillNumberInput";
export default {
name: 'BillEdit',
components: {
FileUpload,
MyFormItemInput,
rq,
BillNumberInput,
},
props: {

@ -1,5 +1,5 @@
<template>
<el-container style="min-height: 100vh">
<el-container style="margin-top: 10px;">
<!-- 搜索部分 -->
<el-header height="auto" style="padding: 10px 0; background-color: #fff; border-bottom: 1px solid #eaeaea;">
<SearchBlock v-model="billQuery" v-show="showSearch" size="mini" :menus="queryOption" @change="handleQuery"></SearchBlock>
@ -7,7 +7,7 @@
<el-container>
<!-- 左侧单据部分 -->
<el-aside width="300px" style="border-right: 1px solid #eaeaea; padding: 10px;max-height: 100vh;">
<el-aside width="300px" style="border-right: 1px solid #eaeaea; padding: 10px;max-height: 90vh;">
<h3 style="margin: 0 0 10px 0; font-size: 16px; font-weight: 500;">单据列表</h3>
<BillList ref="billList" :params="billQuery" @rowClick="billClick"></BillList>
</el-aside>

Loading…
Cancel
Save