common.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. import config from '@/config'
  2. import { getToken } from '@/utils/auth'
  3. import { listCheckApprovalCcDetails, listCheckPendingTasks } from "@/api/myToDoList/myToDoList.js"
  4. import { listData } from "@/api/system/dict/data.js"
  5. /**
  6. * 显示消息提示框
  7. * @param content 提示的标题
  8. */
  9. export function toast(content) {
  10. uni.showToast({
  11. icon: 'none',
  12. title: content
  13. })
  14. }
  15. /**
  16. * 显示模态弹窗
  17. * @param content 提示的标题
  18. */
  19. export function showConfirm(content) {
  20. return new Promise((resolve, reject) => {
  21. uni.showModal({
  22. title: '提示',
  23. content: content,
  24. cancelText: '取消',
  25. confirmText: '确定',
  26. success: function (res) {
  27. resolve(res)
  28. }
  29. })
  30. })
  31. }
  32. /**
  33. * 参数处理
  34. * @param params 参数
  35. */
  36. export function tansParams(params) {
  37. let result = ''
  38. for (const propName of Object.keys(params)) {
  39. const value = params[propName]
  40. var part = encodeURIComponent(propName) + "="
  41. if (value !== null && value !== "" && typeof (value) !== "undefined") {
  42. if (typeof value === 'object') {
  43. for (const key of Object.keys(value)) {
  44. if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
  45. let params = propName + '[' + key + ']'
  46. var subPart = encodeURIComponent(params) + "="
  47. result += subPart + encodeURIComponent(value[key]) + "&"
  48. }
  49. }
  50. } else {
  51. result += part + encodeURIComponent(value) + "&"
  52. }
  53. }
  54. }
  55. return result
  56. }
  57. export function getDate(date, AddDayCount = 0) {
  58. if (!date) {
  59. date = new Date()
  60. }
  61. if (typeof date !== 'object') {
  62. date = date.replace(/-/g, '/')
  63. }
  64. const dd = new Date(date)
  65. dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
  66. const y = dd.getFullYear()
  67. const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
  68. const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
  69. return {
  70. fullDate: y + '-' + m + '-' + d,
  71. year: y,
  72. month: m,
  73. date: d,
  74. day: dd.getDay()
  75. }
  76. }
  77. export function serializeData(obj) {
  78. let str = '?'
  79. Object.keys(obj).forEach(function (key) {
  80. str += key + "=" + obj[key] + '&'
  81. });
  82. let reg = /&$/gi;
  83. str = str.replace(reg, ""); //清除最后一个&符号
  84. return str
  85. }
  86. export function buildTeamOptions(tree = [], includeFullData = false) {
  87. const result = [];
  88. function dfs(node, path = []) {
  89. const currentPath = [...path, node.label];
  90. // 如果是 TEAMS 叶子节点
  91. if (node.deptType === 'TEAMS') {
  92. if (includeFullData) {
  93. // 包含完整节点数据
  94. result.push({
  95. ...node,
  96. text: currentPath.join(' / '),
  97. value: node.id,
  98. path: currentPath,
  99. children: null
  100. });
  101. } else {
  102. // 只包含text和value
  103. result.push({
  104. text: currentPath.join(' / '),
  105. value: node.id
  106. });
  107. }
  108. }
  109. // 继续递归子节点
  110. if (node.children && Array.isArray(node.children)) {
  111. node.children.forEach(child => dfs(child, currentPath));
  112. }
  113. }
  114. tree.forEach(root => dfs(root));
  115. return result;
  116. }
  117. /**
  118. * 找出deptType为DEPARTMENT的节点
  119. * @param {Array} tree - 树形结构数据
  120. * @param {boolean} includeFullData - 是否包含节点的完整数据,默认false
  121. * @returns {Array} 包含所有DEPARTMENT节点的数组
  122. */
  123. export function buildDepartmentOptions(tree = [], includeFullData = false) {
  124. const result = [];
  125. function dfs(node, path = []) {
  126. const currentPath = [...path, node.label];
  127. // 如果是 DEPARTMENT 节点
  128. if (node.deptType === 'DEPARTMENT') {
  129. if (includeFullData) {
  130. // 包含完整节点数据
  131. result.push({
  132. ...node,
  133. text: currentPath.join(' / '),
  134. value: node.id,
  135. path: currentPath,
  136. children: null
  137. });
  138. } else {
  139. // 只包含text和value
  140. result.push({
  141. text: currentPath.join(' / '),
  142. value: node.id
  143. });
  144. }
  145. }
  146. // 继续递归子节点
  147. if (node.children && Array.isArray(node.children)) {
  148. node.children.forEach(child => dfs(child, currentPath));
  149. }
  150. }
  151. tree.forEach(root => dfs(root));
  152. return result;
  153. }
  154. /**
  155. * 找出deptType为BRIGADE的节点
  156. * @param {Array} tree - 树形结构数据
  157. * @param {boolean} includeFullData - 是否包含节点的完整数据,默认false
  158. * @returns {Array} 包含所有BRIGADE节点的数组
  159. */
  160. export function buildBrigadeOptions(tree = [], includeFullData = false) {
  161. const result = [];
  162. function dfs(node, path = []) {
  163. const currentPath = [...path, node.label];
  164. // 如果是 DEPARTMENT 节点
  165. if (node.deptType === 'BRIGADE') {
  166. if (includeFullData) {
  167. // 包含完整节点数据
  168. result.push({
  169. ...node,
  170. text: currentPath.join(' / '),
  171. value: node.id,
  172. path: currentPath,
  173. children: null
  174. });
  175. } else {
  176. // 只包含text和value
  177. result.push({
  178. text: currentPath.join(' / '),
  179. value: node.id
  180. });
  181. }
  182. }
  183. // 继续递归子节点
  184. if (node.children && Array.isArray(node.children)) {
  185. node.children.forEach(child => dfs(child, currentPath));
  186. }
  187. }
  188. tree.forEach(root => dfs(root));
  189. return result;
  190. }
  191. /**
  192. * 找出deptType为BRIGADE的节点
  193. * @param {Array} tree - 树形结构数据
  194. * @param {boolean} includeFullData - 是否包含节点的完整数据,默认false
  195. * @returns {Array} 包含所有BRIGADE节点的数组
  196. */
  197. export function buildManagerOptions(tree = [], includeFullData = false) {
  198. const result = [];
  199. function dfs(node, path = []) {
  200. const currentPath = [...path, node.label];
  201. // 如果是 DEPARTMENT 节点
  202. if (node.deptType === 'MANAGER') {
  203. if (includeFullData) {
  204. // 包含完整节点数据
  205. result.push({
  206. ...node,
  207. text: currentPath.join(' / '),
  208. value: node.id,
  209. path: currentPath,
  210. children: null
  211. });
  212. } else {
  213. // 只包含text和value
  214. result.push({
  215. text: currentPath.join(' / '),
  216. value: node.id
  217. });
  218. }
  219. }
  220. // 继续递归子节点
  221. if (node.children && Array.isArray(node.children)) {
  222. node.children.forEach(child => dfs(child, currentPath));
  223. }
  224. }
  225. tree.forEach(root => dfs(root));
  226. return result;
  227. }
  228. //将数组格式的按照航站楼分成对象格式
  229. export function getHandleAreaData(data, notkezhang) {
  230. let louObj = {};
  231. let areaArr = [];
  232. data.forEach(element => {
  233. let name = `${element.terminlName}-${element.terminlCode}`
  234. if (!louObj[name]) {
  235. louObj[name] = [];
  236. }
  237. louObj[name].push({
  238. ...element,
  239. label: notkezhang ? element.channelName : element.regionalName,
  240. code: notkezhang ? element.channelCode : element.regionalCode,
  241. });
  242. });
  243. Object.keys(louObj).forEach(key => {
  244. areaArr.push({
  245. label: key.split('-')[0],
  246. code: key.split('-')[1],
  247. children: louObj[key]
  248. });
  249. });
  250. return areaArr;
  251. }
  252. // 封装上传
  253. export function uploadFile(event) {
  254. return new Promise((resolve, reject) => {
  255. uni.uploadFile({
  256. url: `${config.baseUrl}/common/upload`,
  257. filePath: event.tempFilePaths[0],
  258. name: 'file',
  259. header: { Authorization: 'Bearer ' + getToken() },
  260. success: (res) => resolve(JSON.parse(res.data)),
  261. fail: reject
  262. });
  263. });
  264. }
  265. // 为消息tab显示红点
  266. export async function showMessageTabRedDot() {
  267. try {
  268. const query = {
  269. pageNum: 1,
  270. pageSize: 9999
  271. };
  272. let total = 0
  273. let response = await listCheckPendingTasks(query);
  274. total += response.total;
  275. let response1 = await listCheckApprovalCcDetails(query);
  276. total += response1.rows.filter(item => item.isRead == '0').length;
  277. if (total > 0) {
  278. // 消息tab在tabBar列表中的索引是1(从0开始)
  279. uni.showTabBarRedDot({
  280. index: 1,
  281. success: () => {
  282. // console.log('消息tab红点显示成功')
  283. },
  284. fail: (err) => {
  285. // console.log('消息tab红点显示失败:', err)
  286. // 如果使用自定义tabBar时原生API失败,可以在这里添加自定义处理逻辑
  287. }
  288. })
  289. } else {
  290. // 当total等于0时,取消消息tab上的红点显示
  291. uni.hideTabBarRedDot({
  292. index: 1,
  293. success: () => {
  294. console.log('消息tab红点隐藏成功')
  295. },
  296. fail: (err) => {
  297. console.log('消息tab红点隐藏失败:', err)
  298. }
  299. })
  300. }
  301. } catch (error) {
  302. }
  303. }
  304. /**
  305. * 文字截断函数,超过指定长度显示省略号
  306. * @param {string} text - 需要截断的文本
  307. * @param {number} maxLength - 最大长度,默认10
  308. * @param {string} suffix - 后缀,默认'...'
  309. * @returns {string} 截断后的文本
  310. */
  311. export function truncateText(text, maxLength = 10, suffix = '...') {
  312. if (!text || typeof text !== 'string') {
  313. return '';
  314. }
  315. // 如果文本长度小于等于最大长度,直接返回原文本
  316. if (text.length <= maxLength) {
  317. return text;
  318. }
  319. // 截取文本并添加后缀
  320. return text.substring(0, maxLength) + suffix;
  321. }
  322. /**
  323. * 智能文字截断函数,考虑中英文混合情况
  324. * @param {string} text - 需要截断的文本
  325. * @param {number} maxLength - 最大长度(按字符数计算),默认10
  326. * @param {string} suffix - 后缀,默认'...'
  327. * @returns {string} 截断后的文本
  328. */
  329. export function smartTruncateText(text, maxLength = 10, suffix = '...') {
  330. if (!text || typeof text !== 'string') {
  331. return '';
  332. }
  333. // 计算字符数(中文字符算1个,英文字符算0.5个)
  334. let charCount = 0;
  335. let result = '';
  336. for (let i = 0; i < text.length; i++) {
  337. const char = text[i];
  338. // 中文字符范围
  339. if (char.charCodeAt(0) > 127) {
  340. charCount += 1;
  341. } else {
  342. charCount += 0.5;
  343. }
  344. // 如果超过最大长度,添加后缀并返回
  345. if (charCount > maxLength) {
  346. return result + suffix;
  347. }
  348. result += char;
  349. }
  350. // 如果文本长度小于等于最大长度,直接返回原文本
  351. return text;
  352. }
  353. /**
  354. * 按单词截断文本(适用于英文文本)
  355. * @param {string} text - 需要截断的文本
  356. * @param {number} maxWords - 最大单词数,默认5
  357. * @param {string} suffix - 后缀,默认'...'
  358. * @returns {string} 截断后的文本
  359. */
  360. export function truncateByWords(text, maxWords = 5, suffix = '...') {
  361. if (!text || typeof text !== 'string') {
  362. return '';
  363. }
  364. const words = text.trim().split(/\s+/);
  365. if (words.length <= maxWords) {
  366. return text;
  367. }
  368. return words.slice(0, maxWords).join(' ') + suffix;
  369. }
  370. /**
  371. * 根据字典值获取对应的字典文字
  372. * @param {string} dictType - 字典类型
  373. * @param {string|number} dictValue - 字典值
  374. * @param {string} defaultValue - 默认返回值,当找不到对应字典文字时返回
  375. * @returns {Promise<string>} 字典文字
  376. */
  377. export async function getDictLabelByValue(dictType, dictValue, defaultValue = '') {
  378. if (!dictType || dictValue === undefined || dictValue === null) {
  379. return defaultValue;
  380. }
  381. try {
  382. // 调用listData接口获取字典数据
  383. const response = await listData({
  384. dictType: dictType,
  385. dictValue: dictValue.toString()
  386. });
  387. // 如果接口返回成功且有数据
  388. if (response.code === 200 && response.rows && response.rows.length > 0) {
  389. return response.rows.find(item => item.dictValue === dictValue.toString())?.dictLabel || defaultValue;
  390. }
  391. return defaultValue;
  392. } catch (error) {
  393. console.error('获取字典文字失败:', error);
  394. return defaultValue;
  395. }
  396. }
  397. /**
  398. * 检查角色是否有访问特定路径的权限
  399. * @param {string} role - 角色名称
  400. * @param {string} path - 访问路径
  401. * @returns {boolean} 是否有权限
  402. */
  403. export function checkRolePermission(role, path) {
  404. // 角色权限配置对象
  405. const rolePermissions = {
  406. //安检员
  407. SecurityCheck: [
  408. '/pages/attendance/index',
  409. `/pages/seizedReported/index?params=${encodeURIComponent(JSON.stringify({ type: 'add' }))}`,
  410. '/pages/daily-exam/task-list/index',
  411. '/pages/eikonStatistics/index',
  412. '/pages/seizureRecord/index',
  413. '/pages/seizeStatistics/index',
  414. '/pages/voiceSubmissionDraft/index'
  415. ],
  416. //班组长
  417. banzuzhang: [
  418. '/pages/attendance/index',
  419. `/pages/seizedReported/index?params=${encodeURIComponent(JSON.stringify({ type: 'add' }))}`,
  420. '/pages/daily-exam/task-list/index',
  421. '/pages/inspectionChecklist/index',
  422. '/pages/eikonStatistics/index',
  423. '/pages/seizureRecord/index',
  424. '/pages/seizeStatistics/index',
  425. '/pages/inspectionStatistics/index',
  426. '/pages/questionStatistics/index',
  427. '/pages/voiceSubmissionDraft/index'
  428. ],
  429. //站长
  430. kezhang: [
  431. '/pages/attendance/index',
  432. '/pages/attendanceStatistics/index',
  433. '/pages/inspectionChecklist/index',
  434. '/pages/questionStatistics/index',
  435. '/pages/inspectionStatistics/index',
  436. '/pages/seizureRecord/index',
  437. '/pages/seizeStatistics/index',
  438. '/pages/eikonStatistics/index',
  439. '/pages/workProfile/index',
  440. '/pages/voiceSubmissionDraft/index'
  441. ],
  442. //站长
  443. test: [
  444. '/pages/attendanceStatistics/index',
  445. '/pages/inspectionChecklist/index',
  446. '/pages/questionStatistics/index',
  447. '/pages/inspectionStatistics/index',
  448. '/pages/seizureRecord/index',
  449. '/pages/seizeStatistics/index',
  450. '/pages/eikonStatistics/index',
  451. '/pages/workProfile/index',
  452. '/pages/voiceSubmissionDraft/index'
  453. ],
  454. zhijianke: [
  455. '/pages/attendanceStatistics/index',
  456. '/pages/inspectionChecklist/index',
  457. '/pages/questionStatistics/index',
  458. '/pages/inspectionStatistics/index',
  459. '/pages/seizureRecord/index',
  460. '/pages/seizeStatistics/index',
  461. '/pages/eikonStatistics/index',
  462. '/pages/workProfile/index',
  463. '/pages/voiceSubmissionDraft/index'
  464. ],
  465. };
  466. // 检查角色是否存在配置
  467. if (!rolePermissions[role]) {
  468. console.warn(`未找到角色 ${role} 的权限配置`);
  469. return false;
  470. }
  471. // 检查路径是否在角色的权限列表中
  472. return rolePermissions[role].includes(path);
  473. }