feat(CoilSelector): 新增入场卷号字段并调整当前卷号显示
feat(customer): 新增客户相关配卷和财务信息查询接口 fix(base.vue): 修复发货单时间条件显示问题 refactor(CustomerEdit): 替换地址选择组件为普通输入框 feat(CoilSelector): 增加入场卷号查询条件并调整对话框宽度 style(OrderEdit): 调整客户名称和销售员选择框宽度 refactor(ChinaAreaSelect): 优化地址解析逻辑并支持空对象处理 feat(FileUpload/FileList): 新增文件预览功能组件 refactor(KLPService/CustomerSelect): 优化客户选择组件并支持自定义字段绑定 fix(AbnormalForm): 修复异常位置校验逻辑并保留当前卷号 feat(ContractTabs): 新增合同附件展示功能 refactor(warehouse/record): 重构操作记录统计展示方式 feat(contract): 集成客户选择组件并优化合同信息填充 refactor(order): 调整订单表单布局并集成合同信息 feat(FilePreview): 新增文件预览组件 feat(customer): 新增财务状态和发货配卷展示 refactor(CustomerOrder): 移除冗余代码并优化布局 feat(PlanDetailForm): 新增合同附件查看功能 feat(dict): 新增字典管理页面
This commit is contained in:
@@ -42,3 +42,19 @@ export function delCustomer(customerId) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询该客户相关的配卷情况
|
||||
export function listCoilByCustomerId(customerId) {
|
||||
return request({
|
||||
url: '/crm/orderItem/coils/customer/' + customerId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询该项目相关的订单异议和财务信息
|
||||
export function listFinanceByCustomerId(customerId) {
|
||||
return request({
|
||||
url: '/crm/orderItem/customerFinance/' + customerId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -47,12 +47,17 @@ function formatAreaText(value) {
|
||||
return { standard, custom };
|
||||
}
|
||||
|
||||
// 非组合格式(纯标准地址/纯自定义地址)→ 默认归为standard
|
||||
return { standard: trimVal, custom: '' };
|
||||
// 非组合格式(纯任意字符串)→ 归为custom
|
||||
return { standard: '', custom: trimVal };
|
||||
}
|
||||
|
||||
// ========== 场景3:输入是对象 → 格式化为组合字符串 ==========
|
||||
if (typeof value === 'object' && !Array.isArray(value)) {
|
||||
// 处理空对象
|
||||
if (Object.keys(value).length === 0) {
|
||||
return '[]()';
|
||||
}
|
||||
|
||||
const { standard = '', custom = '' } = value;
|
||||
// 转字符串并去空格
|
||||
const standardStr = String(standard).trim();
|
||||
@@ -71,11 +76,19 @@ function formatAreaText(value) {
|
||||
*/
|
||||
function formatAreaTextEnhanced(value, keyType = 'name') {
|
||||
// 先调用基础版解析/格式化
|
||||
const result = formatAreaText(value);
|
||||
let result = formatAreaText(value);
|
||||
|
||||
// 如果是解析模式(返回对象)且keyType为name,转换code为name
|
||||
// 如果是解析模式(返回对象)且keyType为name,检查是否为代码输入
|
||||
if (typeof result === 'object' && keyType === 'name') {
|
||||
result.standard = convertCodeToName(result.standard);
|
||||
// 检查custom是否可能是代码(不包含中文)
|
||||
if (result.custom && !/[\u4e00-\u9fa5]/.test(result.custom)) {
|
||||
// 尝试转换code为name
|
||||
const convertedName = convertCodeToName(result.custom);
|
||||
// 如果转换成功(返回非空字符串),则将其移到standard字段
|
||||
if (convertedName) {
|
||||
result = { standard: convertedName, custom: '' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
<script>
|
||||
import areaData from './data.js'
|
||||
import { formatAreaTextEnhanced } from './index.js'
|
||||
|
||||
export default {
|
||||
name: 'ChinaAreaSelectWithDetail',
|
||||
@@ -105,32 +106,9 @@ export default {
|
||||
* @param {String} val - 外部传入的「[标准地址](自定义地址)」格式值
|
||||
*/
|
||||
parseCombineValue(val) {
|
||||
if (!val) {
|
||||
this.areaValue = []
|
||||
this.detailAddress = ''
|
||||
return
|
||||
}
|
||||
|
||||
// 核心正则:匹配「[xxx](yyy)」格式,分组提取xxx和yyy(无匹配则为空)
|
||||
const reg = /\[([^\]]*)\]\(([^)]*)\)/
|
||||
const matchResult = val.match(reg)
|
||||
|
||||
// 提取标准地址(第一个分组)和自定义地址(第二个分组)
|
||||
const standardAddress = matchResult?.[1] || ''
|
||||
const customAddress = matchResult?.[2] || ''
|
||||
|
||||
// 1. 处理自定义地址:直接赋值
|
||||
this.detailAddress = customAddress.trim()
|
||||
|
||||
// 2. 处理标准地址:转换为区域选择器的code数组
|
||||
if (standardAddress) {
|
||||
const standardArr = standardAddress.split('/').filter(Boolean)
|
||||
this.areaValue = this.keyType === 'name'
|
||||
? this.convertNameToCode(standardArr) // name转code
|
||||
: standardArr.filter(code => !!areaData[code]) // code直接过滤无效值
|
||||
} else {
|
||||
this.areaValue = []
|
||||
}
|
||||
const formattedAddress = formatAreaTextEnhanced(val)
|
||||
this.areaValue = formattedAddress.standard.split('/').filter(Boolean)
|
||||
this.detailAddress = formattedAddress.custom.trim()
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
export const defaultColumns = [
|
||||
{
|
||||
label: '卷号',
|
||||
label: '入场卷号',
|
||||
align: 'center',
|
||||
prop: 'enterCoilNo',
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{
|
||||
label: '当前卷号',
|
||||
align: 'center',
|
||||
prop: 'currentCoilNo',
|
||||
showOverflowTooltip: true
|
||||
|
||||
@@ -27,8 +27,12 @@
|
||||
<el-option label="原料" value="raw_material" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="卷号">
|
||||
<el-input v-model="queryParams.currentCoilNo" placeholder="请输入卷号" clearable size="small"
|
||||
<el-form-item label="入场卷号">
|
||||
<el-input v-model="queryParams.enterCoilNo" placeholder="请输入入场卷号" clearable size="small"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="当前卷号">
|
||||
<el-input v-model="queryParams.currentCoilNo" placeholder="请输入当前卷号" clearable size="small"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料">
|
||||
@@ -192,7 +196,7 @@ export default {
|
||||
},
|
||||
dialogWidth: {
|
||||
type: String,
|
||||
default: '1000px'
|
||||
default: '1200px'
|
||||
},
|
||||
// 过滤条件(可以预设一些查询条件)
|
||||
filters: {
|
||||
|
||||
@@ -15,25 +15,47 @@
|
||||
<i class="el-icon-document"></i>
|
||||
<span class="file-name">{{ file.originalName }}</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-download"
|
||||
@click="downloadFile(file)"
|
||||
size="small"
|
||||
class="download-btn"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
<div class="file-actions">
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handlePreview(file)"
|
||||
size="small"
|
||||
class="preview-btn"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-download"
|
||||
@click="downloadFile(file)"
|
||||
size="small"
|
||||
class="download-btn"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件预览组件 -->
|
||||
<file-preview
|
||||
:visible.sync="previewVisible"
|
||||
:file-url="previewFileUrl"
|
||||
:file-name="previewFileName"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listByIds } from "@/api/system/oss";
|
||||
import FilePreview from "../FilePreview";
|
||||
|
||||
export default {
|
||||
name: "FileList",
|
||||
components: {
|
||||
FilePreview
|
||||
},
|
||||
props: {
|
||||
ossIds: {
|
||||
type: String,
|
||||
@@ -43,7 +65,11 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
loading: false // 加载状态
|
||||
loading: false, // 加载状态
|
||||
// 预览相关
|
||||
previewVisible: false,
|
||||
previewFileUrl: '',
|
||||
previewFileName: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -81,6 +107,12 @@ export default {
|
||||
return;
|
||||
}
|
||||
this.$download.oss(file.ossId);
|
||||
},
|
||||
// 预览文件
|
||||
handlePreview(file) {
|
||||
this.previewFileUrl = file.url;
|
||||
this.previewFileName = file.originalName;
|
||||
this.previewVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,6 +147,12 @@ export default {
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.file-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.file-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
185
klp-ui/src/components/FilePreview/index.vue
Normal file
185
klp-ui/src/components/FilePreview/index.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:width="width"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
@close="handleClose"
|
||||
>
|
||||
<!-- 图片预览 -->
|
||||
<div v-if="fileType === 'image'" class="preview-image">
|
||||
<div class="image-controls">
|
||||
<el-button type="primary" size="small" @click="zoomIn">放大</el-button>
|
||||
<el-button type="primary" size="small" @click="zoomOut">缩小</el-button>
|
||||
<el-button type="primary" size="small" @click="resetZoom">重置</el-button>
|
||||
</div>
|
||||
<div class="image-container" ref="imageContainer">
|
||||
<img
|
||||
:src="fileUrl"
|
||||
:style="{ transform: `scale(${scale})` }"
|
||||
class="preview-image-content"
|
||||
@wheel="handleWheel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PDF预览 -->
|
||||
<div v-else-if="fileType === 'pdf'" class="preview-pdf">
|
||||
<iframe
|
||||
:src="fileUrl"
|
||||
class="preview-pdf-content"
|
||||
frameborder="0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 不支持的文件类型 -->
|
||||
<div v-else class="preview-not-supported">
|
||||
<el-empty description="暂不支持预览此文件类型"></el-empty>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "FilePreview",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fileUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
fileName: {
|
||||
type: String,
|
||||
default: "文件预览"
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: "80%"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
scale: 1
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible: {
|
||||
handler(val) {
|
||||
this.dialogVisible = val;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
dialogVisible(val) {
|
||||
if (!val) {
|
||||
this.$emit('update:visible', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.fileName || "文件预览";
|
||||
},
|
||||
fileType() {
|
||||
const fileName = this.fileName || '';
|
||||
const ext = fileName.split('.').pop()?.toLowerCase();
|
||||
if (['png', 'jpg', 'jpeg', 'bmp', 'webp'].includes(ext)) {
|
||||
return 'image';
|
||||
} else if (ext === 'pdf') {
|
||||
return 'pdf';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit('update:visible', false);
|
||||
},
|
||||
// 放大图片
|
||||
zoomIn() {
|
||||
if (this.scale < 3) {
|
||||
this.scale += 0.1;
|
||||
}
|
||||
},
|
||||
// 缩小图片
|
||||
zoomOut() {
|
||||
if (this.scale > 0.1) {
|
||||
this.scale -= 0.1;
|
||||
}
|
||||
},
|
||||
// 重置缩放
|
||||
resetZoom() {
|
||||
this.scale = 1;
|
||||
},
|
||||
// 鼠标滚轮缩放
|
||||
handleWheel(event) {
|
||||
event.preventDefault();
|
||||
const delta = event.deltaY > 0 ? -0.1 : 0.1;
|
||||
if ((this.scale > 0.1 || delta > 0) && (this.scale < 3 || delta < 0)) {
|
||||
this.scale += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
background-color: #f5f7fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.image-controls {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.preview-image-content {
|
||||
transition: transform 0.3s ease;
|
||||
cursor: zoom-in;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.preview-image-content:hover {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
.preview-pdf {
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
}
|
||||
|
||||
.preview-pdf-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.preview-not-supported {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
@@ -32,19 +32,31 @@
|
||||
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
|
||||
</el-link>
|
||||
<div class="ele-upload-list__item-content-action">
|
||||
<el-link :underline="false" @click="handlePreview(file)" type="primary">预览</el-link>
|
||||
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
|
||||
</div>
|
||||
</li>
|
||||
</transition-group>
|
||||
|
||||
<!-- 文件预览组件 -->
|
||||
<file-preview
|
||||
:visible.sync="previewVisible"
|
||||
:file-url="previewFileUrl"
|
||||
:file-name="previewFileName"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { listByIds, delOss } from "@/api/system/oss";
|
||||
import FilePreview from "../FilePreview";
|
||||
|
||||
export default {
|
||||
name: "FileUpload",
|
||||
components: {
|
||||
FilePreview
|
||||
},
|
||||
props: {
|
||||
// 值
|
||||
value: [String, Object, Array],
|
||||
@@ -85,6 +97,10 @@ export default {
|
||||
},
|
||||
fileList: [],
|
||||
loading: false,
|
||||
// 预览相关
|
||||
previewVisible: false,
|
||||
previewFileUrl: '',
|
||||
previewFileName: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -232,6 +248,12 @@ export default {
|
||||
}
|
||||
return strs != "" ? strs.substr(0, strs.length - 1) : "";
|
||||
},
|
||||
// 预览文件
|
||||
handlePreview(file) {
|
||||
this.previewFileUrl = file.url;
|
||||
this.previewFileName = file.name;
|
||||
this.previewVisible = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-select filterable v-model="_customerId" remote :remote-method="remoteSearchCustomer" :loading="customerLoading" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.name" :value="item.customerId" />
|
||||
<el-select filterable v-model="_customerId" remote :remote-method="remoteSearchCustomer" :style="style" :loading="customerLoading" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item[bindField]" :label="item.companyName" :value="item[bindField]" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
@@ -13,6 +13,14 @@
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
bindField: {
|
||||
type: String,
|
||||
default: 'customerId'
|
||||
},
|
||||
style: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -22,6 +30,12 @@
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value);
|
||||
// 找到对应的客户信息
|
||||
const customer = this.customerList.find(item => item[this.bindField] === value);
|
||||
// 触发 change 事件,传递客户信息
|
||||
if (customer) {
|
||||
this.$emit('change', customer);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -37,7 +51,7 @@
|
||||
methods: {
|
||||
remoteSearchCustomer(query) {
|
||||
this.customerLoading = true;
|
||||
listCustomer({ name: query, pageNum: 1, pageSize: 10 }).then(response => {
|
||||
listCustomer({ companyName: query, pageNum: 1, pageSize: 10 }).then(response => {
|
||||
this.customerList = response.rows;
|
||||
}).finally(() => {
|
||||
this.customerLoading = false;
|
||||
|
||||
@@ -7,9 +7,14 @@
|
||||
<template slot="title">
|
||||
<!-- 在这里选择订单后快速填写相关信息 -->
|
||||
<span>订单信息</span>
|
||||
<el-button @click.stop="openOrderDialog" style="margin-left: 10px;" plain :type="formData.orderId ? 'success' : 'default'">
|
||||
{{ formData.orderId ? formData.orderCode : '选择订单' }}
|
||||
</el-button>
|
||||
<el-button @click.stop="openOrderDialog" style="margin-left: 10px;" plain
|
||||
:type="formData.orderId ? 'success' : 'default'">
|
||||
{{ formData.orderId ? formData.orderCode : '选择订单' }}
|
||||
</el-button>
|
||||
<div v-if="formData.orderId" @click.stop="openOrderAttachmentDialog" style="margin-left: 10px; cursor: pointer; color: #409eff;"
|
||||
type="primary">
|
||||
查看附件
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
@@ -207,12 +212,8 @@
|
||||
<el-form :model="orderQueryParams" ref="orderQueryForm" size="small" :inline="true" label-width="80px">
|
||||
<el-form-item label="合同号">
|
||||
<el-select v-model="orderQueryParams.contractId" placeholder="请选择合同">
|
||||
<el-option
|
||||
v-for="contract in contractList"
|
||||
:key="contract.contractId"
|
||||
:label="contract.contractNo"
|
||||
:value="contract.contractId"
|
||||
/>
|
||||
<el-option v-for="contract in contractList" :key="contract.contractId" :label="contract.contractNo"
|
||||
:value="contract.contractId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单号">
|
||||
@@ -250,14 +251,26 @@
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next, jumper"
|
||||
:total="orderTotal"
|
||||
:page-size="orderQueryParams.pageSize"
|
||||
:current-page.sync="orderQueryParams.pageNum"
|
||||
@current-change="getOrderList"
|
||||
/>
|
||||
<el-pagination background layout="prev, pager, next, jumper" :total="orderTotal"
|
||||
:page-size="orderQueryParams.pageSize" :current-page.sync="orderQueryParams.pageNum"
|
||||
@current-change="getOrderList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="合同附件" :visible.sync="attachmentOpen" width="50%" append-to-body>
|
||||
<div class="attachment-section" v-loading="loading">
|
||||
<!-- <div class="attachment-item">
|
||||
<h4>商务附件</h4>
|
||||
<FileList :oss-ids="contractAttachment" />
|
||||
</div> -->
|
||||
<div class="attachment-item">
|
||||
<h4>技术附件</h4>
|
||||
<FileList :oss-ids="contract.techAnnex" />
|
||||
</div>
|
||||
<div class="attachment-item">
|
||||
<h4>排产函</h4>
|
||||
<FileList :oss-ids="contract.productionSchedule" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -265,8 +278,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOrder } from '@/api/crm/order';
|
||||
import { listContract } from '@/api/crm/contract';
|
||||
import { listOrder, getOrder } from '@/api/crm/order';
|
||||
import { listContract, getContract } from '@/api/crm/contract';
|
||||
import FileList from '@/components/FileList'
|
||||
|
||||
export default {
|
||||
name: "PlanDetailForm",
|
||||
@@ -284,6 +298,9 @@ export default {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FileList
|
||||
},
|
||||
computed: {
|
||||
formData: {
|
||||
get() {
|
||||
@@ -330,7 +347,10 @@ export default {
|
||||
contractId: undefined,
|
||||
contractCode: undefined,
|
||||
customerName: undefined
|
||||
}
|
||||
},
|
||||
attachmentOpen: false,
|
||||
contract: {},
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -349,6 +369,29 @@ export default {
|
||||
// 加载订单列表
|
||||
this.getOrderList();
|
||||
},
|
||||
async openOrderAttachmentDialog() {
|
||||
this.loading = true;
|
||||
this.attachmentOpen = true;
|
||||
// 根据订单id获取订单详情,拿到合同id
|
||||
try {
|
||||
if (!this.formData.orderId) {
|
||||
this.$message.error('订单不存在')
|
||||
return;
|
||||
}
|
||||
const order = await getOrder(this.formData.orderId);
|
||||
if (!order.data.contractId) {
|
||||
this.$message.error('未找到合同')
|
||||
return;
|
||||
}
|
||||
// 根据合同id拿到合同详情
|
||||
const contract = await getContract(order.data.contractId);
|
||||
this.contract = contract.data;
|
||||
} catch {
|
||||
this.$message.error('获取合同附件失败')
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
/** 获取合同列表 */
|
||||
getContractList() {
|
||||
listContract().then(response => {
|
||||
@@ -388,6 +431,7 @@ export default {
|
||||
this.formData.contractCode = row.contractCode;
|
||||
this.formData.customerName = row.companyName;
|
||||
this.formData.salesman = row.salesman;
|
||||
this.formData.orderId = row.orderId;
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
/** 处理订单行点击 */
|
||||
@@ -411,4 +455,24 @@ export default {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.attachment-section {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.attachment-item h4 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.attachment-item .file-list-container {
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -95,17 +95,16 @@
|
||||
</el-col>
|
||||
<el-col :span="24" v-hasPermi="['crm:customer:address']">
|
||||
<el-form-item label="客户地址" prop="address">
|
||||
<!-- <el-input
|
||||
type="textarea"
|
||||
<el-input
|
||||
v-model="customer.address"
|
||||
placeholder="请输入客户地址"
|
||||
@input="handleInputChange"
|
||||
/> -->
|
||||
<ChinaAreaSelect
|
||||
/>
|
||||
<!-- <ChinaAreaSelect
|
||||
v-model="customer.address"
|
||||
placeholder="请选择客户地址"
|
||||
@change="handleInputChange"
|
||||
/>
|
||||
/> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" v-hasPermi="['crm:customer:bank']">
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-descriptions :column="2" border title="订单统计">
|
||||
<el-descriptions-item label="订单总数">{{ currentCustomer.totalCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="已成交订单数">{{ currentCustomer.dealCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="待成交订单数">{{ currentCustomer.waitCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="取消订单数">{{ currentCustomer.cancelCount || 0 }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions border title="订单详情">
|
||||
</el-descriptions>
|
||||
|
||||
@@ -21,6 +14,10 @@
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单总数" prop="totalCount" style="margin-left: 10px; float: right;">
|
||||
<div>{{ total || 0 }}</div>
|
||||
<!-- <el-input v-model="queryParams.totalCount" placeholder="请输入订单总数" clearable @keyup.enter.native="handleQuery" /> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table v-loading="loading" :data="orderList" height="400px" highlight-current-row @row-click="handleRowClick">
|
||||
@@ -38,90 +35,15 @@
|
||||
<span v-else-if="scope.row.orderType === ORDER_TYPE['正式订单']">正式订单</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column v-if="orderType === ORDER_TYPE['预订单']" label="审核状态" align="center" prop="preOrderStatus">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.preOrderStatus === 0">待审核</span>
|
||||
<span v-else-if="scope.row.preOrderStatus === 1">已审核</span>
|
||||
<span v-else-if="scope.row.preOrderStatus === 2">已取消</span>
|
||||
<span v-else>未知状态</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column label="审核人" align="center" prop="auditUser" />
|
||||
<el-table-column label="审核时间" align="center" prop="auditTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.auditTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-check"
|
||||
@click="handleApprove(scope.row)"
|
||||
>审批</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 正式订单明细列表组件 -->
|
||||
<!-- <OrderDetailList ref="orderDetailList" :orderId="orderId" /> -->
|
||||
|
||||
<!-- 添加或修改正式订单主对话框 -->
|
||||
<!-- <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="订单编号" prop="orderCode">
|
||||
<el-input v-model="form.orderCode" placeholder="请输入订单编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户" prop="customerId">
|
||||
<el-select v-model="form.customerId" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.customerCode" :value="item.customerId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单总金额" prop="orderAmount">
|
||||
<el-input v-model="form.orderAmount" placeholder="请输入订单总金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="销售员" prop="salesman">
|
||||
<el-input v-model="form.salesman" placeholder="请输入销售员" />
|
||||
</el-form-item>
|
||||
<el-form-item label="交货日期" prop="deliveryDate">
|
||||
<el-date-picker clearable
|
||||
v-model="form.deliveryDate"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择交货日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOrder, getOrder, delOrder, addOrder, updateOrder } from "@/api/crm/order";
|
||||
// import { listCustomer } from "@/api/crm/customer";
|
||||
import OrderDetailList from '@/views/crm/components/OrderDetail.vue'
|
||||
import { ORDER_TYPE } from "../js/enum";
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户名称" prop="customerId">
|
||||
<el-select v-model="form.customerId" placeholder="请选择客户名称">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.customerCode"
|
||||
<el-select style="width: 100%;" v-model="form.customerId" placeholder="请选择客户名称">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.companyName"
|
||||
:value="item.customerId"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="销售员" prop="salesman">
|
||||
<el-select v-model="form.salesman" placeholder="请选择销售员">
|
||||
<el-select style="width: 100%;" v-model="form.salesman" placeholder="请选择销售员">
|
||||
<el-option v-for="item in dict.type.wip_pack_saleman" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div v-if="contractId" class="tabs-content">
|
||||
<el-tabs v-model="activeTab" type="card" tab-position="top" v-loading="tabLoading">
|
||||
<el-tab-pane label="下发订单" name="second">
|
||||
<OrderPage v-if="activeTab === 'second'" :contractId="contractId" />
|
||||
<OrderPage v-if="activeTab === 'second'" :contractId="contractId" :customerId="customerId" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="财务状态" name="third">
|
||||
<KLPTable v-loading="loading" :data="financeList">
|
||||
@@ -38,6 +38,22 @@
|
||||
<el-tab-pane label="发货配卷" name="fifth">
|
||||
<CoilTable :data="coilList" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="合同附件" name="sixth">
|
||||
<div class="attachment-section">
|
||||
<div class="attachment-item">
|
||||
<h4>商务附件</h4>
|
||||
<FileList :oss-ids="contractAttachment" />
|
||||
</div>
|
||||
<div class="attachment-item">
|
||||
<h4>技术附件</h4>
|
||||
<FileList :oss-ids="technicalAgreement" />
|
||||
</div>
|
||||
<div class="attachment-item">
|
||||
<h4>排产函</h4>
|
||||
<FileList :oss-ids="otherAttachment" />
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div v-else class="no-selection" style="display: flex; align-items: center; justify-content: center; height: 100%;">
|
||||
@@ -49,18 +65,24 @@
|
||||
<script>
|
||||
import OrderPage from "@/views/crm/order/index.vue";
|
||||
import CoilTable from "../../components/CoilTable.vue";
|
||||
import FileList from "@/components/FileList";
|
||||
|
||||
export default {
|
||||
name: "ContractTabs",
|
||||
components: {
|
||||
OrderPage,
|
||||
CoilTable
|
||||
CoilTable,
|
||||
FileList
|
||||
},
|
||||
props: {
|
||||
contractId: {
|
||||
type: [Number, String],
|
||||
default: null
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
financeList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
@@ -80,6 +102,19 @@ export default {
|
||||
tabLoading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 附件字段
|
||||
contractAttachment: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
technicalAgreement: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
otherAttachment: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -116,4 +151,24 @@ export default {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.attachment-section {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.attachment-item h4 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.attachment-item .file-list-container {
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -24,8 +24,12 @@
|
||||
|
||||
<!-- 右侧下方:Tab标签页 -->
|
||||
<div class="tab-panel" ref="tabPanel" style="flex: 1; overflow-y: auto;">
|
||||
<ContractTabs :contractId="form.contractId" :financeList="financeList" :objectionList="objectionList"
|
||||
:coilList="coilList" :tabLoading="tabLoading" />
|
||||
<ContractTabs :contractId="form.contractId"
|
||||
:customerId="form.customerId" :financeList="financeList" :objectionList="objectionList"
|
||||
:coilList="coilList" :tabLoading="tabLoading"
|
||||
:contract-attachment="form.businessAnnex"
|
||||
:technical-agreement="form.techAnnex"
|
||||
:other-attachment="form.productionSchedule" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else style="flex: 1; display: flex; flex-direction: column;">
|
||||
@@ -102,7 +106,8 @@
|
||||
<!-- 需方信息 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="需方" prop="customer">
|
||||
<el-input v-model="form.customer" placeholder="请输入需方" />
|
||||
<CustomerSelect v-model="form.customer" bindField="companyName" @change="handleCustomerChange" :style="{ width: '100%' }" />
|
||||
<!-- <el-input v-model="form.customer" placeholder="请输入需方" /> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="需方地址" prop="customerAddress">
|
||||
<el-input v-model="form.customerAddress" placeholder="请输入需方地址" />
|
||||
@@ -151,6 +156,8 @@ import ContractList from "./components/ContractList.vue";
|
||||
import ContractPreview from "./components/ContractPreview.vue";
|
||||
import ContractTabs from "./components/ContractTabs.vue";
|
||||
import ProductContent from "./components/ProductContent.vue";
|
||||
import CustomerSelect from "@/components/KLPService/CustomerSelect/index.vue";
|
||||
import { formatAreaTextEnhanced } from '@/components/ChinaAreaSelect/index.js'
|
||||
|
||||
export default {
|
||||
name: "Contract",
|
||||
@@ -158,7 +165,8 @@ export default {
|
||||
ContractList,
|
||||
ContractPreview,
|
||||
ContractTabs,
|
||||
ProductContent
|
||||
ProductContent,
|
||||
CustomerSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -258,6 +266,29 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 处理客户选择 */
|
||||
handleCustomerChange(customer) {
|
||||
console.log(customer);
|
||||
this.form.customerAddress = customer.address;
|
||||
this.form.customerPhone = customer.contactWay;
|
||||
this.form.customerTaxNo = customer.taxNumber;
|
||||
this.form.customerId = customer.customerId;
|
||||
// 处理银行信息
|
||||
if (customer.bankInfo) {
|
||||
try {
|
||||
const bankList = JSON.parse(customer.bankInfo);
|
||||
if (bankList && bankList.length > 0) {
|
||||
const firstBank = bankList[0];
|
||||
this.form.customerBank = firstBank.bankName;
|
||||
this.form.customerAccount = firstBank.bankAccount;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析银行信息失败:', error);
|
||||
}
|
||||
}
|
||||
// 开户行和银行账号在客户信息中是一个json数组字符串,如果存在则默认选中第一个,将输入框改为下拉选可以快速切换
|
||||
console.log(customer);
|
||||
},
|
||||
|
||||
/** 处理合同状态更新 */
|
||||
handleStatusChange(status) {
|
||||
|
||||
@@ -65,6 +65,39 @@
|
||||
<CustomerOrder :customer="currentCustomer" :dict="dict" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="财务状态" name="third">
|
||||
<KLPTable v-loading="loading" :data="financeList">
|
||||
<el-table-column label="收款日期" align="center" prop="dueDate" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.dueDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款金额" align="center" prop="amount" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
</KLPTable>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="订单异议" name="fourth">
|
||||
<el-table v-loading="loading" :data="objectionList">
|
||||
<el-table-column label="编号" align="center" prop="objectionCode" />
|
||||
<el-table-column label="状态" align="center" prop="objectionStatus">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.objectionStatus === 0" type="danger">待处理</el-tag>
|
||||
<el-tag v-else-if="scope.row.objectionStatus === 1" type="success">已处理</el-tag>
|
||||
<el-tag v-else-if="scope.row.objectionStatus === 2" type="info">已关闭</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="处理人" align="center" prop="handleUser" />
|
||||
<el-table-column label="处理时间" align="center" prop="handleTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="发货配卷" name="fifth">
|
||||
<CoilTable :data="coilList" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-empty v-else style="margin-top: 20px;" description="选择客户查看详情"></el-empty>
|
||||
</el-col>
|
||||
@@ -101,7 +134,8 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户地址" prop="address">
|
||||
<ChinaAreaSelect v-model="form.address" placeholder="请选择客户地址" />
|
||||
<el-input v-model="form.address" placeholder="请输入客户地址" />
|
||||
<!-- <ChinaAreaSelect v-model="form.address" placeholder="请选择客户地址" /> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
@@ -126,8 +160,9 @@ import CustomerDetail from '../components/CustomerInfo.vue'
|
||||
import CustomerEdit from '../components/CustomerEdit.vue'
|
||||
import CustomerOrder from '../components/CustomerOrder.vue'
|
||||
import ChinaAreaSelect from '@/components/ChinaAreaSelect/index.vue'
|
||||
import CoilTable from '../components/CoilTable.vue'
|
||||
|
||||
import { listCustomer, addCustomer, updateCustomer, delCustomer } from '@/api/crm/customer'
|
||||
import { listCustomer, addCustomer, updateCustomer, delCustomer, listCoilByCustomerId, listFinanceByCustomerId } from '@/api/crm/customer'
|
||||
|
||||
export default {
|
||||
name: 'CustomerPage',
|
||||
@@ -137,12 +172,16 @@ export default {
|
||||
CustomerDetail,
|
||||
CustomerEdit,
|
||||
CustomerOrder,
|
||||
ChinaAreaSelect
|
||||
ChinaAreaSelect,
|
||||
CoilTable
|
||||
},
|
||||
dicts: ['customer_industry', 'customer_level'],
|
||||
data() {
|
||||
return {
|
||||
customerList: [],
|
||||
financeList: [],
|
||||
objectionList: [],
|
||||
coilList: [],
|
||||
showQuery: false,
|
||||
queryParams: {
|
||||
industry: '',
|
||||
@@ -187,6 +226,24 @@ export default {
|
||||
this.showQuery = !this.showQuery
|
||||
},
|
||||
|
||||
// 获取客户财务状态
|
||||
getFinanceList() {
|
||||
if (!this.currentCustomerId) return;
|
||||
listFinanceByCustomerId(this.currentCustomerId).then(response => {
|
||||
this.financeList = response.data.financeList || [];
|
||||
this.objectionList = response.data.oobjectionList || [];
|
||||
}).catch(() => {
|
||||
this.$message.error('获取客户财务状态失败');
|
||||
});
|
||||
},
|
||||
|
||||
/** 查询合同配卷列表 */
|
||||
getCoilList() {
|
||||
listContractPackaging(this.form.contractId).then(response => {
|
||||
this.coilList = response.data || [];
|
||||
})
|
||||
},
|
||||
|
||||
debounce(fn, delay) {
|
||||
return (...args) => {
|
||||
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
||||
|
||||
497
klp-ui/src/views/crm/dict/index.vue
Normal file
497
klp-ui/src/views/crm/dict/index.vue
Normal file
@@ -0,0 +1,497 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!-- 左侧:字典类型管理 -->
|
||||
<el-col :span="6" style="height: calc(100vh - 124px); overflow-y: auto;">
|
||||
<div>
|
||||
<div class="dict-type-list">
|
||||
<div
|
||||
v-for="item in typeList"
|
||||
:key="item.dictId"
|
||||
:class="['dict-type-item', { 'active': selectedDictType === item.dictType }]"
|
||||
@click="selectDictType(item.dictType, item.dictId)"
|
||||
>
|
||||
<div class="dict-type-name">{{ item.dictName }}</div>
|
||||
<div class="dict-type-info">
|
||||
<span class="dict-type-code">{{ item.dictType }}</span>
|
||||
<span class="dict-type-id">#{{ item.dictId }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:字典数据管理 -->
|
||||
<el-col :span="18" style="height: 100%; overflow-y: auto;">
|
||||
<div class="dict-data-container">
|
||||
<h3>字典数据管理</h3>
|
||||
<el-form :model="dataQueryParams" ref="dataQueryForm" size="small" :inline="true" v-show="dataShowSearch" label-width="68px">
|
||||
<el-form-item label="字典标签" prop="dictLabel">
|
||||
<el-input
|
||||
v-model="dataQueryParams.dictLabel"
|
||||
placeholder="请输入字典标签"
|
||||
clearable
|
||||
@keyup.enter.native="dataHandleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="dataQueryParams.status" placeholder="数据状态" clearable>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="dataHandleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="dataResetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="dataHandleAdd"
|
||||
v-hasPermi="['system:dict:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="dataSingle"
|
||||
@click="dataHandleUpdate"
|
||||
v-hasPermi="['system:dict:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="dataMultiple"
|
||||
@click="dataHandleDelete"
|
||||
v-hasPermi="['system:dict:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="dataHandleExport"
|
||||
v-hasPermi="['system:dict:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="dataShowSearch" @queryTable="dataGetList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-empty v-if="!dataQueryParams.dictType" description="请选择一个字典类型" />
|
||||
<template v-else>
|
||||
<el-table v-loading="dataLoading" max-height="calc(100vh - 300px)" :data="dataList" @selection-change="dataHandleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典编码" align="center" prop="dictCode" />
|
||||
<el-table-column label="字典标签" align="center" prop="dictLabel">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.listClass == '' || scope.row.listClass == 'default'">{{scope.row.dictLabel}}</span>
|
||||
<el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass">{{scope.row.dictLabel}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字典键值" align="center" prop="dictValue" />
|
||||
<el-table-column label="字典排序" align="center" prop="dictSort" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="dataHandleUpdate(scope.row)"
|
||||
v-hasPermi="['system:dict:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="dataHandleDelete(scope.row)"
|
||||
v-hasPermi="['system:dict:remove']"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="dataTotal>0"
|
||||
:total="dataTotal"
|
||||
:page.sync="dataQueryParams.pageNum"
|
||||
:limit.sync="dataQueryParams.pageSize"
|
||||
@pagination="dataGetList"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 添加或修改字典数据对话框 -->
|
||||
<el-dialog :title="dataTitle" :visible.sync="dataOpen" width="500px" append-to-body>
|
||||
<el-form ref="dataForm" :model="dataForm" :rules="dataRules" label-width="80px">
|
||||
<el-form-item label="字典类型">
|
||||
<el-input v-model="dataForm.dictType" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据标签" prop="dictLabel">
|
||||
<el-input v-model="dataForm.dictLabel" placeholder="请输入数据标签" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据键值" prop="dictValue">
|
||||
<el-input v-model="dataForm.dictValue" placeholder="请输入数据键值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="样式属性" prop="cssClass">
|
||||
<el-input v-model="dataForm.cssClass" placeholder="请输入样式属性" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示排序" prop="dictSort">
|
||||
<el-input-number :controls=false controls-position="right" v-model="dataForm.dictSort" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="回显样式" prop="listClass">
|
||||
<el-select v-model="dataForm.listClass">
|
||||
<el-option
|
||||
v-for="item in listClassOptions"
|
||||
:key="item.value"
|
||||
:label="item.label + '(' + item.value + ')'"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="dataForm.status">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="dataForm.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="dataSubmitForm">确 定</el-button>
|
||||
<el-button @click="dataCancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listType, getType, delType, addType, updateType, refreshCache, optionselect as getDictOptionselect } from "@/api/system/dict/type";
|
||||
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
|
||||
|
||||
export default {
|
||||
name: "Dict",
|
||||
dicts: ['sys_normal_disable'],
|
||||
data() {
|
||||
return {
|
||||
// 字典类型管理相关
|
||||
typeLoading: false,
|
||||
typeIds: [],
|
||||
typeSingle: true,
|
||||
typeMultiple: true,
|
||||
typeShowSearch: true,
|
||||
typeTotal: 0,
|
||||
selectedDictType: '',
|
||||
typeList: [
|
||||
{ dictId: '1996470503006347266', dictName: "钢卷异常位置", dictType: "coil_abnormal_position" },
|
||||
{ dictId: '1996471384858763265', dictName: "钢卷异常缺陷代码", dictType: "coil_abnormal_code" },
|
||||
{ dictId: '1996471559400529922', dictName: "钢卷异常程度", dictType: "coil_abnormal_degree" },
|
||||
{ dictId: '2000385565177729025', dictName: "钢卷厂家", dictType: "coil_manufacturer" },
|
||||
{ dictId: '2000385689094246401', dictName: "钢卷材质", dictType: "coil_material" },
|
||||
{ dictId: '2000385875539447809', dictName: "钢卷名称", dictType: "coil_itemname" },
|
||||
|
||||
{ dictId: '2000445660494381058', dictName: "客户行业", dictType: "customer_industry" },
|
||||
{ dictId: '2000446466396340226', dictName: "客户等级", dictType: "customer_level" },
|
||||
{ dictId: '2010954150756622337', dictName: "钢卷质量状态", dictType: "coil_quality_status" },
|
||||
{ dictId: '2034910283200458753', dictName: "机组产线", dictType: "sys_lines" },
|
||||
|
||||
],
|
||||
typeTitle: "",
|
||||
typeOpen: false,
|
||||
typeDateRange: [],
|
||||
typeQueryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
dictName: undefined,
|
||||
dictType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
typeForm: {},
|
||||
typeRules: {
|
||||
dictName: [
|
||||
{ required: true, message: "字典名称不能为空", trigger: "blur" }
|
||||
],
|
||||
dictType: [
|
||||
{ required: true, message: "字典类型不能为空", trigger: "blur" }
|
||||
]
|
||||
},
|
||||
|
||||
// 字典数据管理相关
|
||||
dataLoading: true,
|
||||
dataIds: [],
|
||||
dataSingle: true,
|
||||
dataMultiple: true,
|
||||
dataShowSearch: true,
|
||||
dataTotal: 0,
|
||||
dataList: [],
|
||||
dataTitle: "",
|
||||
dataOpen: false,
|
||||
listClassOptions: [
|
||||
{
|
||||
value: "default",
|
||||
label: "默认"
|
||||
},
|
||||
{
|
||||
value: "primary",
|
||||
label: "主要"
|
||||
},
|
||||
{
|
||||
value: "success",
|
||||
label: "成功"
|
||||
},
|
||||
{
|
||||
value: "info",
|
||||
label: "信息"
|
||||
},
|
||||
{
|
||||
value: "warning",
|
||||
label: "警告"
|
||||
},
|
||||
{
|
||||
value: "danger",
|
||||
label: "危险"
|
||||
}
|
||||
],
|
||||
typeOptions: [],
|
||||
dataQueryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
dictName: undefined,
|
||||
dictType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
dataForm: {},
|
||||
dataRules: {
|
||||
dictLabel: [
|
||||
{ required: true, message: "数据标签不能为空", trigger: "blur" }
|
||||
],
|
||||
dictValue: [
|
||||
{ required: true, message: "数据键值不能为空", trigger: "blur" }
|
||||
],
|
||||
dictSort: [
|
||||
{ required: true, message: "数据顺序不能为空", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化时设置类型选项
|
||||
this.typeOptions = this.typeList.map(item => ({
|
||||
dictId: item.dictId,
|
||||
dictName: item.dictName,
|
||||
dictType: item.dictType
|
||||
}));
|
||||
},
|
||||
methods: {
|
||||
// 字典数据管理方法
|
||||
/** 查询字典数据列表 */
|
||||
dataGetList() {
|
||||
this.dataLoading = true;
|
||||
listData(this.dataQueryParams).then(response => {
|
||||
this.dataList = response.rows;
|
||||
this.dataTotal = response.total;
|
||||
this.dataLoading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
dataCancel() {
|
||||
this.dataOpen = false;
|
||||
this.dataReset();
|
||||
},
|
||||
// 表单重置
|
||||
dataReset() {
|
||||
this.dataForm = {
|
||||
dictCode: undefined,
|
||||
dictLabel: undefined,
|
||||
dictValue: undefined,
|
||||
cssClass: undefined,
|
||||
listClass: 'default',
|
||||
dictSort: 0,
|
||||
status: "0",
|
||||
remark: undefined
|
||||
};
|
||||
this.resetForm("dataForm");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
dataHandleQuery() {
|
||||
this.dataQueryParams.pageNum = 1;
|
||||
this.dataGetList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
dataResetQuery() {
|
||||
this.resetForm("dataQueryForm");
|
||||
this.dataHandleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
dataHandleAdd() {
|
||||
this.dataReset();
|
||||
this.dataOpen = true;
|
||||
this.dataTitle = "添加字典数据";
|
||||
this.dataForm.dictType = this.dataQueryParams.dictType;
|
||||
},
|
||||
// 多选框选中数据
|
||||
dataHandleSelectionChange(selection) {
|
||||
this.dataIds = selection.map(item => item.dictCode)
|
||||
this.dataSingle = selection.length!=1
|
||||
this.dataMultiple = !selection.length
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
dataHandleUpdate(row) {
|
||||
this.dataReset();
|
||||
const dictCode = row.dictCode || this.dataIds
|
||||
getData(dictCode).then(response => {
|
||||
this.dataForm = response.data;
|
||||
this.dataOpen = true;
|
||||
this.dataTitle = "修改字典数据";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
dataSubmitForm: function() {
|
||||
this.$refs["dataForm"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.dataForm.dictCode != undefined) {
|
||||
updateData(this.dataForm).then(response => {
|
||||
this.$store.dispatch('dict/removeDict', this.dataQueryParams.dictType);
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.dataOpen = false;
|
||||
this.dataGetList();
|
||||
});
|
||||
} else {
|
||||
addData(this.dataForm).then(response => {
|
||||
this.$store.dispatch('dict/removeDict', this.dataQueryParams.dictType);
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.dataOpen = false;
|
||||
this.dataGetList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
dataHandleDelete(row) {
|
||||
const dictCodes = row.dictCode || this.dataIds;
|
||||
this.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?').then(function() {
|
||||
return delData(dictCodes);
|
||||
}).then(() => {
|
||||
this.dataGetList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
this.$store.dispatch('dict/removeDict', this.dataQueryParams.dictType);
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
dataHandleExport() {
|
||||
this.download('system/dict/data/export', {
|
||||
...this.dataQueryParams
|
||||
}, `data_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
|
||||
/** 选择字典类型 */
|
||||
selectDictType(dictType, dictId) {
|
||||
this.selectedDictType = dictType;
|
||||
this.dataQueryParams.dictType = dictType;
|
||||
this.dataGetList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dict-type-container,
|
||||
.dict-data-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.dict-type-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dict-type-item {
|
||||
padding: 15px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.dict-type-item:hover {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dict-type-item.active {
|
||||
border-color: #409eff;
|
||||
background-color: #ecf5ff;
|
||||
box-shadow: 0 2px 12px 0 rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
|
||||
.dict-type-item.active .dict-type-name {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.dict-type-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.dict-type-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.dict-type-code {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dict-type-id {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -102,28 +102,28 @@
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="订单编号" prop="orderCode">
|
||||
<el-input v-model="form.orderCode" placeholder="请输入订单编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同号" prop="contractId">
|
||||
<el-select style="width: 100%;" v-model="form.contractId" placeholder="请选择合同号" filterable clearable @change="handleContractChange">
|
||||
<el-option v-for="item in contractList" :key="item.contractId" :label="item.contractNo"
|
||||
:value="item.contractId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户" prop="customerId">
|
||||
<!-- <el-input v-model="form.customerId" placeholder="请输入客户" /> -->
|
||||
<el-select v-model="form.customerId" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.customerCode"
|
||||
<el-select style="width: 100%;" v-model="form.customerId" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.companyName"
|
||||
:value="item.customerId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单总金额" prop="orderAmount">
|
||||
<el-input v-model="form.orderAmount" placeholder="请输入订单总金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="销售员" prop="salesman">
|
||||
<el-select v-model="form.salesman" placeholder="请选择销售员">
|
||||
<el-select style="width: 100%;" v-model="form.salesman" placeholder="请选择销售员">
|
||||
<el-option v-for="item in dict.type.wip_pack_saleman" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="合同号" prop="contractId">
|
||||
<el-select v-model="form.contractId" placeholder="请选择合同号" filterable clearable @change="handleContractChange">
|
||||
<el-option v-for="item in contractList" :key="item.contractId" :label="item.contractNo"
|
||||
:value="item.contractId" />
|
||||
</el-select>
|
||||
<el-form-item label="订单总金额" prop="orderAmount">
|
||||
<el-input v-model="form.orderAmount" placeholder="请输入订单总金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="交货日期" prop="deliveryDate">
|
||||
<el-date-picker clearable v-model="form.deliveryDate" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
@@ -177,6 +177,10 @@ export default {
|
||||
contractId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -186,7 +190,7 @@ export default {
|
||||
showQuery: false,
|
||||
queryParams: {
|
||||
orderCode: '',
|
||||
customerId: '',
|
||||
customerId: this.customerId,
|
||||
salesman: '',
|
||||
orderStatus: '',
|
||||
contractId: this.contractId,
|
||||
@@ -243,7 +247,10 @@ export default {
|
||||
handleContractChange(contractId) {
|
||||
const contract = this.contractList.find(item => item.contractId === contractId)
|
||||
if (contract) {
|
||||
console.log(contract)
|
||||
this.form.contractCode = contract.contractNo
|
||||
this.form.deliveryDate = contract.deliveryDate
|
||||
this.form.customerId = contract.customerId
|
||||
}
|
||||
|
||||
},
|
||||
@@ -284,7 +291,7 @@ export default {
|
||||
orderId: undefined,
|
||||
orderCode: undefined,
|
||||
orderType: ORDER_TYPE['正式订单'],
|
||||
customerId: undefined,
|
||||
customerId: this.customerId,
|
||||
orderAmount: undefined,
|
||||
salesman: undefined,
|
||||
deliveryDate: undefined,
|
||||
|
||||
@@ -73,12 +73,12 @@ export default {
|
||||
{ required: true, message: '请选择位置', trigger: 'change' }
|
||||
],
|
||||
startPosition: [
|
||||
{ required: true, message: '请输入开始位置', trigger: 'blur' },
|
||||
// { type: 'number', message: '请输入数字', trigger: 'blur' }
|
||||
{ required: true, message: '请输入开始位置', trigger: ['blur', 'change'] },
|
||||
{ validator: this.validateStartPosition, trigger: ['blur', 'change'] }
|
||||
],
|
||||
endPosition: [
|
||||
{ required: true, message: '请输入结束位置', trigger: 'blur' },
|
||||
// { type: 'number', message: '请输入数字', trigger: 'blur' }
|
||||
{ required: true, message: '请输入结束位置', trigger: ['blur', 'change'] },
|
||||
{ validator: this.validateEndPosition, trigger: ['blur', 'change'] }
|
||||
],
|
||||
defectCode: [
|
||||
{ required: true, message: '请选择缺陷代码', trigger: 'change' }
|
||||
@@ -102,14 +102,19 @@ export default {
|
||||
methods: {
|
||||
/** 表单验证 */
|
||||
validate(callback) {
|
||||
if (this.formData.startPosition > this.formData.endPosition) {
|
||||
this.$message.error('开始位置必须小于结束位置');
|
||||
return false;
|
||||
}
|
||||
return this.$refs.form.validate(callback);
|
||||
},
|
||||
/** 重置表单 */
|
||||
resetFields() {
|
||||
this.$refs.form.resetFields();
|
||||
const currentCoilId = this.formData.coilId;
|
||||
this.formData = {
|
||||
abnormalId: undefined,
|
||||
coilId: undefined,
|
||||
coilId: currentCoilId,
|
||||
position: undefined,
|
||||
startPosition: undefined,
|
||||
endPosition: undefined,
|
||||
@@ -124,6 +129,22 @@ export default {
|
||||
if (this.formData.startPosition && this.formData.endPosition) {
|
||||
this.formData.length = this.formData.endPosition - this.formData.startPosition;
|
||||
}
|
||||
},
|
||||
/** 校验开始位置 */
|
||||
validateStartPosition(rule, value, callback) {
|
||||
if (value <= 0) {
|
||||
callback(new Error('开始位置必须为正数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
/** 校验结束位置 */
|
||||
validateEndPosition(rule, value, callback) {
|
||||
if (value <= 0) {
|
||||
callback(new Error('结束位置必须为正数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
<MaterialSelect :hideType="hideType" :itemId.sync="queryParams.itemIds" :itemType.sync="queryParams.itemType"
|
||||
:multiple="true" />
|
||||
|
||||
<el-form-item label="发货单时间">
|
||||
<el-date-picker v-if="showWaybill" v-model="queryParams.shipmentTime" type="daterange" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
<el-form-item v-if="showWaybill" label="发货单时间">
|
||||
<el-date-picker v-model="queryParams.shipmentTime" type="daterange" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
<!-- 统计指标卡 -->
|
||||
<el-row :gutter="10" class="mb10">
|
||||
<el-col :span="8">
|
||||
@@ -71,14 +73,27 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 操作人汇总表格 -->
|
||||
<el-card shadow="hover" :body-style="{ padding: '10px' }" class="mb10">
|
||||
<div slot="header" class="clearfix" style="padding-bottom: 5px;">
|
||||
<span>操作记录趋势</span>
|
||||
</div>
|
||||
<div id="trendChart" style="height: 250px;"></div>
|
||||
</el-card>
|
||||
|
||||
<!-- 图表区域 -->
|
||||
<el-row :gutter="10" class="mb10">
|
||||
<el-col :span="12">
|
||||
<el-card shadow="hover" :body-style="{ padding: '10px' }">
|
||||
<div slot="header" class="clearfix" style="padding-bottom: 5px;">
|
||||
<span>操作记录趋势</span>
|
||||
</div>
|
||||
<div id="trendChart" style="height: 250px;"></div>
|
||||
<el-table :data="userSummaryData" style="width: 100%" height="280px">
|
||||
<el-table-column prop="createBy" label="操作人" width="180"></el-table-column>
|
||||
<el-table-column prop="coilCount" label="操作卷数" width="120"></el-table-column>
|
||||
<el-table-column prop="totalWeight" label="总重量(kg)">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.totalWeight.toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -212,6 +227,8 @@ export default {
|
||||
totalWeight: 0,
|
||||
warehouseCount: 0
|
||||
},
|
||||
// 操作人汇总数据
|
||||
userSummaryData: [],
|
||||
// 图表实例
|
||||
trendChart: null,
|
||||
pieChart: null,
|
||||
@@ -258,7 +275,7 @@ export default {
|
||||
this.queryParams.createEndTime = this.queryParams.createTimeRange[1];
|
||||
}
|
||||
// 移除分页参数,获取全部数据
|
||||
const params = { ...this.queryParams, pageNum:1, pageSize: 10000 };
|
||||
const params = { ...this.queryParams, pageNum: 1, pageSize: 10000 };
|
||||
|
||||
listCoilWarehouseOperationLog(params).then(response => {
|
||||
this.allData = response.rows;
|
||||
@@ -296,6 +313,26 @@ export default {
|
||||
});
|
||||
this.stats.warehouseCount = warehouseIds.size;
|
||||
|
||||
// 按操作人汇总数据
|
||||
const userMap = {};
|
||||
this.allData.forEach(item => {
|
||||
const user = item.createBy || '未知';
|
||||
if (!userMap[user]) {
|
||||
userMap[user] = {
|
||||
createBy: user,
|
||||
coilCount: 0,
|
||||
totalWeight: 0
|
||||
};
|
||||
}
|
||||
userMap[user].coilCount++;
|
||||
if (item.coil && item.coil.netWeight) {
|
||||
userMap[user].totalWeight += parseFloat(item.coil.netWeight);
|
||||
}
|
||||
});
|
||||
|
||||
// 转换为数组并按操作卷数降序排序
|
||||
this.userSummaryData = Object.values(userMap).sort((a, b) => b.coilCount - a.coilCount);
|
||||
|
||||
// 更新图表数据
|
||||
this.updateCharts();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user