business_tms_program 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintrc-auto-import.json +113 -0
  3. package/.eslintrc.js +121 -0
  4. package/.prettierrc.js +9 -0
  5. package/.stylelintignore +4 -0
  6. package/README.md +43 -0
  7. package/components.d.ts +23 -0
  8. package/index.html +20 -0
  9. package/package.json +70 -0
  10. package/shims-uni.d.ts +10 -0
  11. package/src/App.vue +81 -0
  12. package/src/api/afterSale.ts +184 -0
  13. package/src/api/context.ts +26 -0
  14. package/src/api/device.ts +134 -0
  15. package/src/api/index.ts +80 -0
  16. package/src/api/installtion.ts +155 -0
  17. package/src/api/model/index.ts +15 -0
  18. package/src/api/model/userModel.ts +62 -0
  19. package/src/api/order.ts +49 -0
  20. package/src/api/system.ts +19 -0
  21. package/src/api/user.ts +171 -0
  22. package/src/auto-imports.d.ts +108 -0
  23. package/src/components/ConfirmDialog.vue +101 -0
  24. package/src/components/DaySelect.vue +212 -0
  25. package/src/components/Drawer.vue +104 -0
  26. package/src/components/DrawerSelect.vue +105 -0
  27. package/src/components/DropMenu.vue +144 -0
  28. package/src/components/Empty.vue +49 -0
  29. package/src/components/Loading.vue +41 -0
  30. package/src/components/RippleBtn.vue +159 -0
  31. package/src/components/SinglePick.vue +120 -0
  32. package/src/components/Skeleton.vue +43 -0
  33. package/src/components/Timeline.vue +85 -0
  34. package/src/components/Upload.vue +217 -0
  35. package/src/config/app.ts +32 -0
  36. package/src/config/env.ts +29 -0
  37. package/src/dict/afterSale.ts +161 -0
  38. package/src/dict/device.ts +29 -0
  39. package/src/dict/installtion.ts +141 -0
  40. package/src/dict/systems.ts +4 -0
  41. package/src/env.d.ts +8 -0
  42. package/src/hooks/useForm.ts +222 -0
  43. package/src/hooks/useUpload.ts +80 -0
  44. package/src/main.ts +8 -0
  45. package/src/manifest.json +39 -0
  46. package/src/pages/acceptance/DeviceInfo.vue +132 -0
  47. package/src/pages/acceptance/list.vue +276 -0
  48. package/src/pages/afterSale/DeviceInfo.vue +128 -0
  49. package/src/pages/afterSale/Step.vue +0 -0
  50. package/src/pages/afterSale/faultReport.vue +552 -0
  51. package/src/pages/afterSale/orderDetail.vue +327 -0
  52. package/src/pages/afterSale/orderFinish.vue +517 -0
  53. package/src/pages/afterSale/orderList.vue +305 -0
  54. package/src/pages/afterSale/returnVisit.vue +288 -0
  55. package/src/pages/afterSale/searchDeviceList.vue +148 -0
  56. package/src/pages/device/Search.vue +201 -0
  57. package/src/pages/device/acceptance.vue +270 -0
  58. package/src/pages/device/detail.vue +165 -0
  59. package/src/pages/device/index.vue +322 -0
  60. package/src/pages/device/info.vue +140 -0
  61. package/src/pages/device/list.vue +219 -0
  62. package/src/pages/device/materialTowerCode.vue +589 -0
  63. package/src/pages/device/searchList.vue +224 -0
  64. package/src/pages/installtion/Record.vue +145 -0
  65. package/src/pages/installtion/StatusTimeline.vue +85 -0
  66. package/src/pages/installtion/addAcceptance.vue +409 -0
  67. package/src/pages/installtion/addRecord.vue +338 -0
  68. package/src/pages/installtion/orderDetail.vue +220 -0
  69. package/src/pages/installtion/orderList.vue +100 -0
  70. package/src/pages/user/component/PersonAgree.vue +226 -0
  71. package/src/pages/user/component/PrivayAgree.vue +221 -0
  72. package/src/pages/user/component/SliderCode.vue +173 -0
  73. package/src/pages/user/forgetPassword.vue +249 -0
  74. package/src/pages/user/index.vue +139 -0
  75. package/src/pages/user/login.vue +342 -0
  76. package/src/pages/user/register.vue +348 -0
  77. package/src/pages/user/repassword.vue +329 -0
  78. package/src/pages/user/utils/mcaptcha.js +75 -0
  79. package/src/pages/user/utils/verifyCode.ts +41 -0
  80. package/src/pages/workspace/index.vue +225 -0
  81. package/src/pages.json +203 -0
  82. package/src/shime-uni.d.ts +6 -0
  83. package/src/static/icon/system/breeder_icon.png +0 -0
  84. package/src/static/icon/system/check.png +0 -0
  85. package/src/static/icon/system/factory_icon.png +0 -0
  86. package/src/static/icon/system/plus.png +0 -0
  87. package/src/static/icon/system/right.png +0 -0
  88. package/src/static/icon/system/unCheck.png +0 -0
  89. package/src/static/icon/tab/search.png +0 -0
  90. package/src/static/icon/tab/user.png +0 -0
  91. package/src/static/icon/tab/user_active.png +0 -0
  92. package/src/static/icon/tab/workspace.png +0 -0
  93. package/src/static/icon/tab/workspace_active.png +0 -0
  94. package/src/static/img/active_dot.png +0 -0
  95. package/src/static/img/afterSale_icon.png +0 -0
  96. package/src/static/img/check.png +0 -0
  97. package/src/static/img/close.png +0 -0
  98. package/src/static/img/confirm.png +0 -0
  99. package/src/static/img/empty.png +0 -0
  100. package/src/static/img/equipment_icon.png +0 -0
  101. package/src/static/img/fault_icon.png +0 -0
  102. package/src/static/img/install_icon.png +0 -0
  103. package/src/static/img/login_bg2.png +0 -0
  104. package/src/static/img/movable_right.png +0 -0
  105. package/src/static/img/navigation.png +0 -0
  106. package/src/static/img/psw_off.png +0 -0
  107. package/src/static/img/psw_on.png +0 -0
  108. package/src/static/img/scan.png +0 -0
  109. package/src/static/img/scan_icon.png +0 -0
  110. package/src/static/img/search.png +0 -0
  111. package/src/static/img/turn_right.png +0 -0
  112. package/src/static/img/unActive_dot.png +0 -0
  113. package/src/static/img/verifyBg.png +0 -0
  114. package/src/stores/index.ts +11 -0
  115. package/src/stores/modules/customer.ts +146 -0
  116. package/src/stores/modules/installtion.ts +30 -0
  117. package/src/stores/modules/system.ts +56 -0
  118. package/src/stores/modules/user.ts +133 -0
  119. package/src/stores/types.ts +16 -0
  120. package/src/stores/utils.ts +6 -0
  121. package/src/styles/index.less +63 -0
  122. package/src/types/chengyiApi.d.ts +36 -0
  123. package/src/types/index.d.ts +95 -0
  124. package/src/utils/address.ts +17 -0
  125. package/src/utils/cipher.ts +61 -0
  126. package/src/utils/form.ts +155 -0
  127. package/src/utils/httpEnum.ts +31 -0
  128. package/src/utils/image.ts +21 -0
  129. package/src/utils/index.ts +111 -0
  130. package/src/utils/request.ts +139 -0
  131. package/src/utils/requestCancelHandle.ts +67 -0
  132. package/stylelint.config.js +87 -0
  133. package/tsconfig.docs.json +11 -0
  134. package/tsconfig.json +30 -0
  135. package/typedoc.json +6 -0
  136. package/vite.config.ts +55 -0
@@ -0,0 +1,6 @@
1
+ export { store } from "@/stores";
2
+
3
+ export type {
4
+ systemStateType,
5
+ customerStateType
6
+ } from "./types";
@@ -0,0 +1,63 @@
1
+ @charset "UTF-8";
2
+ body {
3
+ height: 100%;
4
+ font-size: 28rpx;
5
+ }
6
+ // 定义省略号mixin(支持单行和多行)
7
+ .text-ellipsis() {
8
+ overflow: hidden;
9
+ text-overflow: ellipsis;
10
+ white-space: nowrap;
11
+ }
12
+
13
+ /* 添加全局盒模型 */
14
+ view, text {
15
+ box-sizing: border-box;
16
+ &::before,
17
+ &::after {
18
+ box-sizing: border-box;
19
+ }
20
+ }
21
+
22
+ // 1px
23
+ .hairline(@color: #e5e5e5, @position: bottom) {
24
+ position: relative;
25
+ &::after {
26
+ content: '';
27
+ position: absolute;
28
+ @{position}: 0;
29
+ left: 0;
30
+ width: 100%;
31
+ height: 1rpx;
32
+ background-color: @color;
33
+ transform: scaleY(0.5);
34
+ transform-origin: 0 0;
35
+ }
36
+ }
37
+ .content{
38
+ background-color: #F5F5F5;
39
+ min-height: 100vh;
40
+ }
41
+
42
+ .flex {
43
+ display: flex;
44
+ }
45
+ .align-center {
46
+ align-items: center;
47
+ }
48
+ .form-box{
49
+ background-color: #fff;
50
+ padding: 32rpx;
51
+ margin-bottom: 32rpx;
52
+ border-radius: 16rpx;
53
+ }
54
+ .noMore{
55
+ padding: 10rpx 0 30rpx 0;
56
+ font-size: 24rpx;
57
+ line-height: 52rpx;
58
+ color: #9e9e9e;
59
+ text-align: center;
60
+ }
61
+ /* 全局变量 */
62
+ @primary-color: #D2FADB;
63
+ @hodler-color: #f7f8fa;
@@ -0,0 +1,36 @@
1
+ // 请求参数
2
+ export interface RequestOptions {
3
+ isTransformResponse?: boolean;
4
+ isReturnNativeResponse?: boolean;
5
+ loading?: boolean;
6
+ // post请求的时候添加参数到url
7
+ joinParamsToUrl?: boolean;
8
+ // 请求头添加token
9
+ withToken?: boolean;
10
+ authenticationScheme?: string;
11
+ showResToast?: boolean;
12
+ autoCancel?: boolean;
13
+ requestId?: string;
14
+ rewriteUrl?: string;
15
+ permActionName?: string
16
+ }
17
+
18
+ // 分页参数
19
+ export interface FetchSetting {
20
+ // 请求接口当前页数
21
+ pageField: string;
22
+ // 每页显示多少条
23
+ sizeField: string;
24
+ // 请求结果列表字段 支持 a.b.c
25
+ listField: string;
26
+ // 请求结果总数字段 支持 a.b.c
27
+ totalField: string;
28
+ }
29
+
30
+ // 返回数据
31
+ export interface ResponseObject extends UniNamespace.RequestSuccessCallbackResult {
32
+ code: number,
33
+ data: AnyObject,
34
+ msg: string
35
+ }
36
+
@@ -0,0 +1,95 @@
1
+ // 此文件跟同级目录的 global.d.ts 文件一样也是全局类型声明,只不过这里存放一些零散的全局类型,无需引入直接在 .vue 、.ts 、.tsx 文件使用即可获得类型提示
2
+
3
+ type RefType<T> = T | null;
4
+
5
+ type EmitType = (event: string, ...args: any[]) => void;
6
+
7
+ type TargetContext = "_self" | "_blank";
8
+
9
+ type ComponentRef<T extends HTMLElement = HTMLDivElement> =
10
+ ComponentElRef<T> | null;
11
+
12
+ type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
13
+
14
+ type ForDataType<T> = {
15
+ [P in T]?: ForDataType<T[P]>;
16
+ };
17
+
18
+ type AnyFunction<T> = (...args: any[]) => T;
19
+
20
+ type PropType<T> = VuePropType<T>;
21
+
22
+ type Writable<T> = {
23
+ -readonly [P in keyof T]: T[P];
24
+ };
25
+
26
+ type Nullable<T> = T | null;
27
+
28
+ type NonNullable<T> = T extends null | undefined ? never : T;
29
+
30
+ type Recordable<T = any> = Record<string, T>;
31
+
32
+ type ReadonlyRecordable<T = any> = {
33
+ readonly [key: string]: T;
34
+ };
35
+
36
+ type Indexable<T = any> = {
37
+ [key: string]: T;
38
+ };
39
+
40
+ type DeepPartial<T> = {
41
+ [P in keyof T]?: DeepPartial<T[P]>;
42
+ };
43
+
44
+ type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
45
+
46
+ type Exclusive<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
47
+
48
+ type TimeoutHandle = ReturnType<typeof setTimeout>;
49
+
50
+ type IntervalHandle = ReturnType<typeof setInterval>;
51
+
52
+ type Effect = "light" | "dark";
53
+
54
+ interface ChangeEvent extends Event {
55
+ target: HTMLInputElement;
56
+ }
57
+
58
+ interface WheelEvent {
59
+ path?: EventTarget[];
60
+ }
61
+
62
+ interface ImportMetaEnv extends ViteEnv {
63
+ __: unknown;
64
+ }
65
+
66
+ interface Fn<T = any, R = T> {
67
+ (...arg: T[]): R;
68
+ }
69
+
70
+ interface PromiseFn<T = any, R = T> {
71
+ (...arg: T[]): Promise<R>;
72
+ }
73
+
74
+ interface ComponentElRef<T extends HTMLElement = HTMLDivElement> {
75
+ $el: T;
76
+ }
77
+
78
+ function parseInt(s: string | number, radix?: number): number;
79
+
80
+ function parseFloat(string: string | number): number;
81
+
82
+ type activeTab = 'customer' | 'user' | undefined; // 列表 | 用户
83
+
84
+ type UserType = 'factory' | 'breeder' | undefined; // 个体 | 企业
85
+
86
+ // 在文件顶部添加类型声明
87
+ declare module '@/store/system' {
88
+ export function useSystemStore(): {
89
+ activeTab: Ref<string>;
90
+ changeTab: (tab: string) => void;
91
+ };
92
+ }
93
+
94
+ // ISO 8601 格式的日期时间字符串类型
95
+ type ISOTime = `${string}T${string}Z`
@@ -0,0 +1,17 @@
1
+ type AddressObj = {
2
+ provinceName: string,
3
+ cityName: string,
4
+ areaName: string,
5
+ address: string
6
+ }
7
+
8
+ export const concactAddress = (addressObj: AddressObj) => {
9
+ if (!addressObj) return '';
10
+ const {
11
+ provinceName,
12
+ cityName,
13
+ areaName,
14
+ address
15
+ } = addressObj
16
+ return `${provinceName}${cityName}${areaName}${address}`
17
+ }
@@ -0,0 +1,61 @@
1
+ /*
2
+ * @Description: 通用加密
3
+ * @Author: xxw
4
+ * @Date: 2023-05-29 14:41:45
5
+ * @LastEditors: xxw
6
+ * @LastEditTime: 2023-05-29 14:43:45
7
+ */
8
+ import { decrypt, encrypt } from 'crypto-js/aes';
9
+ import UTF8, { parse } from 'crypto-js/enc-utf8';
10
+ import pkcs7 from 'crypto-js/pad-pkcs7';
11
+ import ECB from 'crypto-js/mode-ecb';
12
+ import md5 from 'crypto-js/md5';
13
+ import Base64 from 'crypto-js/enc-base64';
14
+
15
+ export interface EncryptionParams {
16
+ key: string;
17
+ iv: string;
18
+ }
19
+
20
+ export class AesEncryption {
21
+ private key;
22
+ private iv;
23
+
24
+ constructor(opt: Partial<EncryptionParams> = {}) {
25
+ const { key, iv } = opt;
26
+ if (key) {
27
+ this.key = parse(key);
28
+ }
29
+ if (iv) {
30
+ this.iv = parse(iv);
31
+ }
32
+ }
33
+
34
+ get getOptions() {
35
+ return {
36
+ mode: ECB,
37
+ padding: pkcs7,
38
+ iv: this.iv
39
+ };
40
+ }
41
+
42
+ encryptByAES(cipherText: string) {
43
+ return encrypt(cipherText, this.key, this.getOptions).toString();
44
+ }
45
+
46
+ decryptByAES(cipherText: string) {
47
+ return decrypt(cipherText, this.key, this.getOptions).toString(UTF8);
48
+ }
49
+ }
50
+
51
+ export function encryptByBase64(cipherText: string) {
52
+ return UTF8.parse(cipherText).toString(Base64);
53
+ }
54
+
55
+ export function decodeByBase64(cipherText: string) {
56
+ return Base64.parse(cipherText).toString(UTF8);
57
+ }
58
+
59
+ export function encryptByMd5(password: string) {
60
+ return md5(password).toString();
61
+ }
@@ -0,0 +1,155 @@
1
+ import { scrollIdPrefix } from "@/config/app"
2
+ import { nextTick, ref } from "vue";
3
+ // 已迁移至useForm.ts
4
+ export interface ValidationRule<T = any> {
5
+ required?: boolean;
6
+ pattern?: RegExp;
7
+ message?: string;
8
+ validatFunc?: (value: T) => boolean;
9
+ }
10
+
11
+ // 定义校验规则对象类型
12
+ export type ValidationRules<T> = {
13
+ [key in keyof T]: ValidationRule;
14
+ }
15
+
16
+ export const validateField = <T extends Record<string, any>>(
17
+ key: keyof T,
18
+ rule: ValidationRule<T[keyof T]>,
19
+ value: T[keyof T],
20
+ errState: Partial<Record<keyof T, string>>
21
+ ): boolean => {
22
+ let isValid = true;
23
+
24
+ // 重置当前字段的错误状态
25
+ errState[key] = '';
26
+
27
+ // 处理数组类型
28
+ if (Array.isArray(value)) {
29
+ if (rule.required && value.length === 0) {
30
+ errState[key] = rule.message;
31
+ isValid = false;
32
+ } else if (rule.validatFunc && !rule.validatFunc(value)) {
33
+ errState[key] = rule.message;
34
+ isValid = false;
35
+ }
36
+ } else {
37
+ // 处理字符串类型
38
+ const stringValue = value || '' as unknown as string;
39
+
40
+ // 必填校验
41
+ if (rule.required && !stringValue) {
42
+ errState[key] = rule.message;
43
+ isValid = false;
44
+ }
45
+
46
+ // 正则校验
47
+ if (rule.pattern && stringValue && !rule.pattern.test(stringValue)) {
48
+ errState[key] = rule.message;
49
+ isValid = false;
50
+ }
51
+
52
+ // 自定义校验函数
53
+ if (rule.validatFunc && !rule.validatFunc(stringValue as T[keyof T])) {
54
+ errState[key] = rule.message;
55
+ isValid = false;
56
+ }
57
+ }
58
+
59
+ return isValid;
60
+ };
61
+
62
+ export const formValidate = <T extends Record<string, any>>(
63
+ validationRules: ValidationRules<T>,
64
+ formData: T,
65
+ key?: keyof T // 可选参数,用于指定校验单个字段
66
+ ): [boolean, Record<keyof T, string>, keyof T | undefined] => {
67
+ const errState = {} as Record<keyof T, string>;
68
+ let isValid = true;
69
+ let firstErrorKey: keyof T | undefined;
70
+ if (key) {
71
+ // 校验单个字段
72
+ const rule = validationRules[key];
73
+ if (rule) {
74
+ isValid = validateField(key, rule, formData[key], errState);
75
+ }
76
+ } else {
77
+ // 校验整个表单
78
+ (Object.keys(validationRules) as Array<keyof T>).forEach(vKey => {
79
+ const rule = validationRules[vKey];
80
+ if (rule) {
81
+ const fieldValid = validateField(vKey, rule, formData[vKey], errState);
82
+ if (!fieldValid) {
83
+ isValid = false;
84
+ // 滚动到第一个错误的字段
85
+ if (!firstErrorKey) {
86
+ firstErrorKey = vKey;
87
+ }
88
+ }
89
+ }
90
+ });
91
+ }
92
+
93
+ return [isValid, errState, firstErrorKey];
94
+ };
95
+
96
+ // 小程序无法根据ref操作Dom, 且组件内uniapp会加属性前缀,新增一个独立滚动方法
97
+ export const scrollToFirstError = <T extends Record<string, any>>(
98
+ firstErrorKey: keyof T,
99
+ prefix: string = scrollIdPrefix,
100
+ ) => {
101
+ nextTick(() => {
102
+ uni.pageScrollTo({
103
+ selector: `#${prefix}${String(firstErrorKey)}`,
104
+ duration: 300,
105
+ offsetTop: -50,
106
+ });
107
+ });
108
+ };
109
+
110
+ export const createFormRefs = <T extends Record<string, any>>(keys: Array<keyof T>) => {
111
+ return keys.reduce((acc, key) => {
112
+ acc[key] = ref(null);
113
+ return acc;
114
+ }, {} as Record<keyof T, any>);
115
+ };
116
+
117
+ export const REGEXP_PWD =
118
+ /^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*\d)|(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*])|(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])|(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*])).{8,20}$/;
119
+
120
+ export const validatePhone = (value: any): any => {
121
+ return new Promise((resolve, reject) => {
122
+ if (value === "") {
123
+ reject("请输入");
124
+ } else if (!/^1[3-9]\d{9}$/.test(value)) {
125
+ reject("手机号格式不正确");
126
+ } else {
127
+ resolve(true);
128
+ }
129
+ })
130
+ }
131
+ export const validatePsw = (value: any): any => {
132
+ return new Promise((resolve, reject) => {
133
+ if (!value) {
134
+ reject("请输入");
135
+ } else if (!REGEXP_PWD.test(value)) {
136
+ reject("密码格式应为8-18位数字、大小写字母、符号的任意三种组合");
137
+ } else {
138
+ resolve(true);
139
+ }
140
+ }
141
+ );
142
+ }
143
+
144
+ export const verifyCodeRule = (value: any): any => {
145
+ return new Promise((resolve, reject) => {
146
+ if (value === "") {
147
+ reject("请输入验证码");
148
+ } else if (!/^\d{6}$/.test(value)) {
149
+ reject("验证码格式不正确");
150
+ } else {
151
+ resolve(true);
152
+ }
153
+ }
154
+ );
155
+ }
@@ -0,0 +1,31 @@
1
+ export enum ResultEnum {
2
+ SUCCESS = 200,
3
+ SUCCESS2 = 0,
4
+ ERROR = 500,
5
+ Unauthorized = 10001,
6
+ TYPE = 'success'
7
+ }
8
+
9
+ export const unauthorizedCodes = [10001, 10002, 10003, 10004, 10005, 10006, 10008];
10
+ /**
11
+ * @description: request method
12
+ */
13
+ export enum RequestEnum {
14
+ GET = 'GET',
15
+ POST = 'POST',
16
+ PUT = 'PUT',
17
+ DELETE = 'DELETE'
18
+ }
19
+
20
+ /**
21
+ * @description: contentType
22
+ */
23
+ export enum ContentTypeEnum {
24
+ // json
25
+ JSON = 'application/json;charset=UTF-8',
26
+ // form-data qs
27
+ FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
28
+ // form-data upload
29
+ FORM_DATA = 'multipart/form-data;charset=UTF-8'
30
+ }
31
+
@@ -0,0 +1,21 @@
1
+ // 图片转base64
2
+ function image2Base64(img: HTMLImageElement) {
3
+ const canvas = document.createElement('canvas');
4
+ canvas.width = img.width;
5
+ canvas.height = img.height;
6
+ const ctx = canvas.getContext('2d');
7
+ ctx?.drawImage(img, 0, 0, img.width, img.height);
8
+ const dataURL = canvas.toDataURL('image/png');
9
+ return dataURL;
10
+ }
11
+
12
+ export function getImgBase64(imageSrc: string, cb: (s: string) => void) {
13
+ let base64 = '';
14
+ const img = new Image();
15
+ img.src = imageSrc;
16
+ img.onload = function () {
17
+ base64 = image2Base64(img);
18
+ cb(base64);
19
+ };
20
+ }
21
+
@@ -0,0 +1,111 @@
1
+
2
+ // 版本检测逻辑
3
+ export const checkSDKVersion = () => {
4
+ try {
5
+ const systemInfo = uni.getSystemInfoSync()
6
+ const SDKVersion = systemInfo.SDKVersion || '1.0.0' // 微信小程序特有属性
7
+ const minVersion = '2.19.0' // 你的最低支持版本
8
+
9
+ if (compareVersion(SDKVersion, minVersion) < 0) {
10
+ uni.showModal({
11
+ title: '版本过低提示',
12
+ content: `当前客户端版本过低(${SDKVersion}),请升级后使用`,
13
+ confirmText: '立即更新',
14
+ success(res) {
15
+ if (res.confirm) {
16
+ uni.navigateToMiniProgram({
17
+ appId: 'wx...' // 你的小程序appid
18
+ })
19
+ }
20
+ }
21
+ })
22
+ return false
23
+ }
24
+ return true
25
+ } catch(e) {
26
+ console.error('版本检测失败', e)
27
+ return true
28
+ }
29
+ }
30
+
31
+ // 版本号比较函数
32
+ export const compareVersion = (v1: string, v2: string) => {
33
+ const v1Arr = v1.split('.').map(Number)
34
+ const v2Arr = v2.split('.').map(Number)
35
+ const len = Math.max(v1Arr.length, v2Arr.length)
36
+
37
+ for (let i = 0; i < len; i++) {
38
+ const num1 = v1Arr[i] || 0
39
+ const num2 = v2Arr[i] || 0
40
+ if (num1 > num2) return 1
41
+ if (num1 < num2) return -1
42
+ }
43
+ return 0
44
+ }
45
+
46
+ /**
47
+ * 将对象转为url参数
48
+ * @param baseUrl 需要拼接的url
49
+ * @param obj 要拼接的对象
50
+ * @returns {string}
51
+ * eg:
52
+ * let obj = {a: '3', b: '4'}
53
+ * setObjToUrlParams('www.baidu.com', obj)
54
+ * ==>www.baidu.com?a=3&b=4
55
+ */
56
+ export function setObjToUrlParams(baseUrl: string, obj: any): string {
57
+ let parameters = '';
58
+ for (const key in obj) {
59
+ parameters += `${key}=${encodeURIComponent(obj[key])}&`;
60
+ }
61
+ parameters = parameters.replace(/&$/, '');
62
+ return /\?$/.test(baseUrl)
63
+ ? baseUrl + parameters
64
+ : baseUrl.replace(/\/?$/, '?') + parameters;
65
+ }
66
+
67
+ export function getDate(date_text : string = 'day', type ?: string) : string {
68
+ const date = new Date();
69
+
70
+ let year : string | number = date.getFullYear();
71
+ let month : string | number = date.getMonth() + 1;
72
+ let day : string | number = date.getDate();
73
+
74
+ if (type == 'start') {
75
+ day = day - 10;
76
+ } else if (type == 'end') {
77
+ day = day + 10;
78
+ }
79
+ month = month > 9 ? month : '0' + month;;
80
+ day = day > 9 ? day : '0' + day;
81
+ if (date_text == 'month') {
82
+ return `${year}-${month}`;
83
+ } else if (date_text == 'year') {
84
+ return `${year}`;
85
+ }
86
+ return `${year}-${month}-${day}`;
87
+ }
88
+
89
+ export function generateUUID() {
90
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
91
+ const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
92
+ return v.toString(16);
93
+ });
94
+ }
95
+
96
+ /**
97
+ * 格式化时间为 YYYY-MM-DD hh:mm:ss 格式
98
+ * @param date 可以是 Date 对象或时间字符串
99
+ */
100
+ export function formatDateTime(date: Date | string): string {
101
+ const d = date instanceof Date ? date : new Date(date);
102
+
103
+ const year = d.getFullYear();
104
+ const month = String(d.getMonth() + 1).padStart(2, '0');
105
+ const day = String(d.getDate()).padStart(2, '0');
106
+ const hours = String(d.getHours()).padStart(2, '0');
107
+ const minutes = String(d.getMinutes()).padStart(2, '0');
108
+ const seconds = String(d.getSeconds()).padStart(2, '0');
109
+
110
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
111
+ }