feat:采收与赋码管理
This commit is contained in:
		
							parent
							
								
									c9829c6a5c
								
							
						
					
					
						commit
						182b97b336
					
				| @ -3,7 +3,7 @@ | ||||
|  * @Author: zenghua.wang | ||||
|  * @Date: 2022-02-23 21:12:37 | ||||
|  * @LastEditors: zenghua.wang | ||||
|  * @LastEditTime: 2025-02-07 14:38:05 | ||||
|  * @LastEditTime: 2025-02-10 14:47:12 | ||||
|  */ | ||||
| import lodash from 'lodash'; | ||||
| import dayjs from 'dayjs'; | ||||
| @ -291,42 +291,56 @@ export const obj2Param = (json) => { | ||||
|  * @returns | ||||
|  */ | ||||
| export const getAssetsFile = (url) => { | ||||
|   return new URL(`../assets/images/${url}`, import.meta.url); | ||||
| }; | ||||
| /** | ||||
|  * @Title: a链接方式文件下载 | ||||
|  * @param {void} content: | ||||
|  * @param {void} fileName: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const downloadLink = (url, fileName) => { | ||||
|   const elink = document.createElement('a'); | ||||
|   elink.download = fileName; | ||||
|   elink.style.display = 'none'; | ||||
|   elink.href = url; | ||||
|   elink.target = '_blank'; | ||||
|   elink.click(); | ||||
|   elink.remove(); | ||||
|   return new URL(`../assets/${url}`, import.meta.url); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 下载文件 | ||||
|  * @param {void} content: | ||||
|  * @param {void} url: | ||||
|  * @param {void} fileName: | ||||
|  * @param {void} fileType: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const downloadFile = (content, fileName) => { | ||||
|   const blob = new Blob([content]); | ||||
|   if ('download' in document.createElement('a')) { | ||||
|     const elink = document.createElement('a'); | ||||
|     elink.download = fileName; | ||||
|     elink.style.display = 'none'; | ||||
|     elink.href = URL.createObjectURL(blob); | ||||
|     document.body.appendChild(elink); | ||||
|     elink.click(); | ||||
|     URL.revokeObjectURL(elink.href); | ||||
|     document.body.removeChild(elink); | ||||
|   } else { | ||||
|     navigator.msSaveBlob(blob, fileName); | ||||
| export const downloadFile = async (url, fileName, fileType) => { | ||||
|   let blob = null; | ||||
|   try { | ||||
|     switch (fileType) { | ||||
|       case 'image': { | ||||
|         const img = new Image(); | ||||
|         img.crossOrigin = 'Anonymous'; | ||||
|         img.src = url; | ||||
|         await new Promise((resolve, reject) => { | ||||
|           img.onload = resolve; | ||||
|           img.onerror = reject; | ||||
|         }); | ||||
|         const canvas = document.createElement('canvas'); | ||||
|         canvas.width = img.width; | ||||
|         canvas.height = img.height; | ||||
|         const ctx = canvas.getContext('2d'); | ||||
|         ctx.drawImage(img, 0, 0); | ||||
|         blob = await new Promise((resolve) => { | ||||
|           canvas.toBlob(resolve, 'image/jpeg'); | ||||
|         }); | ||||
|         break; | ||||
|       } | ||||
|       case 'blob': { | ||||
|         blob = new Blob([url]); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if ('download' in document.createElement('a')) { | ||||
|       const elink = document.createElement('a'); | ||||
|       elink.download = fileName; | ||||
|       elink.style.display = 'none'; | ||||
|       elink.href = blob ? URL.createObjectURL(blob) : url; | ||||
|       document.body.appendChild(elink); | ||||
|       elink.click(); | ||||
|       blob && URL.revokeObjectURL(elink.href); | ||||
|       document.body.removeChild(elink); | ||||
|     } else { | ||||
|       navigator.msSaveBlob(blob, fileName); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('下载出错:', error); | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  | ||||
| @ -6,15 +6,14 @@ import vueSetupExtend from 'vite-plugin-vue-setup-extend'; | ||||
| import compression from 'vite-plugin-compression'; | ||||
| import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; | ||||
| import { createHtmlPlugin } from 'vite-plugin-html'; | ||||
| // import { viteMockServe } from 'vite-plugin-mock';
 | ||||
| import AutoImport from 'unplugin-auto-import/vite'; | ||||
| import Components from 'unplugin-vue-components/vite'; | ||||
| import postcssImport from 'postcss-import'; | ||||
| import autoprefixer from 'autoprefixer'; | ||||
| // import postCssPxToRem from 'postcss-pxtorem';
 | ||||
| import { resolve } from 'path'; | ||||
| 
 | ||||
| export default defineConfig(({ command, mode }) => { | ||||
|   console.log('vite.config.js', command, mode, loadEnv(mode, process.cwd())); | ||||
|   const { | ||||
|     VITE_PORT, | ||||
|     VITE_APP_NAME, | ||||
| @ -77,12 +76,6 @@ export default defineConfig(({ command, mode }) => { | ||||
|           autoprefixer({ | ||||
|             overrideBrowserslist: ['> 1%', 'last 2 versions'], | ||||
|           }), | ||||
|           // postCssPxToRem({
 | ||||
|           //   rootValue: 192,
 | ||||
|           //   selectorBlackList: [],
 | ||||
|           //   propList: ['*'],
 | ||||
|           //   exclude: /node_modules/i,
 | ||||
|           // }),
 | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
| @ -101,7 +94,7 @@ export default defineConfig(({ command, mode }) => { | ||||
|         include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.ts', 'src/*.vue'], | ||||
|       }), | ||||
|       Components({ | ||||
|         dirs: ['../global/components', 'src/components'], | ||||
|         dirs: ['src/components'], | ||||
|         extensions: ['vue', 'js', 'jsx', 'ts', 'tsx'], | ||||
|         resolvers: [], | ||||
|       }), | ||||
| @ -114,12 +107,6 @@ export default defineConfig(({ command, mode }) => { | ||||
|         iconDirs: [resolve(process.cwd(), 'src/assets/svgs')], | ||||
|         symbolId: 'icon-[name]', | ||||
|       }), | ||||
|       // viteMockServe({
 | ||||
|       //   mockPath: 'src/mock',
 | ||||
|       //   watchFiles: true,
 | ||||
|       //   localEnabled: command === 'dev',
 | ||||
|       //   prodEnabled: false,
 | ||||
|       // }),
 | ||||
|     ], | ||||
|   }; | ||||
|   if (mode === 'production') { | ||||
|  | ||||
| @ -3,10 +3,10 @@ | ||||
|  * @Author: zenghua.wang | ||||
|  * @Date: 2022-02-23 21:12:37 | ||||
|  * @LastEditors: zenghua.wang | ||||
|  * @LastEditTime: 2025-01-25 17:05:12 | ||||
|  * @LastEditTime: 2025-02-10 14:45:53 | ||||
|  */ | ||||
| import lodash from 'lodash'; | ||||
| import moment from 'moment'; | ||||
| import dayjs from 'dayjs'; | ||||
| import { Base64 } from 'js-base64'; | ||||
| 
 | ||||
| /** | ||||
| @ -90,7 +90,7 @@ export const setDefaultOption = (options, prop, defaultVal) => { | ||||
|   return options[prop] === undefined ? defaultVal : options.prop; | ||||
| }; | ||||
| /** | ||||
|  * 设置字典值 | ||||
|  * @Title 设置字典值 | ||||
|  * @param {*} columns | ||||
|  * @param {*} key | ||||
|  * @param {*} data | ||||
| @ -107,7 +107,7 @@ export const setDicData = (columns, key, data = []) => { | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  * 求字段lable | ||||
|  * @Title 求字段lable | ||||
|  * @param {*} tree | ||||
|  * @returns | ||||
|  */ | ||||
| @ -124,7 +124,35 @@ export const setDicLabel = (dicData, value) => { | ||||
|   return label; | ||||
| }; | ||||
| /** | ||||
|  * 加密 | ||||
|  * @Title 数组交集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const intersectionArray = (arr1 = [], arr2 = []) => { | ||||
|   return arr1.filter((item) => arr2.includes(item)); | ||||
| }; | ||||
| /** | ||||
|  * @Title 数组并集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const unionArray = (arr1 = [], arr2 = []) => { | ||||
|   return Array.from(new Set([...arr1, ...arr2])); | ||||
| }; | ||||
| /** | ||||
|  * @Title 数组差集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const differenceArray = (arr1 = [], arr2 = []) => { | ||||
|   const s = new Set(arr2); | ||||
|   return arr1.filter((x) => !s.has(x)); | ||||
| }; | ||||
| /** | ||||
|  * @Title 加密 | ||||
|  * @param {*} n | ||||
|  * @returns | ||||
|  */ | ||||
| @ -146,7 +174,7 @@ export const encode = (n, flag = false) => { | ||||
|   return n; | ||||
| }; | ||||
| /** | ||||
|  * 解密 | ||||
|  * @Title 解密 | ||||
|  * @param {*} e | ||||
|  * @returns | ||||
|  */ | ||||
| @ -190,6 +218,22 @@ export const imageToBase64 = (file) => { | ||||
| export const bufferToBase64 = (buffer) => { | ||||
|   return 'data:image/jpeg;base64,' + window.btoa(new Uint8Array(buffer).reduce((data, byte) => data + String.fromCharCode(byte), '')); | ||||
| }; | ||||
| /** | ||||
|  * @Title blob转json | ||||
|  * @param {*} file | ||||
|  * @returns | ||||
|  */ | ||||
| export const blobToJSON = (blob) => { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     const reader = new FileReader(); | ||||
|     reader.readAsText(blob, 'utf-8'); | ||||
|     reader.onload = () => { | ||||
|       const res = !isEmpty(reader.result) ? JSON.parse(reader.result) : reader.result; | ||||
|       resolve(res); | ||||
|     }; | ||||
|     reader.onerror = reject; | ||||
|   }); | ||||
| }; | ||||
| /** | ||||
|  * @Title 将array转化为树 | ||||
|  * @param tree | ||||
| @ -227,42 +271,76 @@ export const getUrlQuery = (name) => { | ||||
|   const usp = new URLSearchParams(search); | ||||
|   return usp.get(name); | ||||
| }; | ||||
| /** | ||||
|  * @Title 将Object参数转换为字符串 | ||||
|  * @param {*} json | ||||
|  * @returns | ||||
|  */ | ||||
| export const obj2Param = (json) => { | ||||
|   if (!json) return ''; | ||||
|   return Object.keys(json) | ||||
|     .map((key) => { | ||||
|       if (isEmpty(json[key])) return ''; | ||||
|       return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]); | ||||
|     }) | ||||
|     .join('&'); | ||||
| }; | ||||
| /** | ||||
|  * @Title 获取静态资源文件 | ||||
|  * @param {*} url | ||||
|  * @returns | ||||
|  */ | ||||
| export const getAssetsFile = (url) => { | ||||
|   return new URL(`../assets/images/${url}`, import.meta.url); | ||||
|   return new URL(`../assets/${url}`, import.meta.url); | ||||
| }; | ||||
| /** | ||||
|  * @Title 替换图片url字段值 | ||||
|  * @param {*} url | ||||
|  * @returns | ||||
|  */ | ||||
| export const setUploadField = (url) => { | ||||
|   if (isEmpty(url) || url.includes('http')) return null; | ||||
|   return url; | ||||
| }; | ||||
| /** | ||||
|  * @Title: a链接方式文件下载 | ||||
|  * @param {void} content: | ||||
|  * @Title: 下载文件 | ||||
|  * @param {void} url: | ||||
|  * @param {void} fileName: | ||||
|  * @param {void} fileType: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const dowloadLink = (content, fileName) => { | ||||
|   const blob = new Blob([content]); | ||||
|   if ('download' in document.createElement('a')) { | ||||
|     const elink = document.createElement('a'); | ||||
|     elink.download = fileName; | ||||
|     elink.style.display = 'none'; | ||||
|     elink.href = URL.createObjectURL(blob); | ||||
|     document.body.appendChild(elink); | ||||
|     elink.click(); | ||||
|     URL.revokeObjectURL(elink.href); | ||||
|     document.body.removeChild(elink); | ||||
|   } else { | ||||
|     navigator.msSaveBlob(blob, fileName); | ||||
| export const downloadFile = async (url, fileName, fileType) => { | ||||
|   let blob = null; | ||||
|   try { | ||||
|     switch (fileType) { | ||||
|       case 'image': { | ||||
|         const img = new Image(); | ||||
|         img.crossOrigin = 'Anonymous'; | ||||
|         img.src = url; | ||||
|         await new Promise((resolve, reject) => { | ||||
|           img.onload = resolve; | ||||
|           img.onerror = reject; | ||||
|         }); | ||||
|         const canvas = document.createElement('canvas'); | ||||
|         canvas.width = img.width; | ||||
|         canvas.height = img.height; | ||||
|         const ctx = canvas.getContext('2d'); | ||||
|         ctx.drawImage(img, 0, 0); | ||||
|         blob = await new Promise((resolve) => { | ||||
|           canvas.toBlob(resolve, 'image/jpeg'); | ||||
|         }); | ||||
|         break; | ||||
|       } | ||||
|       case 'blob': { | ||||
|         blob = new Blob([url]); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if ('download' in document.createElement('a')) { | ||||
|       const elink = document.createElement('a'); | ||||
|       elink.download = fileName; | ||||
|       elink.style.display = 'none'; | ||||
|       elink.href = blob ? URL.createObjectURL(blob) : url; | ||||
|       document.body.appendChild(elink); | ||||
|       elink.click(); | ||||
|       blob && URL.revokeObjectURL(elink.href); | ||||
|       document.body.removeChild(elink); | ||||
|     } else { | ||||
|       navigator.msSaveBlob(blob, fileName); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('下载出错:', error); | ||||
|   } | ||||
| }; | ||||
| /** | ||||
| @ -275,20 +353,106 @@ export const sleep = (duration = 0) => | ||||
|     setTimeout(resolve, duration); | ||||
|   }); | ||||
| /** | ||||
|  * 日期格式化 | ||||
|  * @Title 创建id | ||||
|  * @param {*} prefix | ||||
|  * @returns | ||||
|  */ | ||||
| export const createId = (prefix) => { | ||||
|   const val = Date.now() + Math.ceil(Math.random() * 99999); | ||||
|   return isEmpty(prefix) ? val : prefix + '-' + val; | ||||
| }; | ||||
| /** | ||||
|  * @Title 生成数据 | ||||
|  * @param {*} duration | ||||
|  * @returns | ||||
|  */ | ||||
| export const mockData = (item = {}, len = 1) => { | ||||
|   const list = []; | ||||
|   for (let i = 0; i < len; i++) { | ||||
|     let temp = { ...item, id: createId() }; | ||||
|     list.push(temp); | ||||
|   } | ||||
|   return list; | ||||
| }; | ||||
| /** | ||||
|  * @Title 日期格式化 | ||||
|  * @param {*} date | ||||
|  * @param {*} format | ||||
|  * @returns | ||||
|  */ | ||||
| export const dateFormat = (datetime, type = 'yyyy-MM-dd') => { | ||||
|   return moment(datetime).format(type); | ||||
| export const dateFormat = (datetime, formater = 'YYYY-MM-DD hh:mm:ss') => { | ||||
|   if (datetime instanceof Date || datetime) { | ||||
|     return dayjs(datetime).format(formater); | ||||
|   } else { | ||||
|     return null; | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  * 上日/周/月/年 | ||||
|  * @Title 字符串转日期 | ||||
|  * @param {*} str | ||||
|  * @returns | ||||
|  */ | ||||
| export const lastDate = (last = 0, date = 'month', type = 'yyyy-MM-dd') => { | ||||
|   if (date === 'day') { | ||||
|     return moment().subtract(last, 'day').endOf('day').format(type); | ||||
|   } | ||||
|   return moment().subtract(last, date).format(type); | ||||
| export const toDate = (str) => { | ||||
|   return !isEmpty(str) ? dayjs(str) : dayjs(); | ||||
| }; | ||||
| /** | ||||
|  * @Title 字符串转日期 | ||||
|  * @param {*} str | ||||
|  * @returns | ||||
|  */ | ||||
| export const getDate = (num, type, formater = 'YYYY-MM-DD', start = true) => { | ||||
|   const date = dayjs().subtract(num, type); | ||||
|   return start ? date.startOf(type).format(formater) : date.endOf(type).format(formater); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 获取时间差 | ||||
|  * @param start | ||||
|  * @param end | ||||
|  * @param type | ||||
|  * @returns | ||||
|  */ | ||||
| export const getDiffTime = (start, end, type) => { | ||||
|   const startTime = dayjs(start); | ||||
|   const endTime = dayjs(end); | ||||
|   const duration = endTime.diff(startTime); | ||||
|   let diff = 0; | ||||
|   switch (type) { | ||||
|     case 'DD': { | ||||
|       diff = duration / (1000 * 60 * 60 * 24); | ||||
|       break; | ||||
|     } | ||||
|     case 'HH': { | ||||
|       diff = duration / (1000 * 60 * 60); | ||||
|       break; | ||||
|     } | ||||
|     case 'mm': { | ||||
|       diff = duration / (1000 * 60); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   return Math.round(diff); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 开始日期 | ||||
|  * @param last | ||||
|  * @param type | ||||
|  * @param formater | ||||
|  * @returns | ||||
|  */ | ||||
| export const startDate = (num, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => { | ||||
|   if (num === 'now') return dayjs().format(formater); | ||||
|   if (typeof num === 'string') return dayjs(num).startOf(type).format(formater); | ||||
|   return num === 0 ? dayjs().startOf(type).format(formater) : dayjs().subtract(num, type).startOf(type).format(formater); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 结束日期 | ||||
|  * @param num | ||||
|  * @param type | ||||
|  * @param formater | ||||
|  * @returns | ||||
|  */ | ||||
| export const endDate = (num = 0, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => { | ||||
|   if (num === 'now') return dayjs().format(formater); | ||||
|   if (typeof num === 'string') return dayjs(num).endOf(type).format(formater); | ||||
|   return num === 0 ? dayjs().endOf(type).format(formater) : dayjs().subtract(num, type).endOf(type).format(formater); | ||||
| }; | ||||
|  | ||||
| @ -2,10 +2,10 @@ | ||||
| VITE_PORT = 9528 | ||||
| VITE_MODE = 'DEV' | ||||
| VITE_APP_NAME = 'sub-government-affairs-service' | ||||
| VITE_APP_BASE_API = '/traceApis'  | ||||
| VITE_APP_BASE_API = '/apis'  | ||||
| VITE_APP_BASE_URL = 'http://192.168.18.99:8080' | ||||
| VITE_APP_UPLOAD_API = '/uploadApis' | ||||
| VITE_APP_UPLOAD_URL = 'http://192.168.18.99:9300' | ||||
| VITE_APP_DICDATA_API = '/dicDataApis' | ||||
| VITE_APP_DICDATA_URL = 'http://192.168.18.99:99/stage-api' | ||||
| VITE_APP_SYSTEM_API = '/systemApis' | ||||
| VITE_APP_SYSTEM_URL = 'http://192.168.18.99:99/stage-api' | ||||
| 
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ import request from '@/utils/axios'; | ||||
| /** | ||||
|  * @Title: 列表 | ||||
|  */ | ||||
| export function GetEntityList(params) { | ||||
| export function GetEntityList(params = {}) { | ||||
|   return request('/trace/code/farmMange/page', { | ||||
|     method: 'GET', | ||||
|     params, | ||||
| @ -13,7 +13,7 @@ export function GetEntityList(params) { | ||||
| /** | ||||
|  * @Title: 新增 | ||||
|  */ | ||||
| export function AddEntity(data) { | ||||
| export function AddEntity(data = {}) { | ||||
|   return request('/trace/code/farmMange/save', { | ||||
|     method: 'POST', | ||||
|     data, | ||||
| @ -23,7 +23,7 @@ export function AddEntity(data) { | ||||
| /** | ||||
|  * @Title: 修改 | ||||
|  */ | ||||
| export function UpdateEntity(data) { | ||||
| export function UpdateEntity(data = {}) { | ||||
|   return request('/trace/code/farmMange/edit', { | ||||
|     method: 'PUT', | ||||
|     data, | ||||
| @ -33,7 +33,7 @@ export function UpdateEntity(data) { | ||||
| /** | ||||
|  * @Title: 删除 | ||||
|  */ | ||||
| export function DeleteEntity(params) { | ||||
| export function DeleteEntity(params = {}) { | ||||
|   return request('/trace/code/farmMange/delete', { | ||||
|     method: 'DELETE', | ||||
|     params, | ||||
| @ -43,7 +43,7 @@ export function DeleteEntity(params) { | ||||
| /** | ||||
|  * @Title: 导入 | ||||
|  */ | ||||
| export function ImportEntity(data) { | ||||
| export function ImportEntity(data = {}) { | ||||
|   return request('/trace/code/farmMange/import', { | ||||
|     method: 'POST', | ||||
|     headers: { 'Content-Type': 'multipart/form-data' }, | ||||
| @ -54,7 +54,7 @@ export function ImportEntity(data) { | ||||
| /** | ||||
|  * @Title: 导出 | ||||
|  */ | ||||
| export function ExportEntity(params) { | ||||
| export function ExportEntity(params = {}) { | ||||
|   return request('/trace/code/farmMange/export', { | ||||
|     method: 'GET', | ||||
|     params, | ||||
| @ -63,11 +63,10 @@ export function ExportEntity(params) { | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @Title: 地址列表 | ||||
|  * @Title: 详情 | ||||
|  */ | ||||
| export function GetAreaList(params) { | ||||
|   return request('/trace/code/farmMange/areas', { | ||||
| export function GetEntity(params = {}) { | ||||
|   return request(`/trace/code/farmMange/qualityCheck/${params?.id}`, { | ||||
|     method: 'GET', | ||||
|     params, | ||||
|   }); | ||||
| } | ||||
|  | ||||
							
								
								
									
										41
									
								
								sub-government-affairs-service/src/apis/quality.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								sub-government-affairs-service/src/apis/quality.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| import request from '@/utils/axios'; | ||||
| 
 | ||||
| /** | ||||
|  * @Title: 列表 | ||||
|  */ | ||||
| export function GetEntityList(params) { | ||||
|   return request('/trace/code/qualityManage/page', { | ||||
|     method: 'GET', | ||||
|     params, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @Title: 新增 | ||||
|  */ | ||||
| export function AddEntity(data) { | ||||
|   return request('/trace/code/qualityManage/save', { | ||||
|     method: 'POST', | ||||
|     data, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @Title: 修改 | ||||
|  */ | ||||
| export function UpdateEntity(data) { | ||||
|   return request('/trace/code/qualityManage/edit', { | ||||
|     method: 'PUT', | ||||
|     data, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @Title: 删除 | ||||
|  */ | ||||
| export function DeleteEntity(params) { | ||||
|   return request('/trace/code/qualityManage/delete', { | ||||
|     method: 'DELETE', | ||||
|     params, | ||||
|   }); | ||||
| } | ||||
| @ -17,6 +17,7 @@ export const CRUD_OPTIONS = { | ||||
|   align: 'center', | ||||
|   headerAlign: 'center', | ||||
|   gridBtn: false, | ||||
|   columnBtn: false, | ||||
|   addBtn: true, | ||||
|   viewBtn: false, | ||||
|   editBtn: false, | ||||
| @ -26,4 +27,5 @@ export const CRUD_OPTIONS = { | ||||
|   column: [], | ||||
|   menuWidth: 100, | ||||
|   actions: [], | ||||
|   dialogDrag: true, | ||||
| }; | ||||
|  | ||||
| @ -3,9 +3,10 @@ import { constantRoutes, notFoundRouter } from '@/router'; | ||||
| import { createAsyncRoutes, filterAsyncRoutes, filterKeepAlive } from '@/utils/router'; | ||||
| import { useUserStore } from '@/store/modules/user'; | ||||
| import { getTree } from '@/utils'; | ||||
| import { GenKey } from '@/config'; | ||||
| 
 | ||||
| export const usePermissionStore = defineStore({ | ||||
|   id: 'permissionStore', | ||||
|   id: GenKey('permissionStore'), | ||||
|   state: () => ({ | ||||
|     // 路由
 | ||||
|     routes: [], | ||||
|  | ||||
| @ -1,8 +1,9 @@ | ||||
| import { defineStore } from 'pinia'; | ||||
| import { GenKey } from '@/config'; | ||||
| import router from '@/router'; | ||||
| 
 | ||||
| export const useTagsViewStore = defineStore({ | ||||
|   id: 'tagsViewStore', | ||||
|   id: GenKey('tagsViewStore'), | ||||
|   state: () => ({ | ||||
|     activeTabsValue: '/home', | ||||
|     visitedViews: [], | ||||
|  | ||||
| @ -3,10 +3,10 @@ import { GenKey } from '@/config'; | ||||
| import { isEmpty, encode, decode } from '@/utils'; | ||||
| 
 | ||||
| export const useUserStore = defineStore({ | ||||
|   id: GenKey('USER_STATE'), | ||||
|   id: GenKey('userStore'), | ||||
|   state: () => ({ | ||||
|     token: | ||||
|       'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX2tleSI6IjA0ZjNmZTE5LTc5ZWYtNGMxNy1iNWQ4LTE5YjA0MTkyNTZiMyIsInVzZXJuYW1lIjoiYWRtaW4ifQ.nGVLjwzO7K6MO9DbKKhfmwsoinDig5tsGWGEb3jcOtUQHcyJhTTvvuq3zAxNHSFRm9Nly_MSEcRV6oVcz3gT_w', | ||||
|       'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX2tleSI6IjU0ZGVjMzk4LTRhZmQtNDUyOS1hYjFkLTExZGZlZjU5NjJhOSIsInVzZXJuYW1lIjoiYWRtaW4ifQ._bHoqldw4oL_MqZxrHv81ShD3Z0GJYSdWietR1mHAfKluNi3SSs1PRZNrq1v-WTQyXgz1QgsBimPB48iqP7o6Q', | ||||
|     userInfo: {}, | ||||
|     currentOrg: null, | ||||
|     orgList: [], | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|  * @Author: zenghua.wang | ||||
|  * @Date: 2022-02-23 21:12:37 | ||||
|  * @LastEditors: zenghua.wang | ||||
|  * @LastEditTime: 2025-02-07 15:21:48 | ||||
|  * @LastEditTime: 2025-02-10 14:42:53 | ||||
|  */ | ||||
| import lodash from 'lodash'; | ||||
| import dayjs from 'dayjs'; | ||||
| @ -293,40 +293,54 @@ export const obj2Param = (json) => { | ||||
| export const getAssetsFile = (url) => { | ||||
|   return new URL(`../assets/${url}`, import.meta.url); | ||||
| }; | ||||
| /** | ||||
|  * @Title: a链接方式文件下载 | ||||
|  * @param {void} content: | ||||
|  * @param {void} fileName: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const downloadLink = (url, fileName) => { | ||||
|   const elink = document.createElement('a'); | ||||
|   elink.download = fileName; | ||||
|   elink.style.display = 'none'; | ||||
|   elink.href = url; | ||||
|   elink.target = '_blank'; | ||||
|   elink.click(); | ||||
|   elink.remove(); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 下载文件 | ||||
|  * @param {void} content: | ||||
|  * @param {void} url: | ||||
|  * @param {void} fileName: | ||||
|  * @param {void} fileType: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const downloadFile = (content, fileName) => { | ||||
|   const blob = new Blob([content]); | ||||
|   if ('download' in document.createElement('a')) { | ||||
|     const elink = document.createElement('a'); | ||||
|     elink.download = fileName; | ||||
|     elink.style.display = 'none'; | ||||
|     elink.href = URL.createObjectURL(blob); | ||||
|     document.body.appendChild(elink); | ||||
|     elink.click(); | ||||
|     URL.revokeObjectURL(elink.href); | ||||
|     document.body.removeChild(elink); | ||||
|   } else { | ||||
|     navigator.msSaveBlob(blob, fileName); | ||||
| export const downloadFile = async (url, fileName, fileType) => { | ||||
|   let blob = null; | ||||
|   try { | ||||
|     switch (fileType) { | ||||
|       case 'image': { | ||||
|         const img = new Image(); | ||||
|         img.crossOrigin = 'Anonymous'; | ||||
|         img.src = url; | ||||
|         await new Promise((resolve, reject) => { | ||||
|           img.onload = resolve; | ||||
|           img.onerror = reject; | ||||
|         }); | ||||
|         const canvas = document.createElement('canvas'); | ||||
|         canvas.width = img.width; | ||||
|         canvas.height = img.height; | ||||
|         const ctx = canvas.getContext('2d'); | ||||
|         ctx.drawImage(img, 0, 0); | ||||
|         blob = await new Promise((resolve) => { | ||||
|           canvas.toBlob(resolve, 'image/jpeg'); | ||||
|         }); | ||||
|         break; | ||||
|       } | ||||
|       case 'blob': { | ||||
|         blob = new Blob([url]); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if ('download' in document.createElement('a')) { | ||||
|       const elink = document.createElement('a'); | ||||
|       elink.download = fileName; | ||||
|       elink.style.display = 'none'; | ||||
|       elink.href = blob ? URL.createObjectURL(blob) : url; | ||||
|       document.body.appendChild(elink); | ||||
|       elink.click(); | ||||
|       blob && URL.revokeObjectURL(elink.href); | ||||
|       document.body.removeChild(elink); | ||||
|     } else { | ||||
|       navigator.msSaveBlob(blob, fileName); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('下载出错:', error); | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  | ||||
| @ -8,12 +8,12 @@ | ||||
|       :table-loading="state.loading" | ||||
|       :data="state.data" | ||||
|       :option="state.options" | ||||
|       @size-change="sizeChange" | ||||
|       @current-change="currentChange" | ||||
|       @refresh-change="refreshChange" | ||||
|       @search-reset="searchChange" | ||||
|       @search-change="searchChange" | ||||
|       @selection-change="selectionChange" | ||||
|       @current-change="currentChange" | ||||
|       @size-change="sizeChange" | ||||
|       @row-save="rowSave" | ||||
|       @row-update="rowUpdate" | ||||
|       @row-del="rowDel" | ||||
| @ -24,13 +24,6 @@ | ||||
|         <el-button type="success" icon="download" @click="onExport">导出</el-button> | ||||
|       </template> | ||||
| 
 | ||||
|       <template #qualityReportUrl="{ row }"> | ||||
|         <el-button v-if="row.qualityReportUrl" type="primary" text @click="downloadLink(row.qualityReportUrl, `${row.productName}-质检报告.pdf`)"> | ||||
|           下载 | ||||
|         </el-button> | ||||
|         <span v-else>暂无</span> | ||||
|       </template> | ||||
| 
 | ||||
|       <template #productUrl-form="{ column }"> | ||||
|         <el-upload class="custom-form__uploader" action="#" :show-file-list="false" accept="image/*" :limit="1" :http-request="rowUploadPicture"> | ||||
|           <img v-if="state.form.base64" :src="state.form.base64" class="custom-form__uploader__img" /> | ||||
| @ -38,6 +31,10 @@ | ||||
|         </el-upload> | ||||
|       </template> | ||||
| 
 | ||||
|       <template #customInfo-form="{ column }"> | ||||
|         <custom-info :row="state.currentRow" /> | ||||
|       </template> | ||||
| 
 | ||||
|       <template #menu="scope"> | ||||
|         <custom-table-operate :actions="state.options.actions" :data="scope" /> | ||||
|       </template> | ||||
| @ -49,22 +46,28 @@ | ||||
|       @on-download="onDownloadExcel" | ||||
|       @on-confirm="onUploadExcel" | ||||
|     /> | ||||
| 
 | ||||
|     <custom-quality-add ref="qualityAddRef" :row="state.currentRow" /> | ||||
|   </div> | ||||
| </template> | ||||
| <script setup> | ||||
| import { reactive, ref } from 'vue'; | ||||
| import { useApp } from '@/hooks'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { isEmpty, imageToBase64, getAssetsFile, downloadLink, downloadFile } from '@/utils'; | ||||
| import { isEmpty, imageToBase64, getAssetsFile, downloadFile } from '@/utils'; | ||||
| import { useUserStore } from '@/store/modules/user'; | ||||
| import { CommonUpload } from '@/apis'; | ||||
| import { GetEntityList, GetAreaList, AddEntity, UpdateEntity, DeleteEntity, ImportEntity, ExportEntity } from '@/apis/coding'; | ||||
| import { compact } from 'lodash'; | ||||
| import { GetEntityList, AddEntity, UpdateEntity, DeleteEntity, ImportEntity, ExportEntity } from '@/apis/coding'; | ||||
| import CustomInfo from './info.vue'; | ||||
| import CustomQualityAdd from '../quality/form.vue'; | ||||
| 
 | ||||
| const { VITE_APP_DICDATA_API, VITE_APP_BASE_API } = import.meta.env; | ||||
| const { VITE_APP_SYSTEM_API } = import.meta.env; | ||||
| const app = useApp(); | ||||
| const UserStore = useUserStore(); | ||||
| const crudRef = ref(null); | ||||
| const importExcelRef = ref(null); | ||||
| const qualityAddRef = ref(null); | ||||
| const state = reactive({ | ||||
|   loading: false, | ||||
|   query: { | ||||
| @ -89,11 +92,6 @@ const state = reactive({ | ||||
|         prop: 'harvestBatch', | ||||
|         width: 200, | ||||
|         display: false, | ||||
|         // rules: { | ||||
|         //   required: true, | ||||
|         //   message: '请输入', | ||||
|         //   trigger: 'blur', | ||||
|         // }, | ||||
|       }, | ||||
|       { | ||||
|         label: '产品名称', | ||||
| @ -115,7 +113,7 @@ const state = reactive({ | ||||
|           label: 'dictLabel', | ||||
|           value: 'dictValue', | ||||
|         }, | ||||
|         dicUrl: `${VITE_APP_DICDATA_API}/system/dict/data/list?pageNum=1&pageSize=20&dictType=sys_product_type`, | ||||
|         dicUrl: `${VITE_APP_SYSTEM_API}/system/dict/data/list?pageNum=1&pageSize=20&dictType=sys_product_type`, | ||||
|         dicHeaders: { | ||||
|           authorization: UserStore.token, | ||||
|         }, | ||||
| @ -144,7 +142,7 @@ const state = reactive({ | ||||
|           label: 'dictLabel', | ||||
|           value: 'dictValue', | ||||
|         }, | ||||
|         dicUrl: `${VITE_APP_DICDATA_API}/system/dict/data/list?pageNum=1&pageSize=20&dictType=sys_unit_type`, | ||||
|         dicUrl: `${VITE_APP_SYSTEM_API}/system/dict/data/list?pageNum=1&pageSize=20&dictType=sys_unit_type`, | ||||
|         dicHeaders: { | ||||
|           authorization: UserStore.token, | ||||
|         }, | ||||
| @ -168,17 +166,17 @@ const state = reactive({ | ||||
|           return row.qualityGuaranteePeriod + '天'; | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|         label: '质检结果', | ||||
|         prop: 'qualityResult', | ||||
|         display: false, | ||||
|       }, | ||||
|       { | ||||
|         label: '质检报告', | ||||
|         prop: 'qualityReportUrl', | ||||
|         display: false, | ||||
|         slot: true, | ||||
|       }, | ||||
|       // { | ||||
|       //   label: '质检结果', | ||||
|       //   prop: 'qualityResult', | ||||
|       //   display: false, | ||||
|       // }, | ||||
|       // { | ||||
|       //   label: '质检报告', | ||||
|       //   prop: 'qualityReportUrl', | ||||
|       //   display: false, | ||||
|       //   slot: true, | ||||
|       // }, | ||||
|       { | ||||
|         label: '采收日期', | ||||
|         prop: 'datetime', | ||||
| @ -235,27 +233,27 @@ const state = reactive({ | ||||
|       { | ||||
|         label: '原产地', | ||||
|         prop: 'originAddress', | ||||
|         type: 'cascader', | ||||
|         search: true, | ||||
|         display: false, | ||||
|         overHidden: true, | ||||
|         width: 200, | ||||
|       }, | ||||
|       { | ||||
|         label: '原产地', | ||||
|         prop: 'cities', | ||||
|         type: 'cascader', | ||||
|         // search: true, | ||||
|         hide: true, | ||||
|         props: { | ||||
|           // expandTrigger: 'click', | ||||
|           label: 'areaName', | ||||
|           value: 'areaCode', | ||||
|           children: 'areaChildVOS', | ||||
|           lazy: true, | ||||
|           lazyLoad: async (node, resolve) => { | ||||
|             console.log(361, node); | ||||
|             const { data } = await GetAreaList({ areaCode: node.value }); | ||||
|             resolve(data ?? []); | ||||
|           }, | ||||
|         }, | ||||
|         dicUrl: `${VITE_APP_BASE_API}/trace/code/farmMange/areas`, | ||||
|         dicUrl: `${VITE_APP_SYSTEM_API}/system/area/region?areaCode=530000`, | ||||
|         dicHeaders: { | ||||
|           authorization: UserStore.token, | ||||
|         }, | ||||
|         dicFormatter: (res) => res?.data ?? [], | ||||
|         dicFormatter: (res) => res.data ?? [], | ||||
|         // change: (o) => setCityChange(o), | ||||
|         rules: { | ||||
|           required: true, | ||||
|           message: '请选择', | ||||
| @ -311,6 +309,15 @@ const state = reactive({ | ||||
|         width: 200, | ||||
|         display: false, | ||||
|       }, | ||||
|       { | ||||
|         label: '', | ||||
|         labelWidth: 0, | ||||
|         prop: 'customInfo', | ||||
|         addDisplay: false, | ||||
|         editDisplay: false, | ||||
|         viewDisplay: true, | ||||
|         span: 24, | ||||
|       }, | ||||
|     ], | ||||
|     actions: [ | ||||
|       { | ||||
| @ -329,6 +336,11 @@ const state = reactive({ | ||||
|         icon: 'delete', | ||||
|         event: ({ row }) => rowDel(row), | ||||
|       }, | ||||
|       { | ||||
|         name: '新增质检', | ||||
|         icon: 'plus', | ||||
|         event: ({ row }) => rowAdd(row), | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|   pageData: { | ||||
| @ -337,8 +349,10 @@ const state = reactive({ | ||||
|     pageSize: 10, | ||||
|   }, | ||||
|   data: [], | ||||
|   currentRow: {}, | ||||
| }); | ||||
| 
 | ||||
| // 加载 | ||||
| const loadData = async () => { | ||||
|   state.loading = true; | ||||
|   GetEntityList(state.query) | ||||
| @ -355,14 +369,13 @@ const loadData = async () => { | ||||
|     }) | ||||
|     .catch((err) => { | ||||
|       app.$message.error(err.msg); | ||||
|       state.data = []; | ||||
|     }) | ||||
|     .finally(() => { | ||||
|       state.loading = false; | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| // GetAreaList(); | ||||
| 
 | ||||
| loadData(); | ||||
| 
 | ||||
| // 页数 | ||||
| @ -403,6 +416,7 @@ const selectionChange = (rows) => { | ||||
| // 查看 | ||||
| const rowView = (row) => { | ||||
|   row.base64 = row.productUrl; | ||||
|   state.currentRow = row; | ||||
|   crudRef.value.rowView(row); | ||||
| }; | ||||
| 
 | ||||
| @ -419,9 +433,33 @@ const rowUploadPicture = async ({ file }) => { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| const setCity = (row) => { | ||||
|   if (!isEmpty(row.cities)) { | ||||
|     row.province = row?.cities[0] ?? null; | ||||
|     row.city = row?.cities[1] ?? null; | ||||
|     row.county = row?.cities[2] ?? null; | ||||
|     row.village = row?.cities[3] ?? null; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // const setCityChange = ({ value, dic }) => { | ||||
| //   debugger; | ||||
| //   const labels = []; | ||||
| //   let currentOptions = dic; | ||||
| //   value.forEach((val) => { | ||||
| //     const option = dic.find((item) => item.areaCode === val); | ||||
| //     if (option) { | ||||
| //       labels.push(option.label); | ||||
| //       currentOptions = option.children || []; | ||||
| //     } | ||||
| //   }); | ||||
| //   state.form.originAddress = labels.join(' / '); | ||||
| // }; | ||||
| 
 | ||||
| // 新增 | ||||
| const rowSave = (row, done, loading) => { | ||||
|   delete row.base64; | ||||
|   setCity(row); | ||||
|   AddEntity(row) | ||||
|     .then((res) => { | ||||
|       if (res.code === 200) { | ||||
| @ -441,10 +479,12 @@ const rowSave = (row, done, loading) => { | ||||
| // 编辑 | ||||
| const rowEdit = (row) => { | ||||
|   row.base64 = row.productUrl; | ||||
|   row.cities = compact([row.province, row.city, row.county ?? '', row.village ?? '']); | ||||
|   crudRef.value.rowEdit(row); | ||||
| }; | ||||
| const rowUpdate = (row, index, done, loading) => { | ||||
|   delete row.base64; | ||||
|   setCity(row); | ||||
|   UpdateEntity(row) | ||||
|     .then((res) => { | ||||
|       if (res.code === 200) { | ||||
| @ -490,6 +530,12 @@ const rowDel = (row, index, done) => { | ||||
|   onDel([row]); | ||||
| }; | ||||
| 
 | ||||
| // 质检 | ||||
| const rowAdd = (row) => { | ||||
|   state.currentRow = row; | ||||
|   qualityAddRef?.value && qualityAddRef.value.show(); | ||||
| }; | ||||
| 
 | ||||
| // 导入 | ||||
| const onUpload = () => { | ||||
|   importExcelRef?.value && importExcelRef.value.show(); | ||||
| @ -512,7 +558,7 @@ const onUploadExcel = (formData) => { | ||||
| }; | ||||
| 
 | ||||
| const onDownloadExcel = (url) => { | ||||
|   downloadLink(url, `采收赋码-导入模板.xlsx`); | ||||
|   downloadFile(url, `采收赋码-导入模板.xlsx`, 'blob'); | ||||
| }; | ||||
| 
 | ||||
| // 导出 | ||||
| @ -526,7 +572,7 @@ const onExport = () => { | ||||
|   ExportEntity(state.query) | ||||
|     .then((res) => { | ||||
|       if (res.status === 200) { | ||||
|         downloadFile(res.data, `${fileName}.xlsx`); | ||||
|         downloadFile(res.data, `${fileName}.xlsx`, 'blob'); | ||||
|         app.$message.success('导出成功!'); | ||||
|       } | ||||
|     }) | ||||
|  | ||||
| @ -0,0 +1,175 @@ | ||||
| <template> | ||||
|   <div class="custom-info"> | ||||
|     <avue-crud ref="crudRef" :table-loading="state.loading" :data="state.list" :option="state.options"> | ||||
|       <template #header> | ||||
|         <h5 class="custom-form__title">质检记录</h5> | ||||
|       </template> | ||||
|       <template #qualityReportUrl="{ row: item }"> | ||||
|         <el-button | ||||
|           v-if="item.qualityReportUrl" | ||||
|           type="primary" | ||||
|           text | ||||
|           @click="downloadFile(item.qualityReportUrl, `${item.productName}-质检报告.png`, 'image')" | ||||
|         > | ||||
|           下载 | ||||
|         </el-button> | ||||
|         <span v-else>暂无</span> | ||||
|       </template> | ||||
|     </avue-crud> | ||||
|   </div> | ||||
| </template> | ||||
| <script setup> | ||||
| import { reactive, ref, watch } from 'vue'; | ||||
| import { useApp } from '@/hooks'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { downloadFile } from '@/utils'; | ||||
| import { GetEntity } from '@/apis/coding'; | ||||
| 
 | ||||
| const props = defineProps({ | ||||
|   row: { | ||||
|     type: Object, | ||||
|     default: () => {}, | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| const app = useApp(); | ||||
| const crudRef = ref(null); | ||||
| const state = reactive({ | ||||
|   loading: false, | ||||
|   // query: { | ||||
|   //   current: 1, | ||||
|   //   size: 10, | ||||
|   // }, | ||||
|   options: { | ||||
|     ...CRUD_OPTIONS, | ||||
|     index: false, | ||||
|     addBtn: false, | ||||
|     refreshBtn: false, | ||||
|     selection: false, | ||||
|     menu: false, | ||||
|     column: [ | ||||
|       { | ||||
|         label: '溯源码', | ||||
|         prop: 'id', | ||||
|         width: 200, | ||||
|         fixed: true, | ||||
|       }, | ||||
|       { | ||||
|         label: '采收批次', | ||||
|         prop: 'harvestBatch', | ||||
|         width: 200, | ||||
|       }, | ||||
|       { | ||||
|         label: '产品名称', | ||||
|         prop: 'productName', | ||||
|         width: 200, | ||||
|       }, | ||||
|       { | ||||
|         label: '质检结果', | ||||
|         prop: 'qualityResultType', | ||||
|         type: 'select', | ||||
|         dicData: [ | ||||
|           { | ||||
|             label: '合格', | ||||
|             value: 0, | ||||
|           }, | ||||
|           { | ||||
|             label: '不合格', | ||||
|             value: 1, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       { | ||||
|         label: '质检类型', | ||||
|         prop: 'qualityType', | ||||
|         type: 'select', | ||||
|         dicData: [ | ||||
|           { | ||||
|             label: '检测机构', | ||||
|             value: 0, | ||||
|           }, | ||||
|           { | ||||
|             label: '自检', | ||||
|             value: 1, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       { | ||||
|         label: '质检机构', | ||||
|         prop: 'department', | ||||
|         width: 200, | ||||
|         overHidden: true, | ||||
|       }, | ||||
|       { | ||||
|         label: '质检项目', | ||||
|         prop: 'qualityProject', | ||||
|       }, | ||||
|       { | ||||
|         label: '质检报告', | ||||
|         prop: 'qualityReportUrl', | ||||
|         slot: true, | ||||
|       }, | ||||
|       { | ||||
|         label: '检测说明', | ||||
|         prop: 'qualityDescribe', | ||||
|         type: 'textarea', | ||||
|         overHidden: true, | ||||
|         resize: 'none', | ||||
|         width: 200, | ||||
|       }, | ||||
|       { | ||||
|         label: '质检人', | ||||
|         prop: 'qualityPerson', | ||||
|       }, | ||||
|       { | ||||
|         label: '质检时间', | ||||
|         prop: 'qualityTime', | ||||
|         width: 200, | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|   // pageData: { | ||||
|   //   total: 0, | ||||
|   //   currentPage: 1, | ||||
|   //   pageSize: 10, | ||||
|   // }, | ||||
|   data: {}, | ||||
|   list: [], | ||||
| }); | ||||
| 
 | ||||
| // 加载 | ||||
| const loadData = () => { | ||||
|   state.loading = true; | ||||
|   GetEntity({ id: props.row.id }) | ||||
|     .then((res) => { | ||||
|       if (res.code === 200) { | ||||
|         state.data = res.data; | ||||
|         state.list = res.data?.productInfo ?? []; | ||||
|       } | ||||
|     }) | ||||
|     .catch((err) => { | ||||
|       app.$message.error(err.msg); | ||||
|     }) | ||||
|     .finally(() => { | ||||
|       state.loading = false; | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| watch( | ||||
|   () => props.row, | ||||
|   (val) => { | ||||
|     val?.id && loadData(); | ||||
|   }, | ||||
|   { | ||||
|     deep: true, | ||||
|     immediate: true, | ||||
|   } | ||||
| ); | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .custom-info { | ||||
|   :deep(.avue-crud__header) { | ||||
|     display: none !important; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -3,7 +3,7 @@ | ||||
|  * @Author: zenghua.wang | ||||
|  * @Date: 2022-09-18 21:24:29 | ||||
|  * @LastEditors: zenghua.wang | ||||
|  * @LastEditTime: 2025-02-07 10:01:57 | ||||
|  * @LastEditTime: 2025-02-08 17:26:25 | ||||
|  */ | ||||
| 
 | ||||
| import { defineConfig, loadEnv } from 'vite'; | ||||
| @ -23,7 +23,6 @@ import { resolve } from 'path'; | ||||
| const useDevMode = true; | ||||
| 
 | ||||
| export default defineConfig(({ command, mode }) => { | ||||
|   console.log('vite.config.js', command, mode, loadEnv(mode, process.cwd())); | ||||
|   const { | ||||
|     VITE_PORT, | ||||
|     VITE_APP_NAME, | ||||
| @ -31,8 +30,8 @@ export default defineConfig(({ command, mode }) => { | ||||
|     VITE_APP_BASE_URL, | ||||
|     VITE_APP_UPLOAD_API, | ||||
|     VITE_APP_UPLOAD_URL, | ||||
|     VITE_APP_DICDATA_API, | ||||
|     VITE_APP_DICDATA_URL, | ||||
|     VITE_APP_SYSTEM_API, | ||||
|     VITE_APP_SYSTEM_URL, | ||||
|   } = loadEnv(mode, process.cwd()); | ||||
|   const config = { | ||||
|     base: './', | ||||
| @ -53,17 +52,17 @@ export default defineConfig(({ command, mode }) => { | ||||
|         [VITE_APP_BASE_API]: { | ||||
|           target: VITE_APP_BASE_URL, | ||||
|           changeOrigin: true, | ||||
|           rewrite: (path) => path.replace(/^\/traceApis/, ''), | ||||
|           rewrite: (path) => path.replace(/^\/apis/, ''), | ||||
|         }, | ||||
|         [VITE_APP_UPLOAD_API]: { | ||||
|           target: VITE_APP_UPLOAD_URL, | ||||
|           changeOrigin: true, | ||||
|           rewrite: (path) => path.replace(/^\/uploadApis/, ''), | ||||
|         }, | ||||
|         [VITE_APP_DICDATA_API]: { | ||||
|           target: VITE_APP_DICDATA_URL, | ||||
|         [VITE_APP_SYSTEM_API]: { | ||||
|           target: VITE_APP_SYSTEM_URL, | ||||
|           changeOrigin: true, | ||||
|           rewrite: (path) => path.replace(/^\/dicDataApis/, ''), | ||||
|           rewrite: (path) => path.replace(/^\/systemApis/, ''), | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|  | ||||
| @ -3,10 +3,10 @@ | ||||
|  * @Author: zenghua.wang | ||||
|  * @Date: 2022-02-23 21:12:37 | ||||
|  * @LastEditors: zenghua.wang | ||||
|  * @LastEditTime: 2025-01-25 17:03:51 | ||||
|  * @LastEditTime: 2025-02-10 14:45:39 | ||||
|  */ | ||||
| import lodash from 'lodash'; | ||||
| import moment from 'moment'; | ||||
| import dayjs from 'dayjs'; | ||||
| import { Base64 } from 'js-base64'; | ||||
| 
 | ||||
| /** | ||||
| @ -90,7 +90,7 @@ export const setDefaultOption = (options, prop, defaultVal) => { | ||||
|   return options[prop] === undefined ? defaultVal : options.prop; | ||||
| }; | ||||
| /** | ||||
|  * 设置字典值 | ||||
|  * @Title 设置字典值 | ||||
|  * @param {*} columns | ||||
|  * @param {*} key | ||||
|  * @param {*} data | ||||
| @ -107,7 +107,7 @@ export const setDicData = (columns, key, data = []) => { | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  * 求字段lable | ||||
|  * @Title 求字段lable | ||||
|  * @param {*} tree | ||||
|  * @returns | ||||
|  */ | ||||
| @ -124,7 +124,35 @@ export const setDicLabel = (dicData, value) => { | ||||
|   return label; | ||||
| }; | ||||
| /** | ||||
|  * 加密 | ||||
|  * @Title 数组交集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const intersectionArray = (arr1 = [], arr2 = []) => { | ||||
|   return arr1.filter((item) => arr2.includes(item)); | ||||
| }; | ||||
| /** | ||||
|  * @Title 数组并集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const unionArray = (arr1 = [], arr2 = []) => { | ||||
|   return Array.from(new Set([...arr1, ...arr2])); | ||||
| }; | ||||
| /** | ||||
|  * @Title 数组差集 | ||||
|  * @param {*} arr1 | ||||
|  * @param {*} arr2 | ||||
|  * @returns | ||||
|  */ | ||||
| export const differenceArray = (arr1 = [], arr2 = []) => { | ||||
|   const s = new Set(arr2); | ||||
|   return arr1.filter((x) => !s.has(x)); | ||||
| }; | ||||
| /** | ||||
|  * @Title 加密 | ||||
|  * @param {*} n | ||||
|  * @returns | ||||
|  */ | ||||
| @ -146,7 +174,7 @@ export const encode = (n, flag = false) => { | ||||
|   return n; | ||||
| }; | ||||
| /** | ||||
|  * 解密 | ||||
|  * @Title 解密 | ||||
|  * @param {*} e | ||||
|  * @returns | ||||
|  */ | ||||
| @ -190,6 +218,22 @@ export const imageToBase64 = (file) => { | ||||
| export const bufferToBase64 = (buffer) => { | ||||
|   return 'data:image/jpeg;base64,' + window.btoa(new Uint8Array(buffer).reduce((data, byte) => data + String.fromCharCode(byte), '')); | ||||
| }; | ||||
| /** | ||||
|  * @Title blob转json | ||||
|  * @param {*} file | ||||
|  * @returns | ||||
|  */ | ||||
| export const blobToJSON = (blob) => { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     const reader = new FileReader(); | ||||
|     reader.readAsText(blob, 'utf-8'); | ||||
|     reader.onload = () => { | ||||
|       const res = !isEmpty(reader.result) ? JSON.parse(reader.result) : reader.result; | ||||
|       resolve(res); | ||||
|     }; | ||||
|     reader.onerror = reject; | ||||
|   }); | ||||
| }; | ||||
| /** | ||||
|  * @Title 将array转化为树 | ||||
|  * @param tree | ||||
| @ -227,42 +271,76 @@ export const getUrlQuery = (name) => { | ||||
|   const usp = new URLSearchParams(search); | ||||
|   return usp.get(name); | ||||
| }; | ||||
| /** | ||||
|  * @Title 将Object参数转换为字符串 | ||||
|  * @param {*} json | ||||
|  * @returns | ||||
|  */ | ||||
| export const obj2Param = (json) => { | ||||
|   if (!json) return ''; | ||||
|   return Object.keys(json) | ||||
|     .map((key) => { | ||||
|       if (isEmpty(json[key])) return ''; | ||||
|       return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]); | ||||
|     }) | ||||
|     .join('&'); | ||||
| }; | ||||
| /** | ||||
|  * @Title 获取静态资源文件 | ||||
|  * @param {*} url | ||||
|  * @returns | ||||
|  */ | ||||
| export const getAssetsFile = (url) => { | ||||
|   return new URL(`../assets/images/${url}`, import.meta.url); | ||||
|   return new URL(`../assets/${url}`, import.meta.url); | ||||
| }; | ||||
| /** | ||||
|  * @Title 替换图片url字段值 | ||||
|  * @param {*} url | ||||
|  * @returns | ||||
|  */ | ||||
| export const setUploadField = (url) => { | ||||
|   if (isEmpty(url) || url.includes('http')) return null; | ||||
|   return url; | ||||
| }; | ||||
| /** | ||||
|  * @Title: a链接方式文件下载 | ||||
|  * @param {void} content: | ||||
|  * @Title: 下载文件 | ||||
|  * @param {void} url: | ||||
|  * @param {void} fileName: | ||||
|  * @param {void} fileType: | ||||
|  * @return {void} | ||||
|  */ | ||||
| export const dowloadLink = (content, fileName) => { | ||||
|   const blob = new Blob([content]); | ||||
|   if ('download' in document.createElement('a')) { | ||||
|     const elink = document.createElement('a'); | ||||
|     elink.download = fileName; | ||||
|     elink.style.display = 'none'; | ||||
|     elink.href = URL.createObjectURL(blob); | ||||
|     document.body.appendChild(elink); | ||||
|     elink.click(); | ||||
|     URL.revokeObjectURL(elink.href); | ||||
|     document.body.removeChild(elink); | ||||
|   } else { | ||||
|     navigator.msSaveBlob(blob, fileName); | ||||
| export const downloadFile = async (url, fileName, fileType) => { | ||||
|   let blob = null; | ||||
|   try { | ||||
|     switch (fileType) { | ||||
|       case 'image': { | ||||
|         const img = new Image(); | ||||
|         img.crossOrigin = 'Anonymous'; | ||||
|         img.src = url; | ||||
|         await new Promise((resolve, reject) => { | ||||
|           img.onload = resolve; | ||||
|           img.onerror = reject; | ||||
|         }); | ||||
|         const canvas = document.createElement('canvas'); | ||||
|         canvas.width = img.width; | ||||
|         canvas.height = img.height; | ||||
|         const ctx = canvas.getContext('2d'); | ||||
|         ctx.drawImage(img, 0, 0); | ||||
|         blob = await new Promise((resolve) => { | ||||
|           canvas.toBlob(resolve, 'image/jpeg'); | ||||
|         }); | ||||
|         break; | ||||
|       } | ||||
|       case 'blob': { | ||||
|         blob = new Blob([url]); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if ('download' in document.createElement('a')) { | ||||
|       const elink = document.createElement('a'); | ||||
|       elink.download = fileName; | ||||
|       elink.style.display = 'none'; | ||||
|       elink.href = blob ? URL.createObjectURL(blob) : url; | ||||
|       document.body.appendChild(elink); | ||||
|       elink.click(); | ||||
|       blob && URL.revokeObjectURL(elink.href); | ||||
|       document.body.removeChild(elink); | ||||
|     } else { | ||||
|       navigator.msSaveBlob(blob, fileName); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('下载出错:', error); | ||||
|   } | ||||
| }; | ||||
| /** | ||||
| @ -275,20 +353,106 @@ export const sleep = (duration = 0) => | ||||
|     setTimeout(resolve, duration); | ||||
|   }); | ||||
| /** | ||||
|  * 日期格式化 | ||||
|  * @Title 创建id | ||||
|  * @param {*} prefix | ||||
|  * @returns | ||||
|  */ | ||||
| export const createId = (prefix) => { | ||||
|   const val = Date.now() + Math.ceil(Math.random() * 99999); | ||||
|   return isEmpty(prefix) ? val : prefix + '-' + val; | ||||
| }; | ||||
| /** | ||||
|  * @Title 生成数据 | ||||
|  * @param {*} duration | ||||
|  * @returns | ||||
|  */ | ||||
| export const mockData = (item = {}, len = 1) => { | ||||
|   const list = []; | ||||
|   for (let i = 0; i < len; i++) { | ||||
|     let temp = { ...item, id: createId() }; | ||||
|     list.push(temp); | ||||
|   } | ||||
|   return list; | ||||
| }; | ||||
| /** | ||||
|  * @Title 日期格式化 | ||||
|  * @param {*} date | ||||
|  * @param {*} format | ||||
|  * @returns | ||||
|  */ | ||||
| export const dateFormat = (datetime, type = 'yyyy-MM-dd') => { | ||||
|   return moment(datetime).format(type); | ||||
| export const dateFormat = (datetime, formater = 'YYYY-MM-DD hh:mm:ss') => { | ||||
|   if (datetime instanceof Date || datetime) { | ||||
|     return dayjs(datetime).format(formater); | ||||
|   } else { | ||||
|     return null; | ||||
|   } | ||||
| }; | ||||
| /** | ||||
|  * 上日/周/月/年 | ||||
|  * @Title 字符串转日期 | ||||
|  * @param {*} str | ||||
|  * @returns | ||||
|  */ | ||||
| export const lastDate = (last = 0, date = 'month', type = 'yyyy-MM-dd') => { | ||||
|   if (date === 'day') { | ||||
|     return moment().subtract(last, 'day').endOf('day').format(type); | ||||
|   } | ||||
|   return moment().subtract(last, date).format(type); | ||||
| export const toDate = (str) => { | ||||
|   return !isEmpty(str) ? dayjs(str) : dayjs(); | ||||
| }; | ||||
| /** | ||||
|  * @Title 字符串转日期 | ||||
|  * @param {*} str | ||||
|  * @returns | ||||
|  */ | ||||
| export const getDate = (num, type, formater = 'YYYY-MM-DD', start = true) => { | ||||
|   const date = dayjs().subtract(num, type); | ||||
|   return start ? date.startOf(type).format(formater) : date.endOf(type).format(formater); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 获取时间差 | ||||
|  * @param start | ||||
|  * @param end | ||||
|  * @param type | ||||
|  * @returns | ||||
|  */ | ||||
| export const getDiffTime = (start, end, type) => { | ||||
|   const startTime = dayjs(start); | ||||
|   const endTime = dayjs(end); | ||||
|   const duration = endTime.diff(startTime); | ||||
|   let diff = 0; | ||||
|   switch (type) { | ||||
|     case 'DD': { | ||||
|       diff = duration / (1000 * 60 * 60 * 24); | ||||
|       break; | ||||
|     } | ||||
|     case 'HH': { | ||||
|       diff = duration / (1000 * 60 * 60); | ||||
|       break; | ||||
|     } | ||||
|     case 'mm': { | ||||
|       diff = duration / (1000 * 60); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   return Math.round(diff); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 开始日期 | ||||
|  * @param last | ||||
|  * @param type | ||||
|  * @param formater | ||||
|  * @returns | ||||
|  */ | ||||
| export const startDate = (num, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => { | ||||
|   if (num === 'now') return dayjs().format(formater); | ||||
|   if (typeof num === 'string') return dayjs(num).startOf(type).format(formater); | ||||
|   return num === 0 ? dayjs().startOf(type).format(formater) : dayjs().subtract(num, type).startOf(type).format(formater); | ||||
| }; | ||||
| /** | ||||
|  * @Title: 结束日期 | ||||
|  * @param num | ||||
|  * @param type | ||||
|  * @param formater | ||||
|  * @returns | ||||
|  */ | ||||
| export const endDate = (num = 0, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => { | ||||
|   if (num === 'now') return dayjs().format(formater); | ||||
|   if (typeof num === 'string') return dayjs(num).endOf(type).format(formater); | ||||
|   return num === 0 ? dayjs().endOf(type).format(formater) : dayjs().subtract(num, type).endOf(type).format(formater); | ||||
| }; | ||||
|  | ||||
| @ -23,7 +23,6 @@ import { resolve } from 'path'; | ||||
| const useDevMode = true; | ||||
| 
 | ||||
| export default defineConfig(({ command, mode }) => { | ||||
|   console.log('vite.config.js', command, mode, loadEnv(mode, process.cwd())); | ||||
|   const { VITE_PORT, VITE_APP_NAME, VITE_APP_BASE_API, VITE_APP_BASE_URL, VITE_APP_UPLOAD_API, VITE_APP_UPLOAD_URL } = loadEnv(mode, process.cwd()); | ||||
|   const config = { | ||||
|     base: './', | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user