| | |
| | | <template> |
| | | <div> |
| | | <a-date-picker :getCalendarContainer="getCalendarContainer" v-model="startValue" :disabled-date="disabledStartDate" |
| | | :disabled-time="disabledStartTime" show-time format="YYYY-MM-DD HH:mm:ss" placeholder="Start" :open="startOpen" |
| | | :disabled-time="disabledStartTime" :show-time="showTime" :format="formatStr" placeholder="Start" :open="startOpen" |
| | | size="small" @openChange="handleStartOpenChange" @change="change(0)" /> |
| | | - |
| | | <a-date-picker :getCalendarContainer="getCalendarContainer" v-model="endValue" :disabled-date="disabledEndDate" |
| | | :disabled-time="disabledEndTime" show-time format="YYYY-MM-DD HH:mm:ss" placeholder="End" :open="endOpen" |
| | | :disabled-time="disabledEndTime" :show-time="showTime" :format="formatStr" placeholder="End" :open="endOpen" |
| | | size="small" @change="change(1)" @openChange="handleEndOpenChange" /> |
| | | </div> |
| | | </template> |
| | |
| | | endOpen: false, |
| | | }; |
| | | }, |
| | | props: ["value", "getCalendarContainer"], |
| | | props: { |
| | | value: { |
| | | required: true, |
| | | }, |
| | | getCalendarContainer: { |
| | | required: true |
| | | }, |
| | | showTime: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | }, |
| | | model: { |
| | | prop: "value", |
| | | event: "change", |
| | |
| | | this.endValue = value[1]; |
| | | }, |
| | | }, |
| | | formatStr() { |
| | | return this.showTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD" |
| | | }, |
| | | }, |
| | | methods: { |
| | | range(start, end) { |
| | |
| | | <slot v-else-if="col.slots && col.slots.title" :name="col.slots.title"></slot> |
| | | <datetime-range v-model="col.search.value" :getCalendarContainer="() => $refs.root" @change="onDateRangeChange(col)"></datetime-range> |
| | | </div> |
| | | <div v-else-if="col.dataType === 'dateRange'" :class="['title', {active: col.search.value && (col.search.value[0] || col.search.value[1])}]"> |
| | | <template v-if="col.title"> |
| | | {{col.title}}: |
| | | </template> |
| | | <slot v-else-if="col.slots && col.slots.title" :name="col.slots.title"></slot> |
| | | <datetime-range v-model="col.search.value" :showTime="false" :getCalendarContainer="() => $refs.root" @change="onDateRangeChange(col)"></datetime-range> |
| | | </div> |
| | | <div v-else-if="col.dataType === 'select'" :class="['title', {active: col.search.value !== undefined}]"> |
| | | <template v-if="col.title"> |
| | | {{col.title}}: |
New file |
| | |
| | | <template> |
| | | <div class=""> |
| | | <a-table |
| | | ref="aTable" |
| | | size="small" |
| | | :scroll="{ y }" |
| | | bordered |
| | | :columns="columns" |
| | | :data-source="dataSource" |
| | | :pagination="false" |
| | | :rowKey="(record, index) => index" |
| | | > |
| | | <template slot="action" slot-scope="text, record"> |
| | | <div v-if="record.url"> |
| | | <a v-if="canView(record)" @click="view(record)">预览</a> |
| | | <template> |
| | | <a-divider type="vertical"></a-divider> |
| | | <a @click="downloadOther(record.url)">下载</a> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | </a-table> |
| | | <a-modal |
| | | :width="600" |
| | | :visible="previewVisible" |
| | | :footer="null" |
| | | @cancel="handleCancel" |
| | | > |
| | | <img alt="example" style="width: 100%" :src="imgUrl" /> |
| | | </a-modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import getWebUrl from "@/assets/js/tools/getWebUrl"; |
| | | import { dwgReview } from "@/pages/workplace/apis"; |
| | | import { mapGetters } from "vuex"; |
| | | export default { |
| | | name: "", |
| | | components: {}, |
| | | props: { |
| | | list: { |
| | | type: Array, |
| | | default() { |
| | | return []; |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | const columns = [ |
| | | { |
| | | title: "文件名称", |
| | | dataIndex: "fileName", |
| | | align: "center", |
| | | width: 200, |
| | | }, |
| | | { |
| | | title: "文件类型", |
| | | dataIndex: "fileType", |
| | | align: "center", |
| | | width: 100, |
| | | }, |
| | | { |
| | | title: "操作", |
| | | dataIndex: "operation", |
| | | key: "operation", |
| | | align: "center", |
| | | width: 200, |
| | | scopedSlots: { customRender: "action" }, |
| | | }, |
| | | ]; |
| | | return { |
| | | y1: 400, |
| | | columns, |
| | | y: 500, |
| | | imgUrl: "", |
| | | previewVisible: false, |
| | | webUrl: getWebUrl(), |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleClick() { |
| | | this.$emit("success", this.list); |
| | | }, |
| | | canView(obj) { |
| | | return [ |
| | | "bmp", |
| | | "jpg", |
| | | "jpeg", |
| | | "gif", |
| | | "png", |
| | | "pdf", |
| | | "doc", |
| | | "docx", |
| | | "dwg", |
| | | ].some((v) => v == obj.fileType); |
| | | }, |
| | | view(obj) { |
| | | switch (obj.fileType) { |
| | | // 图片 |
| | | case "bmp": |
| | | case "jpg": |
| | | case "jpeg": |
| | | case "gif": |
| | | case "png": |
| | | this.imgUrl = this.webUrl + obj.url; |
| | | this.previewVisible = true; |
| | | break; |
| | | case "pdf": |
| | | window.open(this.webUrl + obj.url); |
| | | break; |
| | | case "doc": |
| | | case "docx": |
| | | case "dwg": |
| | | this.dwgReview(obj.url); |
| | | break; |
| | | default: |
| | | this.$message.warn("该类型文件暂不支持预览"); |
| | | break; |
| | | } |
| | | }, |
| | | handleCancel() { |
| | | this.previewVisible = false; |
| | | }, |
| | | dwgReview(url) { |
| | | let loading = this.$layer.loading(); |
| | | dwgReview(url) |
| | | .then((res) => { |
| | | let { code, data, msg } = res.data; |
| | | if (code && data) { |
| | | window.open(this.webUrl + data); |
| | | } else { |
| | | this.$message.error(msg); |
| | | } |
| | | this.$layer.close(loading); |
| | | }) |
| | | .catch((error) => { |
| | | console.log(error); |
| | | this.$layer.close(loading); |
| | | }); |
| | | }, |
| | | downloadOther(url) { |
| | | let reg = /(.*\\+)*(.*)$/; |
| | | let fileName = url.match(reg)[2]; |
| | | |
| | | let link = document.createElement("a"); |
| | | link.style.display = "none"; |
| | | link.href = this.webUrl + url; |
| | | link.download = fileName; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | }, |
| | | }, |
| | | computed: { |
| | | dataSource() { |
| | | let reg = /(.*\\+)*(.*)$/; |
| | | return this.list.map((item) => { |
| | | let fileName = item.match(reg)[2]; |
| | | let arr = fileName.split("."); |
| | | let fileType = arr.length ? arr[arr.length - 1].toLowerCase() : ""; |
| | | return { |
| | | fileName, |
| | | fileType, |
| | | url: item, |
| | | }; |
| | | }); |
| | | }, |
| | | ...mapGetters("account", ["permits"]), |
| | | }, |
| | | mounted() {}, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | /deep/.is-lock td { |
| | | background: #ddd; |
| | | } |
| | | </style> |
New file |
| | |
| | | import axios from "@/assets/axios"; |
| | | |
| | | /** |
| | | * 录入不良品信息 |
| | | * @param {*} data {multipartFileList, defectiveJson} |
| | | * @returns |
| | | */ |
| | | export const addDefective = (data) => { |
| | | return axios({ |
| | | method: "POST", |
| | | url: "defective/addDefective", |
| | | headers: { |
| | | "Content-Type": "multipart/form-data" |
| | | }, |
| | | data |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 处理不良品信息 |
| | | * @param {*} data {multipartFileList, defectiveHisJson} |
| | | * @returns |
| | | */ |
| | | export const updateDefective = (data) => { |
| | | return axios({ |
| | | method: "POST", |
| | | url: "defective/updateDefective", |
| | | headers: { |
| | | "Content-Type": "multipart/form-data" |
| | | }, |
| | | data |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 归档不良品信息 |
| | | * @param {*} data deftId |
| | | * @returns |
| | | */ |
| | | export const stopDefective = (deftId) => { |
| | | return axios({ |
| | | method: "POST", |
| | | url: "defective/stopDefective", |
| | | params: { |
| | | deftId |
| | | } |
| | | }) |
| | | } |
New file |
| | |
| | | <template> |
| | | <div class="dispose"> |
| | | <a-form-model |
| | | ref="formRef" |
| | | name="advanced_search" |
| | | class="ant-advanced-search-form" |
| | | :model="info" |
| | | :rules="rules" |
| | | > |
| | | <a-row> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="入库时间" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="startTime" |
| | | > |
| | | <a-date-picker |
| | | format="YYYY-MM-DD" |
| | | disabled |
| | | valueFormat="YYYY-MM-DD" |
| | | :allowClear="false" |
| | | :disabled-date="disabledDate" |
| | | :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }" |
| | | v-model="info.startTime" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="厂商名称" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="provideName" |
| | | > |
| | | <a-input |
| | | disabled |
| | | placeholder="请输入厂商名称" |
| | | v-model.trim="info.provideName" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="产品名称" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="productName" |
| | | > |
| | | <a-input |
| | | disabled |
| | | placeholder="请输入产品名称" |
| | | v-model.trim="info.productName" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="产品型号" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="type" |
| | | > |
| | | <a-input |
| | | disabled |
| | | placeholder="请输入产品型号" |
| | | v-model.trim="info.type" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="剩余不良数" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="restProduct" |
| | | > |
| | | <a-input disabled v-model.number="info.restProduct" /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="处理数量" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="delProduct" |
| | | > |
| | | <a-input-number |
| | | placeholder="请输入处理数量" |
| | | :min="1" |
| | | :max="info.restProduct" |
| | | v-model.number="info.delProduct" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="24"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="处理描述" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="note" |
| | | > |
| | | <a-textarea |
| | | placeholder="请输入处理描述" |
| | | v-model.trim="info.note" |
| | | :rows="2" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row type="flex" class="row"> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="邮件通知" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="selectedItems" |
| | | > |
| | | <a-select |
| | | mode="multiple" |
| | | placeholder="" |
| | | :value="info.selectedItems" |
| | | style="width: 100%" |
| | | allow-clear |
| | | @change="handleChange" |
| | | > |
| | | <a-select-option |
| | | v-for="item in filteredOptions" |
| | | :key="item.name" |
| | | :value="item.name" |
| | | :disabled="!item.isHasMail" |
| | | > |
| | | {{ item.name }} |
| | | </a-select-option> |
| | | </a-select> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row type="flex" class="row"> |
| | | <a-col flex="8em" class="label">附件</a-col> |
| | | <a-col :flex="1"> |
| | | <a-upload |
| | | class="upload" |
| | | :before-upload="beforeUpload" |
| | | @change="uploadChange" |
| | | multiple |
| | | > |
| | | <!-- accept=".zip,.rar" --> |
| | | <a-button type="primary">选择附件</a-button> |
| | | </a-upload> |
| | | </a-col> |
| | | </a-row> |
| | | </a-form-model> |
| | | <div class="modal-footer"> |
| | | <a-button type="danger" @click="cancel"> 取消 </a-button> |
| | | <a-button type="primary" @click="ok"> 提交 </a-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import moment from "moment"; |
| | | import { updateDefective } from "./apis"; |
| | | |
| | | import { searchDefaultMailUser } from "../../components/emailCard/apis"; |
| | | import { getUserList } from "../../permission/apis"; |
| | | |
| | | export default { |
| | | name: "", |
| | | props: { |
| | | record: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | }, |
| | | data() { |
| | | // console.log("record", this.record, "============="); |
| | | const { |
| | | restProduct, |
| | | id: deftId, |
| | | productName, |
| | | provideName, |
| | | type, |
| | | startTime, |
| | | } = this.record; |
| | | |
| | | return { |
| | | userList: [], |
| | | defaultMailUsers: [], |
| | | selectedItems: [], |
| | | userListAll: [], |
| | | info: { |
| | | deftId, |
| | | restProduct, |
| | | provideName, |
| | | productName, |
| | | note: "", |
| | | type, |
| | | sumProduct: "", |
| | | badProduct: "", |
| | | delProduct: "", |
| | | // startTime: moment().format("YYYY-MM-DD"), |
| | | startTime, |
| | | selectedItems: [], |
| | | }, |
| | | file: null, |
| | | receiverIds: "", |
| | | receiverNames: "", |
| | | rules: { |
| | | delProduct: [ |
| | | { |
| | | required: true, |
| | | message: "请输入处理数量", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | note: [ |
| | | { |
| | | required: true, |
| | | message: "请输入处理描述", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | selectedItems: [ |
| | | { |
| | | required: true, |
| | | message: "请先择要邮件通知的人员", |
| | | trigger: "blur", |
| | | }, |
| | | // { validator: validateSelectedItems, trigger: "change" }, |
| | | ], |
| | | }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | filteredOptions() { |
| | | let users = this.userListAll; |
| | | return users |
| | | .filter((o) => !this.info.selectedItems.includes(o.name)) |
| | | .map((o) => { |
| | | o.isHasMail = o.mail ? true : false; |
| | | return o; |
| | | }); |
| | | }, |
| | | }, |
| | | methods: { |
| | | moment, |
| | | beforeUpload() { |
| | | return false; |
| | | }, |
| | | uploadChange(data) { |
| | | const { file, fileList } = data; |
| | | if (fileList.length) { |
| | | this.file = fileList.map((v) => v.originFileObj); |
| | | } else { |
| | | this.file = null; |
| | | } |
| | | }, |
| | | searchAllUserList() { |
| | | getUserList() |
| | | .then((res) => { |
| | | let rs = res.data; |
| | | if (rs.code && rs.data) { |
| | | this.userListAll = rs.data2; |
| | | this.searchDefaultMailUser(); |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | searchDefaultMailUser() { |
| | | // type为4 |
| | | let type = 4; |
| | | searchDefaultMailUser(type).then((res) => { |
| | | let rs = res.data; |
| | | let data = []; |
| | | if (rs.code === 1) { |
| | | data = rs.data.map((item) => { |
| | | return item.user; |
| | | }); |
| | | } |
| | | this.info.selectedItems = this.userListAll |
| | | .filter((o) => data.includes(o.name) && o.mail) |
| | | .map((item) => { |
| | | return item.name; |
| | | }); |
| | | this.handleChange(this.info.selectedItems); |
| | | }); |
| | | }, |
| | | handleChange(selectedItems) { |
| | | this.info.selectedItems = selectedItems; |
| | | let users = this.userListAll; |
| | | let mailList = users.filter((o) => |
| | | this.info.selectedItems.includes(o.name) |
| | | ); |
| | | this.receiverNames = mailList.map((v) => v.name).join(","); |
| | | this.receiverIds = mailList.map((v) => v.id).join(","); |
| | | }, |
| | | cancel() { |
| | | this.$emit("cancel"); |
| | | }, |
| | | ok() { |
| | | this.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | let loading = this.$layer.loading(); |
| | | const formData = new FormData(); |
| | | if (this.file) { |
| | | this.file.forEach((v) => { |
| | | formData.append("multipartFileList", v); |
| | | }); |
| | | } |
| | | let { deftId, note, delProduct } = this.info; |
| | | formData.append( |
| | | "defectiveHisJson", |
| | | JSON.stringify({ |
| | | deftId, |
| | | note, |
| | | delProduct, |
| | | receiverIds: this.receiverIds, |
| | | receiverNames: this.receiverNames, |
| | | }) |
| | | ); |
| | | |
| | | updateDefective(formData) |
| | | .then((res) => { |
| | | let { code, data } = res.data; |
| | | this.$layer.close(loading); |
| | | if (code && data) { |
| | | this.$message.success("操作成功"); |
| | | this.$emit("ok"); |
| | | } else { |
| | | this.$message.error("操作失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | this.$layer.close(loading); |
| | | }); |
| | | } else { |
| | | this.$message.error("存在未通过检验的表单项"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | disabledDate(current) { |
| | | // Can not select days before today and today |
| | | return current > moment().endOf("day"); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.searchAllUserList(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .modal-footer { |
| | | text-align: right; |
| | | button + button { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | .row { |
| | | color: rgba(0, 0, 0, 0.85); |
| | | line-height: 30px; |
| | | .label { |
| | | text-align: right; |
| | | } |
| | | .label::after { |
| | | content: ":"; |
| | | position: relative; |
| | | top: -0.5px; |
| | | margin: 0 8px 0 2px; |
| | | } |
| | | } |
| | | |
| | | /deep/ .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | </style> |
New file |
| | |
| | | import list from './list'; |
| | | export default list; |
New file |
| | |
| | | <template> |
| | | <div class="main"> |
| | | <div class="inner" ref="wraper"> |
| | | <a-spin class="" :spinning="spinning" tip="拼命加载中..."> |
| | | <a-card> |
| | | <advance-table |
| | | ref="table" |
| | | class="doc-center-table" |
| | | :data-source="dataSource" |
| | | :columns="columns" |
| | | :loading="loading" |
| | | title="" |
| | | row-key="id" |
| | | @search="onSearch" |
| | | @refresh="onRefresh" |
| | | @reset="onReset" |
| | | :format-conditions="true" |
| | | :scroll="{ x: 400, y }" |
| | | :pagination="{ |
| | | current: pageCurr, |
| | | pageSize: pageSize, |
| | | total: total, |
| | | showSizeChanger: true, |
| | | showLessItems: true, |
| | | showQuickJumper: true, |
| | | pageSizeOptions: ['10', '20', '50', '100'], |
| | | showTotal: (total, range) => |
| | | `第 ${range[0]}-${range[1]} 条,总计 ${total} 条`, |
| | | onChange: onPageChange, |
| | | onShowSizeChange: onSizeChange, |
| | | }" |
| | | :rowClassName="rowClassFn" |
| | | > |
| | | <template slot="dataIndex" slot-scope="{ index }"> |
| | | {{ index + 1 }} |
| | | </template> |
| | | <template slot="title"> |
| | | <a-space class="operator"> |
| | | <span class="title">不良品中心</span> |
| | | <a-button |
| | | v-if="canUploadBom" |
| | | type="primary" |
| | | @click="uploadDefective" |
| | | >新增</a-button |
| | | > |
| | | </a-space> |
| | | </template> |
| | | <template slot="action" slot-scope="{ record }"> |
| | | <a @click="viewLog(record)">处理记录</a> |
| | | <template v-if="record.nameList && record.nameList.length"> |
| | | <a-divider type="vertical"></a-divider> |
| | | <a @click="showFileList(record)">附件</a> |
| | | </template> |
| | | <a-divider type="vertical"></a-divider> |
| | | <!-- TODO --> |
| | | <a v-if="record.confirmStatus < 2" @click="dispose(record)" |
| | | >处理</a |
| | | > |
| | | <a |
| | | v-else-if="record.confirmStatus == 2" |
| | | @click="stopDefective(record)" |
| | | >归档</a |
| | | > |
| | | </template> |
| | | </advance-table> |
| | | </a-card> |
| | | </a-spin> |
| | | </div> |
| | | <!-- 上传 --> |
| | | <a-modal |
| | | :visible="bomUploadShow" |
| | | :width="760" |
| | | title="上传不良品信息" |
| | | :destroyOnClose="true" |
| | | :maskClosable="false" |
| | | @cancel="bomUploadCancel" |
| | | @ok="bomUploadOk" |
| | | :footer="null" |
| | | > |
| | | <prod-upload @ok="bomUploadOk" @cancel="bomUploadCancel"></prod-upload> |
| | | </a-modal> |
| | | <!-- 处理 --> |
| | | <a-modal |
| | | :visible="disposeVisible" |
| | | :width="760" |
| | | title="处理不良品" |
| | | :destroyOnClose="true" |
| | | :maskClosable="false" |
| | | @cancel="disposeCancel" |
| | | @ok="disposeOk" |
| | | :footer="null" |
| | | > |
| | | <dispose-upload |
| | | :record="currentData" |
| | | @ok="disposeOk" |
| | | @cancel="disposeCancel" |
| | | ></dispose-upload> |
| | | </a-modal> |
| | | <!-- 操作记录 --> |
| | | <a-modal |
| | | :visible="logVisible" |
| | | :width="760" |
| | | title="操作记录" |
| | | :destroyOnClose="true" |
| | | :maskClosable="false" |
| | | @cancel="logVisible = false" |
| | | :footer="null" |
| | | > |
| | | <div class="log-content" v-if="logVisible"> |
| | | <a-timeline> |
| | | <a-timeline-item |
| | | v-for="(item, idx) in logList" |
| | | :key="'log_' + idx" |
| | | :color=" |
| | | 0 == item.confirmStatus || 3 == item.confirmStatus |
| | | ? 'red' |
| | | : 'green' |
| | | " |
| | | > |
| | | <div> |
| | | <span class="user">{{ item.delName }}</span> 在 |
| | | <span class="time">{{ item.recordTime }}</span> |
| | | <template v-if="0 == item.confirmStatus"> |
| | | 创建了不良品记录 |
| | | <span class="rest">余({{ item.restProduct }})</span> |
| | | </template> |
| | | <template v-else-if="3 == item.confirmStatus"> |
| | | 归档了不良品记录 |
| | | </template> |
| | | <template v-else> |
| | | {{ { "1": "处理", "2": "处理" }[item.confirmStatus] }}了 |
| | | <span class="version">{{ item.delProduct }}</span |
| | | >个不良品 <span class="rest">余({{ item.restProduct }})</span> |
| | | <div class="">描述: {{ item.note }}</div> |
| | | <div |
| | | class="others" |
| | | v-if="item.hisNameList && item.hisNameList.length" |
| | | > |
| | | <div class="label">附件</div> |
| | | <div class="content"> |
| | | <div |
| | | class="item" |
| | | v-for="file in item.hisNameList" |
| | | :key="file" |
| | | > |
| | | <div class="file-name">{{ file }}</div> |
| | | <div class="btn-list"> |
| | | <a-button |
| | | class="btn" |
| | | v-if="canView(file)" |
| | | @click="view(file, item.delUrl)" |
| | | >预览</a-button |
| | | > |
| | | <a-button |
| | | class="btn" |
| | | type="primary" |
| | | @click="downloadOther(file, item.delUrl)" |
| | | >下载</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | </a-timeline-item> |
| | | </a-timeline> |
| | | </div> |
| | | </a-modal> |
| | | |
| | | <!-- 附件 --> |
| | | <a-modal |
| | | :visible="otherFilesVisible" |
| | | :width="760" |
| | | title="附件" |
| | | :destroyOnClose="true" |
| | | :maskClosable="false" |
| | | @cancel="otherFilesVisible = false" |
| | | :footer="null" |
| | | > |
| | | <files-list v-if="otherFilesVisible" :list="fileList"></files-list> |
| | | </a-modal> |
| | | <a-modal |
| | | :width="600" |
| | | :visible="previewVisible" |
| | | :footer="null" |
| | | @cancel="handleCancel" |
| | | > |
| | | <img alt="example" style="width: 100%" :src="imgUrl" /> |
| | | </a-modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AdvanceTable from "@/components/table/advance/AdvanceTable"; |
| | | import ProdUpload from "./prodUpload"; |
| | | import DisposeUpload from "./disposeUpload"; |
| | | import DrawUpload from "@/pages/components/drawUpload"; |
| | | import DownloadReason from "@/pages/components/downloadReason"; |
| | | import DownloadLogs from "@/pages/components/downloadLogs"; |
| | | |
| | | import filesList from "@/pages/components/filesList"; |
| | | |
| | | import getWebUrl from "@/assets/js/tools/getWebUrl"; |
| | | |
| | | import { stopDefective } from "./apis"; |
| | | import { mapGetters } from "vuex"; |
| | | import checkPermit from "@/assets/js/tools/checkPermit"; |
| | | import PERMITS from "@/assets/js/const/const_permits"; |
| | | |
| | | import createWs from "@/assets/js/websocket"; |
| | | import DiffList from "@/pages/components/diffList"; |
| | | import FeedbackForm from "../components/feedbackForm.vue"; |
| | | import OwnerDownload from "../components/ownerDownload"; |
| | | import moment from "moment"; |
| | | const WSMixin = createWs("defective"); |
| | | |
| | | export default { |
| | | name: "", |
| | | mixins: [WSMixin], |
| | | data() { |
| | | return { |
| | | previewVisible: false, |
| | | imgUrl: "", |
| | | fileList: [], |
| | | otherFilesVisible: false, |
| | | currentData: {}, |
| | | logVisible: false, |
| | | disposeVisible: false, |
| | | logList: [], |
| | | |
| | | ownerLogVisible: false, |
| | | reason: "", |
| | | reasonVisible: false, |
| | | oprateInfo: "", |
| | | downloadlogVisible: false, |
| | | tester: [], |
| | | downloadReasonVisible: false, |
| | | curObj: null, |
| | | errorVisible: false, |
| | | feedbackShow: false, |
| | | lockListVisible: false, |
| | | currentObj: null, |
| | | bomLockList: [], |
| | | otherLockList: [], |
| | | ecrList: [], |
| | | ecrListVisible: false, |
| | | fromProd: undefined, |
| | | prodList: [], |
| | | diffData: {}, |
| | | bomUploadShow: false, |
| | | prodData: {}, |
| | | userListAll: [], |
| | | mailList: [], |
| | | file: null, |
| | | // title: "", |
| | | fileUrl: "", |
| | | resList: [], |
| | | uploadShow: false, |
| | | customShow: false, |
| | | customProd: null, |
| | | editShow: false, |
| | | editObj: undefined, |
| | | selectedRowKeys: [], |
| | | selectedRows: [], |
| | | spinning: false, |
| | | loading: false, |
| | | pageCurr: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | y: 400, |
| | | update: -1, |
| | | webUrl: getWebUrl(), |
| | | conditions: {}, |
| | | columns: [ |
| | | { |
| | | fixed: "left", |
| | | title: "序号", |
| | | dataIndex: "dataIndex", |
| | | key: "dataIndex", |
| | | align: "center", |
| | | width: 60, |
| | | noSearch: true, |
| | | scopedSlots: { customRender: "dataIndex" }, |
| | | }, |
| | | { |
| | | title: "物料名称", |
| | | dataIndex: "productName", |
| | | key: "productName", |
| | | width: 130, |
| | | align: "center", |
| | | // searchAble: true, |
| | | noSearch: true, |
| | | }, |
| | | { |
| | | title: "型号", |
| | | dataIndex: "type", |
| | | key: "type", |
| | | align: "center", |
| | | width: 180, |
| | | noSearch: true, |
| | | }, |
| | | { |
| | | title: "厂商名称", |
| | | dataIndex: "provideName", |
| | | key: "provideName", |
| | | align: "center", |
| | | width: 180, |
| | | // searchAble: true, |
| | | noSearch: true, |
| | | }, |
| | | { |
| | | title: "入料时间", |
| | | dataIndex: "startTimeEx", |
| | | key: "startTimeEx", |
| | | align: "center", |
| | | width: 160, |
| | | searchAble: true, |
| | | dataType: "dateRange", |
| | | }, |
| | | { |
| | | title: "创建人", |
| | | dataIndex: "recorder", |
| | | align: "center", |
| | | width: 160, |
| | | searchAble: true, |
| | | dataType: "select", |
| | | search: { |
| | | default: "", |
| | | selectOptions: [], |
| | | }, |
| | | }, |
| | | { |
| | | title: "状态", |
| | | dataIndex: "status", |
| | | align: "center", |
| | | searchAble: true, |
| | | dataType: "select", |
| | | search: { |
| | | default: "", |
| | | selectOptions: [ |
| | | { |
| | | title: "全部", |
| | | value: "", |
| | | }, |
| | | { |
| | | title: "未处理", |
| | | value: 0, |
| | | }, |
| | | { |
| | | title: "处理中", |
| | | value: 1, |
| | | }, |
| | | { |
| | | title: "已完成", |
| | | value: 2, |
| | | }, |
| | | { |
| | | title: "归档", |
| | | value: 3, |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | title: "总数量", |
| | | dataIndex: "sumProduct", |
| | | align: "center", |
| | | // searchAble: true, |
| | | noSearch: true, |
| | | // visible: false, |
| | | }, |
| | | { |
| | | title: "不良数", |
| | | dataIndex: "badProduct", |
| | | align: "center", |
| | | // searchAble: true, |
| | | noSearch: true, |
| | | // visible: false, |
| | | }, |
| | | { |
| | | title: "不良描述", |
| | | dataIndex: "content", |
| | | align: "center", |
| | | // searchAble: true, |
| | | noSearch: true, |
| | | // visible: false, |
| | | }, |
| | | { |
| | | title: "操作", |
| | | dataIndex: "operation", |
| | | key: "operation", |
| | | align: "center", |
| | | width: 228, |
| | | fixed: "right", |
| | | scopedSlots: { customRender: "action" }, |
| | | noSearch: true, |
| | | }, |
| | | ], |
| | | dataSource: [], |
| | | }; |
| | | }, |
| | | components: { |
| | | AdvanceTable, |
| | | // ChangeParts, |
| | | filesList, |
| | | ProdUpload, |
| | | DisposeUpload, |
| | | DrawUpload, |
| | | DiffList, |
| | | FeedbackForm, |
| | | DownloadReason, |
| | | DownloadLogs, |
| | | OwnerDownload, |
| | | }, |
| | | methods: { |
| | | rowClassFn(record) { |
| | | let classList = []; |
| | | classList.push("level-" + record.confirmStatus); |
| | | return classList; |
| | | }, |
| | | dispose(record) { |
| | | this.currentData = record; |
| | | this.disposeVisible = true; |
| | | }, |
| | | canView(fileName) { |
| | | let arr = fileName.split("."); |
| | | let fileType = arr.length ? arr[arr.length - 1].toLowerCase() : ""; |
| | | return [ |
| | | "bmp", |
| | | "jpg", |
| | | "jpeg", |
| | | "gif", |
| | | "png", |
| | | "pdf", |
| | | "doc", |
| | | "docx", |
| | | "dwg", |
| | | ].some((v) => v == fileType); |
| | | }, |
| | | view(fileName, url) { |
| | | let arr = fileName.split("."); |
| | | let fileType = arr.length ? arr[arr.length - 1].toLowerCase() : ""; |
| | | switch (fileType) { |
| | | // 图片 |
| | | case "bmp": |
| | | case "jpg": |
| | | case "jpeg": |
| | | case "gif": |
| | | case "png": |
| | | this.imgUrl = this.webUrl + url + fileName; |
| | | this.previewVisible = true; |
| | | break; |
| | | case "pdf": |
| | | window.open(this.webUrl + url + fileName); |
| | | break; |
| | | case "doc": |
| | | case "docx": |
| | | case "dwg": |
| | | this.dwgReview(url + fileName); |
| | | break; |
| | | default: |
| | | this.$message.warn("该类型文件暂不支持预览"); |
| | | break; |
| | | } |
| | | }, |
| | | handleCancel() { |
| | | this.previewVisible = false; |
| | | }, |
| | | downloadOther(fileName, url) { |
| | | let link = document.createElement("a"); |
| | | link.style.display = "none"; |
| | | link.href = this.webUrl + url + fileName; |
| | | link.download = fileName; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | }, |
| | | stopDefective(record) { |
| | | // console.log("record", record, "============="); |
| | | const self = this; |
| | | this.$confirm({ |
| | | title: "请确认", |
| | | content: "请确认是否进行归档操作?", |
| | | onOk() { |
| | | stopDefective(record.id) |
| | | .then((res) => { |
| | | let { code, data } = res.data; |
| | | if (code && data) { |
| | | self.$message.success("操作成功"); |
| | | } else { |
| | | self.$message.error("操作失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | }); |
| | | }, |
| | | onCancel() {}, |
| | | }); |
| | | }, |
| | | onSearch(conditions, searchOptions) { |
| | | // console.log(conditions); |
| | | // console.log(searchOptions); |
| | | this.pageCurr = 1; |
| | | this.conditions = conditions; |
| | | this.sendMessage(); |
| | | }, |
| | | onPageChange(page, pageSize) { |
| | | this.pageCurr = page; |
| | | this.pageSize = pageSize; |
| | | this.sendMessage(); |
| | | }, |
| | | onSizeChange(current, size) { |
| | | this.pageCurr = 1; |
| | | this.pageSize = size; |
| | | this.sendMessage(); |
| | | }, |
| | | onRefresh(conditions) { |
| | | this.conditions = conditions; |
| | | this.sendMessage(); |
| | | }, |
| | | onReset(conditions) { |
| | | this.conditions = conditions; |
| | | this.sendMessage(); |
| | | }, |
| | | showFileList(record) { |
| | | let { nameList, fileUrl } = record; |
| | | // let baseUrl = this.webUrl; |
| | | this.fileList = nameList.map((v) => fileUrl + v); |
| | | this.otherFilesVisible = true; |
| | | }, |
| | | searchData(res) { |
| | | if (res) { |
| | | // res = res.data; |
| | | // console.log(res, "======"); |
| | | let data = []; |
| | | let total = 0; |
| | | if (res.code && res.data) { |
| | | data = res.data2.list.map((v) => { |
| | | v.status = ["未处理", "处理中", "已完成", "归档"][v.confirmStatus]; |
| | | v.recorder = v.senderName; |
| | | return v; |
| | | }); |
| | | total = res.data2.total; |
| | | } |
| | | this.dataSource = data; |
| | | this.total = total; |
| | | if (-1 == this.update) { |
| | | this.update = Math.random(); |
| | | } |
| | | } |
| | | }, |
| | | resize() { |
| | | setTimeout(() => { |
| | | this.update = Math.random(); |
| | | }, 200); |
| | | }, |
| | | onWSOpen() { |
| | | this.$nextTick(() => { |
| | | this.sendMessage(); |
| | | }); |
| | | }, |
| | | sendMessage() { |
| | | if (!this.isWSOpen) { |
| | | return false; |
| | | } |
| | | const { pageCurr, pageSize, conditions, columns } = this; |
| | | let params = {}; |
| | | let col, index; |
| | | Object.keys(conditions).forEach((v) => { |
| | | switch (v) { |
| | | case "startTimeEx": |
| | | if (conditions[v]) { |
| | | if (conditions[v][0]) { |
| | | params["startTime"] = |
| | | moment(conditions[v][0]).format("YYYY-MM-DD") + " 00:00:00"; |
| | | } |
| | | if (conditions[v][1]) { |
| | | params["endTime"] = |
| | | moment(conditions[v][1]).format("YYYY-MM-DD") + " 23:59:59"; |
| | | } |
| | | } |
| | | break; |
| | | case "status": |
| | | if ("" !== conditions[v]) { |
| | | params["confirmStatus"] = conditions[v]; |
| | | } |
| | | break; |
| | | case "recorder": |
| | | if ("" !== conditions[v]) { |
| | | params["senderId"] = conditions[v]; |
| | | } |
| | | break; |
| | | default: |
| | | params[v] = conditions[v]; |
| | | break; |
| | | } |
| | | }); |
| | | let data = { |
| | | pageSize, |
| | | pageCurr, |
| | | ...params, |
| | | }; |
| | | // console.log("=====9=", data, JSON.stringify(data)); |
| | | this.SOCKET.send(JSON.stringify(data)); |
| | | }, |
| | | onWSMessage(res) { |
| | | res = JSON.parse(res.data); |
| | | // // console.log(res, "=====111data"); |
| | | this.searchData(res); |
| | | }, |
| | | activeFN() { |
| | | this.resize(); |
| | | }, |
| | | uploadDefective() { |
| | | this.bomUploadShow = true; |
| | | }, |
| | | disposeCancel() { |
| | | this.disposeVisible = false; |
| | | }, |
| | | disposeOk() { |
| | | this.disposeVisible = false; |
| | | }, |
| | | bomUploadCancel() { |
| | | this.bomUploadShow = false; |
| | | }, |
| | | bomUploadOk() { |
| | | this.bomUploadShow = false; |
| | | // 调用sendMessage 更新列表 |
| | | this.pageCurr = 1; |
| | | this.sendMessage(); |
| | | }, |
| | | viewLog(obj) { |
| | | // console.log(obj); |
| | | this.logList = obj.hisList; |
| | | this.logVisible = true; |
| | | }, |
| | | logCancel() { |
| | | this.logVisible = false; |
| | | }, |
| | | }, |
| | | watch: { |
| | | update(n) { |
| | | if (-1 != n && !this._inactive) { |
| | | this.$nextTick(() => { |
| | | const table = this.$refs.table; |
| | | const header = document.querySelectorAll( |
| | | ".doc-center-table .ant-table-header" |
| | | )[0].clientHeight; |
| | | const bar = document.querySelectorAll(".header-bar")[0].clientHeight; |
| | | if (table.fullScreen) { |
| | | this.y = table.$el.clientHeight - bar - header - 64; |
| | | } else { |
| | | const wraper = this.$refs.wraper.clientHeight; |
| | | const card = document.querySelectorAll(".ant-card-body")[0]; |
| | | const { paddingBottom, paddingTop } = getComputedStyle(card, null); |
| | | const h = |
| | | wraper - |
| | | header - |
| | | 64 - |
| | | bar - |
| | | parseInt(paddingBottom) - |
| | | parseInt(paddingTop); |
| | | // console.log(h, "h",wraper, header, bar ); |
| | | this.y = h; |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | affixed() { |
| | | setTimeout(() => { |
| | | this.update = Math.random(); |
| | | }, 200); |
| | | }, |
| | | }, |
| | | computed: { |
| | | ...mapGetters("account", [ |
| | | "roles", |
| | | "projectManagerList", |
| | | "generalManagerList", |
| | | "permits", |
| | | "user", |
| | | ]), |
| | | ...mapGetters("setting", ["affixed"]), |
| | | canUploadBom() { |
| | | return checkPermit(PERMITS.uploadBom, this.permits); |
| | | }, |
| | | canDownloadBom() { |
| | | return checkPermit(PERMITS.downloadBom, this.permits); |
| | | }, |
| | | canFeedback() { |
| | | return checkPermit(PERMITS.feedback, this.permits); |
| | | }, |
| | | abLabel() { |
| | | let num = this.abTbl.dataSource.length; |
| | | num = num > 99 ? "99+" : num; |
| | | return "异常(" + num + ")"; |
| | | }, |
| | | errorLabel() { |
| | | let num = this.errorTbl.dataSource.length; |
| | | num = num > 99 ? "99+" : num; |
| | | return "错误(" + num + ")"; |
| | | }, |
| | | abState() { |
| | | let result = false; |
| | | if (this.abTbl.dataSource.length != 0) { |
| | | if (this.abTbl.ignore) { |
| | | result = false; |
| | | } else { |
| | | result = true; |
| | | } |
| | | } else { |
| | | result = false; |
| | | } |
| | | |
| | | return result; |
| | | }, |
| | | submitState() { |
| | | let result = { |
| | | code: 0, |
| | | msg: "存在异常或错误的数据,请修复后再提交", |
| | | }; |
| | | if (this.abState) { |
| | | result.code = 1; |
| | | } else { |
| | | result.code = 0; |
| | | } |
| | | |
| | | if (this.errorTbl.dataSource.length != 0) { |
| | | result.code = 1; |
| | | } |
| | | |
| | | return result; |
| | | }, |
| | | isTester() { |
| | | return this.tester.some((v) => v == this.user.name); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.sendMessage(); |
| | | window.addEventListener("resize", this.resize); |
| | | }, |
| | | destroyed() { |
| | | window.removeEventListener("resize", this.resize); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .main { |
| | | height: 100%; |
| | | position: relative; |
| | | |
| | | .inner { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .img-wraper { |
| | | width: 80px; |
| | | height: 50px; |
| | | display: inline-block; |
| | | |
| | | .image-view { |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | /deep/img { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: contain; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /deep/table { |
| | | table-layout: fixed; |
| | | } |
| | | |
| | | .text-right { |
| | | text-align: right; |
| | | |
| | | span::after { |
| | | content: ":"; |
| | | position: relative; |
| | | top: -0.5px; |
| | | margin: 0 8px 0 2px; |
| | | } |
| | | } |
| | | |
| | | .upload { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .modal-footer { |
| | | text-align: right; |
| | | |
| | | button + button { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | |
| | | .mt8 { |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .from { |
| | | width: 100%; |
| | | } |
| | | |
| | | .label { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | padding-right: 1em; |
| | | align-items: center; |
| | | } |
| | | |
| | | .bom-list /deep/ .ant-card-body { |
| | | padding: 8px 24px; |
| | | } |
| | | |
| | | .log-content { |
| | | max-height: 400px; |
| | | overflow-y: auto; |
| | | |
| | | .user { |
| | | color: #23aaf2; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .rest, |
| | | .time { |
| | | color: #f9be13; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .version { |
| | | color: #0aedb2; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .ant-timeline-item:first-of-type { |
| | | padding-top: 6px; |
| | | } |
| | | } |
| | | |
| | | .table-title { |
| | | font-weight: 700; |
| | | color: #13c2c2; |
| | | } |
| | | |
| | | .btn-grp .ant-btn { |
| | | min-width: 6.4em; |
| | | } |
| | | /deep/.level-1 > td { |
| | | background: #fec54b; |
| | | } |
| | | /deep/.level-1.level-1.level-1.ant-table-row-hover > td, |
| | | /deep/.level-1.level-1.level-1:hover > td { |
| | | background: #fcd583; |
| | | } |
| | | /deep/.level-0 > td { |
| | | background: #fca4b3; |
| | | } |
| | | /deep/.level-0.level-0.level-0.ant-table-row-hover > td, |
| | | /deep/.level-0.level-0.level-0:hover > td { |
| | | background: #f6c4cc; |
| | | } |
| | | /deep/.level-2 > td { |
| | | background: #7bfd7b; |
| | | } |
| | | /deep/.level-2.level-2.level-2.ant-table-row-hover > td, |
| | | /deep/.level-2.level-2.level-2:hover > td { |
| | | background: #b2fbbd; |
| | | } |
| | | .others { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | .label { |
| | | margin-right: 0.4em; |
| | | &::after { |
| | | content: ":"; |
| | | } |
| | | } |
| | | .content { |
| | | flex: 1; |
| | | .item { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 0.4em; |
| | | .file-name { |
| | | flex: 1; |
| | | text-align: right; |
| | | padding-right: 0.6em; |
| | | } |
| | | .btn { |
| | | & + .btn { |
| | | margin-left: 0.4em; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="less"> |
| | | .full-modal { |
| | | height: 100%; |
| | | .ant-modal { |
| | | max-width: 100%; |
| | | height: 100%; |
| | | top: 0; |
| | | padding-bottom: 0; |
| | | margin: 0; |
| | | } |
| | | .ant-modal-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | overflow: hidden; |
| | | // height: calc(100vh); |
| | | } |
| | | .ant-modal-body { |
| | | flex: 1; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class=""> |
| | | <a-form-model |
| | | ref="formRef" |
| | | name="advanced_search" |
| | | class="ant-advanced-search-form" |
| | | :model="info" |
| | | :rules="rules" |
| | | > |
| | | <a-row> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="入库时间" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="startTime" |
| | | > |
| | | <a-date-picker |
| | | format="YYYY-MM-DD" |
| | | valueFormat="YYYY-MM-DD" |
| | | :allowClear="false" |
| | | :disabled-date="disabledDate" |
| | | :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }" |
| | | v-model="info.startTime" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="厂商名称" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="provideName" |
| | | > |
| | | <a-input |
| | | placeholder="请输入厂商名称" |
| | | v-model.trim="info.provideName" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="产品名称" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="productName" |
| | | > |
| | | <a-input |
| | | placeholder="请输入产品名称" |
| | | v-model.trim="info.productName" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="产品型号" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="type" |
| | | > |
| | | <a-input placeholder="请输入产品型号" v-model.trim="info.type" /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="总数" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="sumProduct" |
| | | > |
| | | <a-input-number |
| | | placeholder="请输入来料总数" |
| | | :min="1" |
| | | v-model.number="info.sumProduct" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="不良产品数" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="badProduct" |
| | | > |
| | | <a-input-number |
| | | placeholder="请输入不良产品数" |
| | | :min="1" |
| | | :max="info.sumProduct" |
| | | v-model.number="info.badProduct" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | <a-col :span="24"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="不良现象描述" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="content" |
| | | > |
| | | <a-textarea |
| | | placeholder="请输入不良现象描述" |
| | | v-model.trim="info.content" |
| | | :rows="2" |
| | | /> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row type="flex" class="row"> |
| | | <a-col :span="12"> |
| | | <a-form-model-item |
| | | class="ant-row-flex" |
| | | label="邮件通知" |
| | | :labelCol="{ flex: '8em' }" |
| | | :wrapperCol="{ flex: 1 }" |
| | | prop="selectedItems" |
| | | > |
| | | <a-select |
| | | mode="multiple" |
| | | placeholder="" |
| | | :value="info.selectedItems" |
| | | style="width: 100%" |
| | | allow-clear |
| | | @change="handleChange" |
| | | > |
| | | <a-select-option |
| | | v-for="item in filteredOptions" |
| | | :key="item.name" |
| | | :value="item.name" |
| | | :disabled="!item.isHasMail" |
| | | > |
| | | {{ item.name }} |
| | | </a-select-option> |
| | | </a-select> |
| | | </a-form-model-item> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row type="flex" class="row"> |
| | | <a-col flex="8em" class="label">附件</a-col> |
| | | <a-col :flex="1"> |
| | | <a-upload |
| | | class="upload" |
| | | :before-upload="beforeUpload" |
| | | @change="uploadChange" |
| | | multiple |
| | | > |
| | | <!-- accept=".zip,.rar" --> |
| | | <a-button type="primary">选择附件</a-button> |
| | | </a-upload> |
| | | </a-col> |
| | | </a-row> |
| | | </a-form-model> |
| | | <div class="modal-footer"> |
| | | <a-button type="danger" @click="cancel"> 取消 </a-button> |
| | | <a-button type="primary" @click="ok"> 提交 </a-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import moment from "moment"; |
| | | import { addDefective } from "./apis"; |
| | | |
| | | import { searchDefaultMailUser } from "../../components/emailCard/apis"; |
| | | import { getUserList } from "../../permission/apis"; |
| | | |
| | | export default { |
| | | name: "", |
| | | props: {}, |
| | | data() { |
| | | const validatebadProduct = (rule, value, callback) => { |
| | | if (this.info.sumProduct == "") { |
| | | callback(new Error('请先输入总数')); |
| | | this.$refs.formRef.validateField("sumProduct"); |
| | | } |
| | | callback(); |
| | | }; |
| | | return { |
| | | userList: [], |
| | | defaultMailUsers: [], |
| | | selectedItems: [], |
| | | userListAll: [], |
| | | info: { |
| | | provideName: "", |
| | | productName: "", |
| | | content: "", |
| | | type: "", |
| | | sumProduct: "", |
| | | badProduct: "", |
| | | startTime: moment().format("YYYY-MM-DD"), |
| | | selectedItems: [], |
| | | }, |
| | | file: null, |
| | | receiverIds: "", |
| | | receiverNames: "", |
| | | rules: { |
| | | startTime: [ |
| | | { |
| | | required: true, |
| | | message: "请选择入库日期", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | provideName: [ |
| | | { |
| | | required: true, |
| | | message: "请输入厂商名称", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | productName: [ |
| | | { |
| | | required: true, |
| | | message: "请输入产品名称", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | type: [ |
| | | { |
| | | required: true, |
| | | message: "请输入型号", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | sumProduct: [ |
| | | { |
| | | required: true, |
| | | message: "请输入总数", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | badProduct: [ |
| | | { |
| | | required: true, |
| | | message: "请输入不良产品数", |
| | | trigger: "blur", |
| | | }, |
| | | { validator: validatebadProduct, trigger: "change" }, |
| | | ], |
| | | content: [ |
| | | { |
| | | required: true, |
| | | message: "请输入不良现象描述", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | selectedItems: [ |
| | | { |
| | | required: true, |
| | | message: "请先择要邮件通知的人员", |
| | | trigger: "blur", |
| | | }, |
| | | // { validator: validateSelectedItems, trigger: "change" }, |
| | | ], |
| | | }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | filteredOptions() { |
| | | let users = this.userListAll; |
| | | return users |
| | | .filter((o) => !this.info.selectedItems.includes(o.name)) |
| | | .map((o) => { |
| | | o.isHasMail = o.mail ? true : false; |
| | | return o; |
| | | }); |
| | | }, |
| | | }, |
| | | methods: { |
| | | moment, |
| | | beforeUpload() { |
| | | return false; |
| | | }, |
| | | uploadChange(data) { |
| | | const { file, fileList } = data; |
| | | if (fileList.length) { |
| | | this.file = fileList.map((v) => v.originFileObj); |
| | | } else { |
| | | this.file = null; |
| | | } |
| | | }, |
| | | searchAllUserList() { |
| | | getUserList() |
| | | .then((res) => { |
| | | let rs = res.data; |
| | | if (rs.code && rs.data) { |
| | | this.userListAll = rs.data2; |
| | | this.searchDefaultMailUser(); |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | searchDefaultMailUser() { |
| | | // type为4 |
| | | let type = 4; |
| | | searchDefaultMailUser(type).then((res) => { |
| | | let rs = res.data; |
| | | let data = []; |
| | | if (rs.code === 1) { |
| | | data = rs.data.map((item) => { |
| | | return item.user; |
| | | }); |
| | | } |
| | | this.info.selectedItems = this.userListAll |
| | | .filter((o) => data.includes(o.name) && o.mail) |
| | | .map((item) => { |
| | | return item.name; |
| | | }); |
| | | this.handleChange(this.info.selectedItems); |
| | | }); |
| | | }, |
| | | handleChange(selectedItems) { |
| | | this.info.selectedItems = selectedItems; |
| | | let users = this.userListAll; |
| | | let mailList = users.filter((o) => |
| | | this.info.selectedItems.includes(o.name) |
| | | ); |
| | | this.receiverNames = mailList.map((v) => v.name).join(","); |
| | | this.receiverIds = mailList.map((v) => v.id).join(","); |
| | | }, |
| | | cancel() { |
| | | this.$emit("cancel"); |
| | | }, |
| | | ok() { |
| | | this.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | let loading = this.$layer.loading(); |
| | | const formData = new FormData(); |
| | | if (this.file) { |
| | | this.file.forEach((v) => { |
| | | formData.append("multipartFileList", v); |
| | | }); |
| | | } |
| | | let { |
| | | provideName, |
| | | content, |
| | | type, |
| | | sumProduct, |
| | | productName, |
| | | badProduct, |
| | | startTime, |
| | | } = this.info; |
| | | formData.append( |
| | | "defectiveJson", |
| | | JSON.stringify({ |
| | | provideName, |
| | | productName, |
| | | content, |
| | | type, |
| | | sumProduct, |
| | | badProduct, |
| | | startTime, |
| | | receiverIds: this.receiverIds, |
| | | receiverNames: this.receiverNames, |
| | | }) |
| | | ); |
| | | |
| | | addDefective(formData).then((res) => { |
| | | // console.log("res", res, "============="); |
| | | res = res.data; |
| | | this.$layer.close(loading); |
| | | if (res.code && res.data) { |
| | | this.$message.success("操作成功"); |
| | | this.$emit("ok"); |
| | | } else { |
| | | this.$message.error("操作失败"); |
| | | } |
| | | }); |
| | | } else { |
| | | this.$message.error("存在未通过检验的表单项"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | disabledDate(current) { |
| | | // Can not select days before today and today |
| | | return current > moment().endOf("day"); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.searchAllUserList(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .modal-footer { |
| | | text-align: right; |
| | | button + button { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | .row { |
| | | color: rgba(0, 0, 0, 0.85); |
| | | line-height: 30px; |
| | | .label { |
| | | text-align: right; |
| | | } |
| | | .label::after { |
| | | content: ":"; |
| | | position: relative; |
| | | top: -0.5px; |
| | | margin: 0 8px 0 2px; |
| | | } |
| | | } |
| | | /deep/ .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | }, |
| | | component: () => import('@/pages/resourceManage/specification/history'), |
| | | }, |
| | | { |
| | | path: 'defective', |
| | | name: '不良品管理', |
| | | component: () => import('@/pages/resourceManage/defective'), |
| | | }, |
| | | ] |
| | | }, |
| | | { |