common.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. import { getToken } from './auth';
  2. // 定义类型接口
  3. interface VipOptions {
  4. vipReviewStatus: string;
  5. vipEndDate: string;
  6. vipLevelName: string;
  7. vipLevel: number;
  8. }
  9. interface VipResult {
  10. isVip: boolean;
  11. text: string;
  12. level?: number;
  13. }
  14. interface StoreModule {
  15. dispatch: (action: string, payload?: any) => Promise<any>;
  16. state: any;
  17. }
  18. interface LocationResult {
  19. name: string;
  20. address: string;
  21. latitude: number;
  22. longitude: number;
  23. }
  24. /**
  25. * 显示消息提示框
  26. * @param content 提示的标题
  27. */
  28. export function toast(content: string): void {
  29. uni.showToast({
  30. icon: 'none',
  31. title: content
  32. });
  33. }
  34. export function isChinese(text: string): boolean {
  35. const pattern = /[\u4E00-\u9FA5\uF900-\uFA2D]/;
  36. return pattern.test(text);
  37. }
  38. /**
  39. * 显示模态弹窗
  40. * @param content 提示的标题
  41. */
  42. export function showConfirm(content: string): Promise<UniApp.ShowModalRes> {
  43. return new Promise((resolve, reject) => {
  44. uni.showModal({
  45. title: '提示',
  46. content: content,
  47. cancelText: '取消',
  48. confirmText: '确定',
  49. success: function (res) {
  50. resolve(res);
  51. }
  52. });
  53. });
  54. }
  55. /**
  56. * 参数处理
  57. * @param params 参数
  58. */
  59. export function tansParams(params: Record<string, any>): string {
  60. let result = '';
  61. for (const propName of Object.keys(params)) {
  62. const value = params[propName];
  63. const part = encodeURIComponent(propName) + '=';
  64. if (value !== null && value !== '' && typeof value !== 'undefined') {
  65. if (typeof value === 'object') {
  66. for (const key of Object.keys(value)) {
  67. if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
  68. const params = propName + '[' + key + ']';
  69. const subPart = encodeURIComponent(params) + '=';
  70. result += subPart + encodeURIComponent(value[key]) + '&';
  71. }
  72. }
  73. } else {
  74. result += part + encodeURIComponent(value) + '&';
  75. }
  76. }
  77. }
  78. return result;
  79. }
  80. /**
  81. * 更新当前用户信息
  82. */
  83. export const updateUserInfo = async (
  84. store: StoreModule,
  85. storeType: string[] = ['user', 'cpy', 'cpyLi', 'vip', 'card']
  86. ): Promise<void> => {
  87. let res: any = null;
  88. if (storeType.includes('user')) {
  89. res = await store.dispatch('getUserInfoBytoken');
  90. }
  91. if (storeType.includes('cpy')) {
  92. res?.data?.currentCpyid && (await store.dispatch('cpyDetail', res?.data?.currentCpyid));
  93. res?.data?.currentCpyid && (await store.dispatch('memberAuditCount', res?.data?.currentCpyid));
  94. }
  95. if (storeType.includes('cpyLi')) {
  96. await store.dispatch('getMyCpyList');
  97. }
  98. if (storeType.includes('vip')) {
  99. // 判断是否申请过会员
  100. +store.state.cpy?.cpyInfo?.extraInfo?.vipApply && (await store.dispatch('vip/vipDetail'));
  101. }
  102. if (storeType.includes('card')) {
  103. // 获取当前名片信息
  104. await store.dispatch('getCurrentCard');
  105. }
  106. };
  107. // 判断是否是会员并且会员是否过期
  108. export function isVip(options: VipOptions | null): VipResult {
  109. if (!options) {
  110. return {
  111. isVip: false,
  112. text: '非会员单位'
  113. };
  114. }
  115. const { vipReviewStatus, vipEndDate, vipLevelName, vipLevel } = options;
  116. if (vipReviewStatus !== '1') {
  117. return {
  118. isVip: false,
  119. text: '非会员单位'
  120. };
  121. } else {
  122. const now = new Date().getTime();
  123. const end = new Date(vipEndDate).getTime();
  124. if (now > end) {
  125. return {
  126. isVip: false,
  127. text: '非会员单位',
  128. level: vipLevel
  129. };
  130. } else {
  131. return {
  132. isVip: true,
  133. text: vipLevelName,
  134. level: vipLevel
  135. };
  136. }
  137. }
  138. }
  139. // 返回上一页失败返回首页
  140. export function navigateBackOrHome(): void {
  141. const pages = getCurrentPages();
  142. if (pages.length === 1) {
  143. uni.switchTab({
  144. url: '/pages/index/index'
  145. });
  146. } else {
  147. uni.navigateBack();
  148. }
  149. }
  150. // 提示uni.showToast
  151. export function showToast(title: string): void {
  152. uni.showToast({
  153. icon: 'none',
  154. title
  155. });
  156. }
  157. // 保存图片临时路径
  158. export function saveImagePath(url: string): void {
  159. uni.saveImageToPhotosAlbum({
  160. filePath: url,
  161. success: function () {
  162. uni.showToast({
  163. title: '保存成功',
  164. icon: 'success'
  165. });
  166. },
  167. fail: function () {
  168. uni.showToast({
  169. title: '保存失败',
  170. icon: 'none'
  171. });
  172. }
  173. });
  174. }
  175. // 分享图片临时路径
  176. export function shareImagePath(url: string): void {
  177. uni.saveImageToPhotosAlbum({
  178. filePath: url,
  179. success: function () {
  180. uni.showToast({
  181. title: '分享成功',
  182. icon: 'success'
  183. });
  184. },
  185. fail: function () {
  186. uni.showToast({
  187. title: '分享失败',
  188. icon: 'none'
  189. });
  190. }
  191. });
  192. }
  193. // 根据截止时间计算剩余多少天 如果为负数则返回0
  194. export function getRemainingDays(endTime: string | Date): number {
  195. const now = new Date().getTime();
  196. const end = new Date(endTime).getTime();
  197. const remainingTime = end - now;
  198. if (remainingTime < 0) {
  199. return 0;
  200. } else {
  201. return Math.floor(remainingTime / (1000 * 60 * 60 * 24));
  202. }
  203. }
  204. // 图片预览
  205. export function uniPreviewImage(url: string): void {
  206. uni.previewImage({
  207. urls: [url],
  208. current: url
  209. });
  210. }
  211. export const emitBus = (bus: string, data: any = null): void => {
  212. uni.$emit(bus, data);
  213. };
  214. // 播放语音
  215. export function playVoice(url: string): UniApp.InnerAudioContext {
  216. const audio = uni.createInnerAudioContext();
  217. audio.src = url;
  218. audio.onPlay(() => {
  219. console.log('开始播放');
  220. });
  221. audio.onError((res) => {
  222. console.log('播放失败', res);
  223. });
  224. return audio;
  225. }
  226. // 选择地址判断是否授权,如果授权则返回地址信息,否则引导授权 uni.chooseLocation
  227. export function chooseAddress(): Promise<LocationResult> {
  228. return new Promise((resolve, reject) => {
  229. uni.chooseLocation({
  230. success: (res) => {
  231. resolve(res as LocationResult);
  232. },
  233. fail: (err) => {
  234. if (err.errMsg.includes('chooseLocation:fail auth deny')) {
  235. uni.showModal({
  236. title: '提示',
  237. content: '请授权地理位置权限后再试',
  238. showCancel: false,
  239. success: () => {
  240. // 引导用户去设置页面开启权限
  241. uni.openSetting({
  242. success: (settingRes) => {
  243. if (settingRes.authSetting['scope.userLocation']) {
  244. // 用户授权成功后再次调用选择地址
  245. uni.chooseLocation({
  246. success: (res) => {
  247. resolve(res as LocationResult);
  248. },
  249. fail: (err) => {
  250. reject(err);
  251. }
  252. });
  253. } else {
  254. reject(new Error('用户未授权地理位置权限'));
  255. }
  256. }
  257. });
  258. }
  259. });
  260. } else {
  261. reject(err);
  262. }
  263. }
  264. });
  265. });
  266. }
  267. // 需要token跳转页面
  268. export function navigateToWithToken(url: string): void {
  269. if (!getToken()) {
  270. uni.$u.route({
  271. type: 'reLaunch',
  272. url: '/pages/login/login',
  273. params: {
  274. redirect: encodeURIComponent(url)
  275. }
  276. });
  277. return;
  278. }
  279. uni.$u.route({
  280. type: 'navigateTo',
  281. url: url
  282. });
  283. }
  284. // 判断开启微信小程序权限功能,如果开启则返回true,否则先引导开启
  285. export const isOpenSetting = async (scope?: string): Promise<boolean> => {
  286. // #ifdef MP-WEIXIN
  287. try {
  288. if (!scope || typeof scope !== 'string') {
  289. return true;
  290. }
  291. const hasAuth = await new Promise<boolean>((resolve) => {
  292. uni.getSetting({
  293. success: (res) => {
  294. resolve(!!(res.authSetting && (res.authSetting as any)[scope as string]));
  295. },
  296. fail: () => resolve(false)
  297. });
  298. });
  299. if (hasAuth) return true;
  300. const authorized = await new Promise<boolean>((resolve) => {
  301. uni.authorize({
  302. scope,
  303. success: () => resolve(true),
  304. fail: () => resolve(false)
  305. });
  306. });
  307. if (authorized) return true;
  308. const goSetting = await new Promise<boolean>((resolve) => {
  309. uni.showModal({
  310. title: '提示',
  311. content: '请打开手机自身定位并且点击右上角三个点,进入设置,允许小程序获取定位,并选择您的位置。',
  312. confirmText: '去设置',
  313. success: (mRes: UniApp.ShowModalRes) => resolve(!!mRes.confirm),
  314. fail: () => resolve(false)
  315. });
  316. });
  317. if (!goSetting) return false;
  318. const finalAuth = await new Promise<boolean>((resolve) => {
  319. uni.openSetting({
  320. success: (setRes) => {
  321. resolve(!!(setRes.authSetting && (setRes.authSetting as any)[scope as string]));
  322. },
  323. fail: () => resolve(false)
  324. });
  325. });
  326. return !!finalAuth;
  327. } catch (e) {
  328. return false;
  329. }
  330. // #endif
  331. // 非微信小程序平台默认返回可用
  332. return true;
  333. }
  334. // 根据传入url获取文件后缀名,根据文件后缀名返回相应的图片icon
  335. export const getFileIconByUrl = (url: string) => {
  336. const fileExtension = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
  337. const iconMap = {
  338. jpg: 'jpg',
  339. jpeg: 'jpg',
  340. png: 'png',
  341. gif: 'jpg',
  342. pdf: 'pdf',
  343. doc: 'doc',
  344. docx: 'doc',
  345. xls: 'xlsx',
  346. xlsx: 'xlsx',
  347. txt: 'txt',
  348. // 大写后缀映射
  349. JPG: 'jpg',
  350. JPEG: 'jpg',
  351. PNG: 'png',
  352. GIF: 'jpg',
  353. PDF: 'pdf',
  354. DOC: 'doc',
  355. DOCX: 'doc',
  356. XLS: 'xlsx',
  357. XLSX: 'xlsx',
  358. TXT: 'txt'
  359. };
  360. return `https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images/file-type-sub/${iconMap?.[fileExtension] || 'def'}.png`; // 默认图标
  361. };