gaoluyang
2 天以前 2323c93baf009d2f60acaec545622611673203cb
1.巡检上传页面开发、联调
已修改4个文件
已添加5个文件
554 ■■■■■ 文件已修改
package.json 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inspectionManagement/index.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionManagement/components/formDia.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionManagement/components/qrCodeDia.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionManagement/index.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionUpload/components/formDia.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionUpload/index.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesOutbound/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -16,13 +16,14 @@
    "url": "https://gitee.com/y_project/RuoYi-Vue.git"
  },
  "dependencies": {
    "@chenfengyuan/vue-qrcode": "^2.0.0",
    "@element-plus/icons-vue": "2.3.1",
    "@vueup/vue-quill": "1.2.0",
    "@vueuse/core": "10.11.0",
    "axios": "0.28.1",
    "clipboard": "2.0.11",
    "echarts": "5.5.1",
    "default-passive-events": "^4.0.0",
    "echarts": "5.5.1",
    "element-china-area-data": "^6.1.0",
    "element-plus": "2.7.6",
    "file-saver": "2.0.5",
@@ -32,9 +33,12 @@
    "jsencrypt": "3.3.2",
    "nprogress": "0.2.0",
    "pinia": "2.1.7",
    "print-js": "^1.6.0",
    "qrcode": "^1.5.4",
    "splitpanes": "3.1.5",
    "vue": "3.4.31",
    "vue-cropper": "1.1.1",
    "vue-qrcode": "^2.2.2",
    "vue-router": "4.4.0",
    "vuedraggable": "4.1.0"
  },
src/api/inspectionManagement/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
// å·¡æ£€ç®¡ç†
import request from '@/utils/request'
// å·¡æ£€ä»»åŠ¡è¡¨è¡¨æŸ¥è¯¢
export function inspectionTaskList(query) {
    return request({
        url: '/inspectionTask/list',
        method: 'get',
        params: query
    })
}
// å·¡æ£€ä»»åŠ¡è¡¨æ–°å¢žä¿®æ”¹
export function addOrEditInspectionTask(query) {
    return request({
        url: '/inspectionTask/addOrEditInspectionTask',
        method: 'post',
        data: query
    })
}
// å·¡æ£€ä»»åŠ¡è¡¨æ–°å¢žä¿®æ”¹
export function delInspectionTask(query) {
    return request({
        url: '/inspectionTask/delInspectionTask',
        method: 'delete',
        data: query
    })
}
src/main.js
@@ -45,6 +45,7 @@
import DictTag from '@/components/DictTag'
import {summarizeTable} from "@/utils/summarizeTable.js";
import {getCurrentDate} from "@/utils/getCurrentDate.js";
import VueQrcode from '@chenfengyuan/vue-qrcode';
const app = createApp(App)
@@ -68,6 +69,7 @@
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
app.component('vue-qrcode', VueQrcode)
app.use(router)
app.use(store)
src/views/inspectionManagement/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
<template>
  <div>
    <el-dialog :title="operationType === 'add' ? '新增巡检任务' : '编辑销售出库'"
               v-model="dialogVisitable" width="800px" @close="cancel">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="任务名称" prop="taskName">
              <el-input v-model="form.taskName" placeholder="请输入任务名称" maxlength="30" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="地点" prop="port">
              <el-input v-model="form.port" placeholder="请输入地点" maxlength="30" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="巡检人" prop="inspector">
              <el-input v-model="form.inspector" placeholder="巡检人" maxlength="30" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="备注" prop="remarks">
              <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submitForm">保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {reactive, ref} from "vue";
import useUserStore from '@/store/modules/user'
import {addOrEditInspectionTask} from "@/api/inspectionManagement/index.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const userStore = useUserStore()
const dialogVisitable = ref(false);
const operationType = ref('add');
const data = reactive({
  form: {
    taskName: '',
    port: '',
    inspector: '',
    remarks: '',
  },
  rules: {
    taskName: [{ required: true, message: "请输入任务名称", trigger: "blur" },],
    port: [{ required: true, message: "请输入地点", trigger: "blur" },],
    inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" },],
  }
})
const { form, rules } = toRefs(data)
// æ‰“开弹框
const openDialog = async (type, row) => {
  dialogVisitable.value = true
  if (type === 'edit') {
    form.value = {...row}
  }
}
// æäº¤åˆå¹¶è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      addOrEditInspectionTask(form.value).then(() => {
        cancel()
        proxy.$modal.msgSuccess('提交成功')
      })
    }
  })
}
// å…³é—­åˆå¹¶è¡¨å•
const cancel = () => {
  proxy.resetForm("formRef")
  dialogVisitable.value = false
  emit('closeDia')
}
defineExpose({ openDialog })
</script>
<style scoped>
</style>
src/views/inspectionManagement/components/qrCodeDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
<template>
  <div>
    <el-dialog :title="operationType === 'add' ? '新增二维码' : '编辑二维码'"
               v-model="dialogVisitable" width="500px" @close="cancel">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="设备名称" prop="name">
              <el-input v-model="form.name" placeholder="请输入设备名称" maxlength="30" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="地点" prop="taxTrans">
              <el-input v-model="form.taxTrans" placeholder="请输入地点" maxlength="30"/>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div>
        <el-button type="primary" @click="submitForm">生成并打印二维码</el-button>
      </div>
      <div v-if="isShowQrCode" class="print-section" ref="qrCodeContainer" id="qrCodeContainer">
        <vue-qrcode :value="qrCodeValue" :width="qrCodeSize"></vue-qrcode>
      </div>
    </el-dialog>
  </div>
</template>
<script setup>
import useUserStore from "@/store/modules/user.js";
import {reactive, ref} from "vue";
import printJS from 'print-js'; // å¼•å…¥ print.js
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const userStore = useUserStore()
const dialogVisitable = ref(false);
const isShowQrCode = ref(false);
const operationType = ref('add');
const qrCodeValue = ref('https://example.com');
const qrCodeSize = ref(100);
const data = reactive({
  form: {
    name: '',
    taxTrans: '',
  },
  rules: {
    name: [{ required: true, message: '请输入设备名称', trigger: 'blur' }],
    taxTrans: [{ required: true, message: '请输入地点', trigger: 'blur' }]
  }
})
const { form, rules } = toRefs(data)
// æ‰“开弹框
const openDialog = async (type, row) => {
  dialogVisitable.value = true
}
// æäº¤åˆå¹¶è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      // å°†è¡¨å•数据转为 JSON å­—符串作为二维码内容
      qrCodeValue.value = JSON.stringify(form.value);
      isShowQrCode.value = true;
      // å»¶è¿Ÿæ‰§è¡Œæ‰“印,避免 DOM æ›´æ–°å‰å°±è°ƒç”¨æ‰“印
      setTimeout(() => {
        printJS({
          printable: 'qrCodeContainer',//页面
          type: "html",//文档类型
          maxWidth: 360,
          style: `@page {
                margin:0;
                size: 400px 75px collapse;
                margin-top:3px;
                &:first-of-type{
                  margin-top:0 !important;
                }
              }
              html{
                zoom:100%;
              }
              @media print{
                width: 400px;
                height: 75px;
                margin:0;
              }`,
          targetStyles: ["*"], // ä½¿ç”¨dom的所有样式,很重要
          font_size: '0.20cm',
        });
      }, 300);
    }
  })
}
// å…³é—­åˆå¹¶è¡¨å•
const cancel = () => {
  proxy.resetForm("formRef")
  dialogVisitable.value = false
  emit('closeDia')
}
defineExpose({ openDialog })
</script>
<style scoped>
.print-section {
  text-align: center;
  margin-top: 30px;
}
</style>
src/views/inspectionManagement/index.vue
@@ -63,15 +63,23 @@
        />
      </div>
    </el-card>
    <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
    <qr-code-dia ref="qrCodeDia" @closeDia="handleQuery"></qr-code-dia>
  </div>
</template>
<script setup>
import {Download, Delete, Plus} from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
const { proxy } = getCurrentInstance()
import Pagination from "@/components/Pagination/index.vue";
import ETable from "@/components/Table/ETable.vue";
import FormDia from "@/views/inspectionManagement/components/formDia.vue";
import QrCodeDia from "@/views/inspectionManagement/components/qrCodeDia.vue";
import {delInspectionTask, inspectionTaskList} from "@/api/inspectionManagement/index.js";
const formDia = ref()
const qrCodeDia = ref()
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  supplierName: "",
@@ -79,7 +87,7 @@
})
// å½“前标签
const activeTab = ref("task");
const tabName = ref("qrCode");
const tabName = ref("task");
// æ ‡ç­¾é¡µæ•°æ®
const tabs = reactive([
  { name: "task", label: "任务下发" },
@@ -93,22 +101,12 @@
const pageNum = ref(1);
const pageSize = ref(10);
const columns = ref([
  { prop: "saleDate", label: "销售日期", minWidth: 160 },
  { prop: "customer", label: "客户", minWidth: 120 },
  { prop: "coal", label: "煤种", minWidth: 150 },
  { prop: "unit", label: "单位", minWidth: 150 },
  { prop: "priceIncludingTax", label: "单价(含税)", minWidth: 150 },
  { prop: "inventoryQuantity", label: "库存数量", minWidth: 120 },
  { prop: "saleQuantity", label: "销售数量", minWidth: 120 },
  { prop: "salePrice", label: "销售单价(含税)", minWidth: 150 },
  { prop: "totalAmount", label: "销售总价(含税)", minWidth: 120 },
  { prop: "freight", label: "运费", minWidth: 90 },
  { prop: "taxCoal", label: "购销煤税率(%)", minWidth: 120 },
  { prop: "taxTrans", label: "运输税率(%)", minWidth: 120 },
  { prop: "grossProfit", label: "毛利润", minWidth: 90 },
  { prop: "netProfit", label: "净利润", minWidth: 90 },
  { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
  { prop: "port", label: "地点", minWidth: 120 },
  { prop: "remarks", label: "备注", minWidth: 150 },
  { prop: "inspector", label: "执行巡检人", minWidth: 150 },
  { prop: "registrant", label: "登记人", minWidth: 100 },
  { prop: "registrationDate", label: "登记日期", minWidth: 100 },
  { prop: "createTime", label: "登记日期", minWidth: 100 },
]);
onMounted(() => {
@@ -127,8 +125,13 @@
  getList()
}
const getList = () => {
  // tableLoading.value = true;
  tableLoading.value = true;
  inspectionTaskList({...queryParams, size: pageSize.value, current: pageNum.value}).then(res => {
    console.log(res)
    tableLoading.value = false;
    tableData.value = res.data.records;
    total.value = res.data.total;
  })
};
// é‡ç½®æŸ¥è¯¢
const resetQuery = () => {
@@ -142,7 +145,14 @@
// æ–°å¢žã€ç¼–辑
const handleAdd = (row) => {
  const type = row === undefined ? 'add' : 'edit'
  nextTick(() => {
    if (tabName.value === "task") {
      formDia.value?.openDialog(type, row)
    } else {
      qrCodeDia.value?.openDialog(type, row)
    }
  })
};
// åˆ é™¤ä»»åŠ¡
const handleDelete = () => {
@@ -152,7 +162,7 @@
  }
  const deleteIds = selectedRows.value.map(item => item.id);
  proxy.$modal.confirm('是否确认删除所选数据项?').then(function() {
    return delSalesRecord(deleteIds)
    return delInspectionTask(deleteIds)
  }).then(() => {
    handleQuery()
    proxy.$modal.msgSuccess("删除成功")
src/views/inspectionUpload/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
<template>
  <div>
    <el-dialog title="上传"
               v-model="dialogVisitable" width="400px" @close="cancel">
      <el-form :model="form" ref="formRef" label-width="120px">
        <el-form-item label="生产前" prop="fileList0">
          <el-upload
              v-model:file-list="fileList0"
              ref="fileUpload0"
              :action="uploadFileUrl"
              multiple
              name="files"
              :data="{type: 0}"
              style="width: 100%"
              :headers="headers"
              :before-upload="handleBeforeUpload"
              :on-success="handleUploadSuccess"
          >
            <el-button type="primary">上传</el-button>
          </el-upload>
        </el-form-item>
        <el-form-item label="生产后" prop="fileList1">
          <el-upload
              v-model:file-list="fileList1"
              ref="fileUpload1"
              :action="uploadFileUrl"
              multiple
              name="files"
              :data="{type: 1}"
              style="width: 100%"
              :headers="headers"
              :before-upload="handleBeforeUpload"
              :on-success="handleUploadSuccess1"
          >
            <el-button type="primary">上传</el-button>
          </el-upload>
        </el-form-item>
        <el-form-item label="生产问题" prop="fileList2">
          <el-upload
              v-model:file-list="fileList2"
              ref="fileUpload2"
              :action="uploadFileUrl"
              multiple
              name="files"
              :data="{type: 2}"
              style="width: 100%"
              :headers="headers"
              :before-upload="handleBeforeUpload"
              :on-success="handleUploadSuccess2"
          >
            <el-button type="primary">上传</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submitForm">保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {reactive, ref} from "vue";
import {addOrEditInspectionTask} from "@/api/inspectionManagement/index.js";
import {getToken} from "@/utils/auth.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const dialogVisitable = ref(false);
const data = reactive({
  form: {
    id: '',
    storageBlobDTO: {}
  },
})
const { form } = toRefs(data)
const fileList0 = ref([])
const fileList1 = ref([])
const fileList2 = ref([])
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/common/minioUploads'); // ä¸Šä¼ æ–‡ä»¶æœåŠ¡å™¨åœ°å€
const headers = ref({ Authorization: "Bearer " + getToken() });
// æ‰“开弹框
const openDialog = async (row) => {
  dialogVisitable.value = true
  form.value.id = row.id
}
// ä¸Šä¼ å‰æ ¡æ£€æ ¼å¼å’Œå¤§å°
function handleBeforeUpload(file) {
  return true
}
// ä¸Šä¼ æˆåŠŸå›žè°ƒ
function handleUploadSuccess(res, file) {
  if (res.code === 200) {
    console.log("上传成功", res);
    proxy.$modal.msgSuccess("文件上传成功");
    console.log('fileList0---', fileList0)
  } else {
    proxy.$modal.msgError(res.msg)
    proxy.$refs.fileUpload0.handleRemove(file)
  }
}
function handleUploadSuccess1(res, file) {
  if (res.code === 200) {
    proxy.$modal.msgSuccess("文件上传成功");
  } else {
    proxy.$modal.msgError(res.msg)
    proxy.$refs.fileUpload1.handleRemove(file)
  }
}
function handleUploadSuccess2(res, file) {
  if (res.code === 200) {
    proxy.$modal.msgSuccess("文件上传成功");
  } else {
    proxy.$modal.msgError(res.msg)
    proxy.$refs.fileUpload2.handleRemove(file)
  }
}
// æäº¤åˆå¹¶è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      // åˆå§‹åŒ– storageBlobDTO ä¸ºä¸€ä¸ªç©ºæ•°ç»„
      form.value.storageBlobDTO = []
      // åˆå¹¶æ‰€æœ‰ fileList åˆ° storageBlobDTO
      const allFiles = [
        ...fileList0.value,
        ...fileList1.value,
        ...fileList2.value
      ]
      // å°†æ–‡ä»¶åˆ—表赋值给 form
      form.value.storageBlobDTO = allFiles
      // æäº¤æ•°æ®
      addOrEditInspectionTask(form.value).then(() => {
        cancel()
        proxy.$modal.msgSuccess('提交成功')
      })
    }
  })
}
// å…³é—­åˆå¹¶è¡¨å•
const cancel = () => {
  proxy.resetForm("formRef")
  dialogVisitable.value = false
  emit('closeDia')
}
defineExpose({ openDialog })
</script>
<style scoped>
</style>
src/views/inspectionUpload/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
<template>
  <div class="app-container">
    <el-card>
      <!-- æ ‡ç­¾é¡µ -->
      <el-tabs
          v-model="activeTab"
          class="info-tabs"
          @tab-click="handleTabClick"
      >
        <el-tab-pane
            v-for="tab in tabs"
            :key="tab.name"
            :label="tab.label"
            :name="tab.name"
        />
      </el-tabs>
      <div>
        <div>
          <el-table ref="table" :data="tableData" height="480" v-loading="tableLoading">
            <el-table-column label="序号" type="index" width="60" align="center" />
            <el-table-column prop="taskName" label="巡检任务名称" :show-overflow-tooltip="true"></el-table-column>
            <el-table-column prop="port" label="地点" :show-overflow-tooltip="true"></el-table-column>
            <el-table-column prop="remarks" label="备注"></el-table-column>
            <el-table-column prop="inspector" label="执行巡检人"></el-table-column>
            <el-table-column fixed="right" label="操作">
              <template #default="scope">
                <el-button link type="primary" @click="handleAdd(scope.row)">上传</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <pagination
            v-if="total>0"
            :page-num="pageNum"
            :page-size="pageSize"
            :total="total"
            @pagination="handleQuery"
            :layout="'total, prev, pager, next, jumper'"
        />
      </div>
    </el-card>
    <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
  </div>
</template>
<script setup>
import Pagination from "@/components/Pagination/index.vue";
import {inspectionTaskList} from "@/api/inspectionManagement/index.js";
import {onMounted, ref} from "vue";
import FormDia from "@/views/inspectionUpload/components/formDia.vue";
const formDia = ref()
// å½“前标签
const activeTab = ref("task");
const tabName = ref("task");
// æ ‡ç­¾é¡µæ•°æ®
const tabs = reactive([
  { name: "task", label: "任务下发" },
  { name: "qrCode", label: "二维码管理" },
]);
// è¡¨æ ¼
const tableData = ref([]);
const tableLoading = ref(false);
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
onMounted(() => {
  handleTabClick({ props: { name: "task" } });
});
// æ ‡ç­¾é¡µç‚¹å‡»
const handleTabClick = (tab) => {
  tabName.value = tab.props.name;
  tableData.value = [];
  getList();
};
// ç‚¹å‡»æŸ¥è¯¢
const handleQuery = () => {
  pageNum.value = 1
  pageSize.value = 10
  getList()
}
const getList = () => {
  tableLoading.value = true;
  inspectionTaskList({size: pageSize.value, current: pageNum.value}).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records;
    total.value = res.data.total;
  })
};
// ä¸Šä¼ 
const handleAdd = (row) => {
  nextTick(() => {
    formDia.value?.openDialog(row)
  })
}
</script>
<style scoped>
</style>
src/views/salesOutbound/index.vue
@@ -79,7 +79,7 @@
import ETable from "@/components/Table/ETable.vue";
import Pagination from "@/components/Pagination/index.vue";
import FormDia from "@/views/salesOutbound/components/formDia.vue";
import {delSalesRecord, salesRecordList} from "../../api/salesOutbound/index.js";
import {delSalesRecord, salesRecordList} from "@/api/salesOutbound/index.js";
const formDia = ref()
const activeTab = ref("out");