import request from '@/utils/request'; import { setStorageWithExpiry, getStorageWithExpiry } from '@/utils/auth' export function getWXStatusHeight() { // #ifdef MP-WEIXIN // 获取距上 const barTop = wx.getSystemInfoSync().statusBarHeight // 获取胶囊按钮位置信息 const menuButtonInfo = wx.getMenuButtonBoundingClientRect() // 获取导航栏高度 const barHeight = menuButtonInfo.height + (menuButtonInfo.top - barTop) * 2 let barWidth = menuButtonInfo.width console.log('menuButtonInfo', menuButtonInfo) let barLeftPosition = 375 - menuButtonInfo.right + menuButtonInfo.width let menuButtonLeft = menuButtonInfo.left let menuButtonRight = menuButtonInfo.right return { barHeight, barTop, barWidth, barLeftPosition, menuButtonLeft, menuButtonRight } // #endif } /** * 根据订单的状态获取订单的文字展示状态(这个状态范围少,是按李总意思整理出来的状态) * @param ticketsStatus 订单状态 * @param isHandover 是否交车 */ export function getOrderStatusText(ticketsStatus, isHandover) { let str = "已进厂"; if ("04" == ticketsStatus) { //待派工 str = "待维修" } else if ("05" == ticketsStatus) { //维修中 str = "维修中" } else if ("01" == ticketsStatus) { //待取车结算 if ("1" == isHandover) { //已交车 str = "已交车未结算" } else { //未交车 str = "未交车未结算" } } else if ("06" == ticketsStatus) { //挂单/记账 if ("1" == isHandover) { //已交车 str = "已交车已结算" } else { //未交车 str = "已结算未交车" } } else if ("07" == ticketsStatus) { //待通知客户取车 str = "已竣工" } else if ("02" == ticketsStatus) { //已结账 if ("1" == isHandover) { //已交车 str = "已交车已结算" } else { //未交车 str = "已结算未交车" } } else if ("03" == ticketsStatus) { //已作废 str = "已作废" } else if ("08" == ticketsStatus) { //已作废 str = "已完成" } return str; } /** * 根据订单的状态获取订单的文字展示状态(这个状态多,就是系统初始状态) * @param ticketsStatus 订单状态 * @param isHandover 是否交车 */ export function getOrderStatusTextAll(ticketsStatus, isHandover) { let str = "已进厂"; if ("04" == ticketsStatus) { //待派工 str = "待派工" } else if ("05" == ticketsStatus) { //维修中 str = "维修中" } else if ("01" == ticketsStatus) { //待取车结算 if ("1" == isHandover) { //已交车 str = "已交车未结算" } else { //未交车 str = "未交车未结算" } } else if ("06" == ticketsStatus) { //挂单/记账 str = "已挂单/记账待交车" if ("1" == isHandover) { //已交车 str = "已交车已结算" } else { //未交车 str = "已结算未交车" } } else if ("07" == ticketsStatus) { //待通知客户取车 str = "待通知客户取车" } else if ("02" == ticketsStatus) { //已结账 if ("1" == isHandover) { //已交车 str = "已交车已结算" } else { //未交车 str = "已结算未交车" } } else if ("03" == ticketsStatus) { //已作废 str = "已作废" } else if ("08" == ticketsStatus) { //已作废 str = "已完成" } return str; } /** * 查询字典可选值 * @param dictCode */ export function getDictByCode(dictCode) { let dictArray = getStorageWithExpiry(dictCode); if (null == dictArray || undefined == dictArray) { request({ url: '/admin-api/system/dict-data/type', method: 'get', params: { type: dictCode } }).then((res) => { console.log(res) if (res.code == 200) { setStorageWithExpiry(dictCode, res.data, 3600) return res.data } }) } else { return dictArray } } /** * 工单记录操作日志 * @param id 工单主表id * @param ticketsWorkStatus 工单主表状态 * @param itemId 工单子表id * @param itemStatus 工单子表状态 * @param recordType 操作类型 对应后端枚举:RecordTypeEnum * @param remark 备注 * @param image 图片相对路径,多个英文逗号隔开 * @param finishType 完成类型 01:完成并移交下一班组、02:完成并移交总检、03:完成工单 * @param nextName 下一班组名称 */ export function saveTicketsRecords(id, ticketsWorkStatus, itemId, itemStatus, recordType, remark, image, finishType, nextName) { return new Promise((resolve, reject) => { let dataObj = { id: id, ticketsWorkStatus: ticketsWorkStatus, item: { id: itemId, itemStatus: itemStatus }, recordType: recordType, remark: remark, finishType: finishType, nextName: nextName, image: image } request({ url: '/admin-api/repair/tickets/updateStatus', method: 'POST', data: dataObj }).then((res) => { console.log(res) if (res.code == 200) { uni.showToast({ title: '操作成功', icon: 'none' }) resolve(1); } else { uni.showToast({ title: '操作失败,请联系管理员', icon: 'none' }) reject(0); } }) }); } /** * 翻译字典 * @param dictCode */ export async function getDictTextByCodeAndValue(dictCode, value) { let dictArray = getStorageWithExpiry(dictCode); if (null == dictArray || undefined == dictArray) { let res = await request({ url: '/admin-api/system/dict-data/type', method: 'get', params: { type: dictCode } }) if (res.code == 200) { setStorageWithExpiry(dictCode, res.data, 3600) dictArray = res.data let dictObj = dictArray.find(item => item.value == value) if (dictObj) { return dictObj.label } else { return "未知数据" } } } else { let dictObj = dictArray.find(item => item.value == value) if (dictObj) { return dictObj.label } else { return "未知数据" } } } export function formatTimestamp(timestamp) { // 将时间戳转换为Date对象 const date = new Date(timestamp); // 获取年月日时分秒 const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); // 组合成日期时间字符串 return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } /** * 将时间戳转换为指定格式的日期字符串 * @param {number} timestamp - 时间戳(毫秒) * @param {string} [format='YYYY-MM-DD'] - 日期格式,默认为 'YYYY-MM-DD' * @returns {string} - 格式化的日期字符串 */ export function formatTimestampCustom(timestamp, format = 'YYYY-MM-DD') { const date = new Date(timestamp); const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const hour = date.getHours().toString().padStart(2, '0'); const minute = date.getMinutes().toString().padStart(2, '0'); const second = date.getSeconds().toString().padStart(2, '0'); const replaceMap = { 'YYYY': year, 'MM': month, 'DD': day, 'HH': hour, 'mm': minute, 'ss': second }; return format.replace(/YYYY|MM|DD|HH|mm|ss/g, match => replaceMap[match]); } /** * 格式化金额 * @param {string|number} amount - 金额 * @returns {string} - 格式化后的金额 */ export function formatCurrency(amount) { if (amount === undefined || amount === null || amount === '') { return '0.00'; } // 处理可能的字符串类型金额 const num = typeof amount === 'string' ? parseFloat(amount) : amount; // 检查是否是有效数字 if (isNaN(num)) { return '0.00'; } // 格式化金额,保留两位小数 return num.toLocaleString('zh-CN', { minimumFractionDigits: 2, numberOfDigits: 2 }); } /** * 组装订单对象 * @param order */ export function builderOrder(order) { return { id: order.id, orderNo: order.ticketNo, flag: 1, ticketsStatus: order.ticketsStatus, ticketsWorkStatus: order.ticketsWorkStatus, flagStr: getOrderStatusTextAll(order.ticketsStatus, order.isHandover), carNum: order.carNo, nowRepairId: order.nowRepairId, carModel: order.carBrandName, userName: order.userName, userPhone: order.userMobile, counselorName: order.adviserName, canOperate: order.canOperate, ...order, } } export function formatDate(timestamp) { if (!timestamp) { return '' } // 将时间戳转换为Date对象 const date = new Date(timestamp); // 获取年月日时分秒 const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); // 组合成日期时间字符串 return `${year}-${month}-${day}`; } //转换为double // utils.js export function convertToDouble(value, decimalPlaces = 1) { if (value !== undefined && value !== null) { const parsedValue = parseFloat(value); if (!isNaN(parsedValue)) { return parsedValue.toFixed(decimalPlaces); } else { console.error('转换失败,值不是有效的数字'); return '0.0'; // 可以设置一个默认值 } } else { console.error('值不存在'); return '0.0'; // 可以设置一个默认值 } } /** * 生成一个16位的纯数字的唯一ID * 生成策略 head + 当前时间戳 + 随机数 * @param head 前缀 */ export function createUniqueCodeByHead(head = '') { const min = 100; // 最小值 const max = 999; // 最大值 return head.toString() + Date.now().toString() + Math.floor(Math.random() * (max - min + 1)) + min; } /** * 构造树 * @param items 原对象数组 * @param idKey 主标识 * @param parentKey 父标识 * @param mapping 映射Map */ export function buildTree(items, idKey, parentKey, mapping = null) { const result = []; // 存储最终的树形结构 const itemMap = {}; // 用于快速查找对象 // 首先将所有项放入map中,便于后续快速查找 for (const item of items) { itemMap[item[idKey]] = { ...item, children: [] }; } // 遍历每个项,构建树形结构 for (const item of items) { const id = item[idKey]; const parentId = item[parentKey]; const node = itemMap[id]; if (parentId !== null && itemMap[parentId]) { // 如果有父ID,并且父节点存在,则将当前节点加入到其父节点的children数组中 itemMap[parentId].children.push(node); } else { // 如果没有父ID,或者找不到对应的父节点,则认为这是根节点 result.push(node); } } if (mapping) { return mapTree(result, mapping) } return result; } // 映射函数 function mapTree(tree, mapping) { if (!tree || !Array.isArray(tree)) { return tree; } const mappedTree = tree.map(item => { const mappedItem = {}; for (const key in item) { if (key === 'children') { // 递归处理 children 数组 if (mapping.children) { mappedItem[mapping.children] = mapTree(item[key], mapping); } else { mappedItem[key] = mapTree(item[key], mapping); } } else if (key in mapping) { // 根据映射规则转换属性 const targetKey = mapping[key]; mappedItem[targetKey] = item[key]; } } return mappedItem; }); return mappedTree; } export function formatDateChinese(timestamp) { // 将时间戳转换为Date对象 const date = new Date(timestamp); // 获取年月日时分秒 const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); // 组合成日期时间字符串 return `${year}年${month}月${day}日`; } export function formatDateTimeToMinute(timestamp) { // 将时间戳转换为 Date 对象 const date = new Date(timestamp); // 获取年月日时分 const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); // 组合成日期时间字符串(格式:yyyy-MM-dd hh:mm) return `${year}-${month}-${day} ${hours}:${minutes}`; } export function getDateRange(type) { const now = new Date() let start, end if (type === 'week') { // 获取本周的开始(周一)和结束(周日) const day = now.getDay() || 7 // Sunday 为 0,设为 7 start = new Date(now) start.setDate(now.getDate() - day + 1) end = new Date(start) end.setDate(start.getDate() + 6) } else if (type === 'month') { // 获取本月的开始和结束 start = new Date(now.getFullYear(), now.getMonth(), 1) end = new Date(now.getFullYear(), now.getMonth() + 1, 0) // 本月最后一天 } else if (type === 'day') { // 获取当天的开始和结束(00:00:00 到 23:59:59) start = new Date(now) start.setHours(0, 0, 0, 0) end = new Date(now) end.setHours(23, 59, 59, 999) } else { return [] } return [ formatDateCus(start), formatDateCus(end) ] } export function formatDateCus(date) { const y = date.getFullYear() const m = (date.getMonth() + 1).toString().padStart(2, '0') const d = date.getDate().toString().padStart(2, '0') return `${y}-${m}-${d}` } /** * 将扁平数组转换为树形结构,并支持按 sort 字段排序 * @param {Array} data 源数据 * @param {String} id 节点ID字段名,默认为 'id' * @param {String} parentId 父节点ID字段名,默认为 'parentId' * @param {String} children 子节点字段名,默认为 'children' * @param {Number|String} rootId 根节点ID值,默认为最小的parentId或0 * @param {String} sortKey 排序字段名,默认为 'sort' * @returns {Array} 树形结构数据 */ export function handleTree(data, id, parentId, children, rootId, sortKey) { // 参数默认值处理 id = id || 'id'; parentId = parentId || 'parentId'; children = children || 'children'; sortKey = sortKey || 'sort'; // 自动计算根节点ID(取最小的parentId,若无则用0) rootId = rootId || Math.min(...data.map(item => item[parentId])) || 0; // 深拷贝源数据以避免污染原数组 const cloneData = JSON.parse(JSON.stringify(data)); // 先对所有数据进行排序(确保父节点在前) cloneData.sort((a, b) => { const aSort = a[sortKey] ?? 0; // 使用空值合并运算符处理undefined const bSort = b[sortKey] ?? 0; return aSort - bSort; // 升序排序 }); // 构建哈希表加速查找 const nodeMap = {}; cloneData.forEach(item => { nodeMap[item[id]] = item; item[children] = []; // 初始化children数组 }); // 构建树形结构 const tree = []; cloneData.forEach(item => { if (item[parentId] === rootId) { // 根节点直接加入结果 tree.push(item); } else { // 非根节点找到父节点并插入 const parent = nodeMap[item[parentId]]; parent?.[children]?.push(item); } }); // 递归排序所有子节点 const sortChildren = (nodes) => { nodes.forEach(node => { if (node[children]?.length) { node[children].sort((a, b) => { const aSort = a[sortKey] ?? 0; const bSort = b[sortKey] ?? 0; return aSort - bSort; }); sortChildren(node[children]); } }); }; sortChildren(tree); return tree.length ? tree : data; // 空树时返回原数据 } /** * 将树形结构数据转成 uniapp multiSelector picker 可用的二维数组 * @param {Array} tree 树形结构数据 * @param {String} labelKey 节点显示字段,默认为 'name' * @param {String} childrenKey 子节点字段,默认为 'children' * @returns {Array} picker二维数组,例如 [[一级], [二级], [三级]...] */ export function toPickerData(tree, labelKey = 'name', childrenKey = 'children') { const result = [] function buildColumns(nodes, level = 0) { if (!nodes || !nodes.length) return // 当前层级的所有 name result[level] = nodes.map(n => n[labelKey]) // 默认取第一个子节点继续递归 if (nodes[0][childrenKey] && nodes[0][childrenKey].length) { buildColumns(nodes[0][childrenKey], level + 1) } } buildColumns(tree, 0) return result }