@smart100/spu-web-plugin 0.0.1
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.
- package/dist/spu-web-plugin.mjs +14 -0
- package/package.json +51 -0
- package/src/AMapLoader.ts +46 -0
- package/src/axios.ts +144 -0
- package/src/cloudServ.ts +121 -0
- package/src/index.ts +31 -0
- package/src/install.ts +88 -0
- package/src/loadding/img/loading.gif +0 -0
- package/src/loadding/index.ts +83 -0
- package/src/loadding/index.vue +43 -0
- package/src/location.ts +187 -0
- package/src/login.ts +248 -0
- package/src/oss/downloadService.ts +192 -0
- package/src/oss/index.ts +8 -0
- package/src/oss/multiUpload.ts +129 -0
- package/src/oss/servtoken.ts +131 -0
- package/src/oss/uploadService.ts +145 -0
- package/src/package/ali-oss/aliyun-oss-sdk.apaas.js +25198 -0
- package/src/package/ali-oss/aliyun-oss-sdk.apaas.min.js +15 -0
- package/src/package/ali-oss/aliyun-oss-sdk.js +25168 -0
- package/src/package/ali-oss/aliyun-oss-sdk.min.js +14 -0
- package/src/package/ali-oss/package.json +162 -0
- package/src/package/huaweicloud-obs/esdk-obs-browserjs-without-polyfill.3.22.3.min.js +2 -0
- package/src/package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js +2 -0
- package/src/package/huaweicloud-obs/package.json +28 -0
- package/src/storageProxy.ts +47 -0
- package/src/tenantInfo.ts +76 -0
- package/src/types/index.d.ts +84 -0
- package/src/types/shims-lib.d.ts +37 -0
- package/src/urlquery.ts +53 -0
- package/src/utils.ts +20 -0
package/src/location.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import AMapLoader from './AMapLoader'
|
|
2
|
+
import { cloneDeep } from 'lodash-es'
|
|
3
|
+
import urlquery from './urlquery'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
type Location = {
|
|
7
|
+
longitude: string;
|
|
8
|
+
latitude: string;
|
|
9
|
+
address: string;
|
|
10
|
+
[propName: string]: any;
|
|
11
|
+
} | null
|
|
12
|
+
|
|
13
|
+
let AMap: any = null
|
|
14
|
+
let geocoder: any = null
|
|
15
|
+
let geolocation: any = null
|
|
16
|
+
let datetime: number | null = null
|
|
17
|
+
let lastLocation: Location = null
|
|
18
|
+
let runing = false
|
|
19
|
+
let locationPromise: Promise<Location>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const init = async () => {
|
|
23
|
+
if (!AMap) {
|
|
24
|
+
AMap = await AMapLoader.load({
|
|
25
|
+
plugins: ['AMap.Geolocation', 'AMap.Geocoder']
|
|
26
|
+
})
|
|
27
|
+
geocoder = new AMap.Geocoder({
|
|
28
|
+
city: '',
|
|
29
|
+
radius: 500
|
|
30
|
+
})
|
|
31
|
+
geolocation = new AMap.Geolocation({
|
|
32
|
+
enableHighAccuracy: true,
|
|
33
|
+
timeout: 3000
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getAmapLocation = async (): Promise<Location> => {
|
|
39
|
+
await init()
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
geolocation.getCurrentPosition((status: string, result: any) => {
|
|
42
|
+
if (status === 'complete') {
|
|
43
|
+
const { lng, lat } = result.position
|
|
44
|
+
// console.log('getAmapLocation success')
|
|
45
|
+
resolve({
|
|
46
|
+
longitude: lng.toString(),
|
|
47
|
+
latitude: lat.toString(),
|
|
48
|
+
address: ''
|
|
49
|
+
})
|
|
50
|
+
} else {
|
|
51
|
+
// reject(new Error('getAmapLocation fail'))
|
|
52
|
+
console.error('getAmapLocation fail')
|
|
53
|
+
resolve(null)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const getSpuLocation = async (): Promise<Location> => {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
window.Native.getLocation((result: any, error: any, status: any) => {
|
|
62
|
+
// console.log('getLocation result', result)
|
|
63
|
+
// console.log('getLocation error', error)
|
|
64
|
+
// console.log('getLocation status', status)
|
|
65
|
+
if (result && result?.longitude && result?.latitude) {
|
|
66
|
+
resolve({
|
|
67
|
+
longitude: result.longitude.toString(),
|
|
68
|
+
latitude: result.latitude.toString(),
|
|
69
|
+
address: result.address || ''
|
|
70
|
+
})
|
|
71
|
+
} else {
|
|
72
|
+
console.error('getSpuLocation fail')
|
|
73
|
+
resolve(null)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const getAmapCityLocation = async (): Promise<Location> => {
|
|
80
|
+
await init()
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
geolocation.getCityInfo((status: string, result: any) => {
|
|
83
|
+
if (status === 'complete') {
|
|
84
|
+
const lng = result.position[0].toString()
|
|
85
|
+
const lat = result.position[1].toString()
|
|
86
|
+
// console.log('getAmapCityLocation success')
|
|
87
|
+
// resolve([lng, lat])
|
|
88
|
+
resolve({
|
|
89
|
+
longitude: lng.toString(),
|
|
90
|
+
latitude: lat.toString(),
|
|
91
|
+
address: ''
|
|
92
|
+
})
|
|
93
|
+
} else {
|
|
94
|
+
// reject(new Error('getAmapCityLocation fail'))
|
|
95
|
+
console.error('getAmapCityLocation fail')
|
|
96
|
+
resolve(null)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const getAddress = async (position: Location): Promise<string> => {
|
|
103
|
+
await init()
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
if (position) {
|
|
106
|
+
geocoder.getAddress([position.longitude, position.latitude], (status: string, result: any) => {
|
|
107
|
+
if (status === 'complete' && result.regeocode) {
|
|
108
|
+
resolve(result.regeocode.formattedAddress)
|
|
109
|
+
} else {
|
|
110
|
+
// reject(new Error('getAddress fail'))
|
|
111
|
+
console.error('getAddress fail')
|
|
112
|
+
resolve('')
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 定位流程: 缓存 > 判断环境(APP,小程序,企微)基于环境获取定位 > 高德地图高精度定位 > 百度地图定位 > 高德城市定位
|
|
120
|
+
const getLocationPromise = async (): Promise<Location> => {
|
|
121
|
+
let location: Location = null
|
|
122
|
+
|
|
123
|
+
// 在 SPU 容器里使用 Native-API 的定位
|
|
124
|
+
if (window?.Native?.getLocation) {
|
|
125
|
+
location = await getSpuLocation()
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 高德定位
|
|
129
|
+
if (!location) {
|
|
130
|
+
location = await getAmapLocation()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 城市定位结果不精确 仅在开发模式下使用
|
|
134
|
+
// if (!location && process.env.NODE_ENV !== 'production') {
|
|
135
|
+
if (!location && urlquery.isvirtuallocation) {
|
|
136
|
+
location = await getAmapCityLocation()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 测试虚拟定位
|
|
140
|
+
if (!location && urlquery.isvirtuallocation) {
|
|
141
|
+
location = {
|
|
142
|
+
longitude: '113.34331353081598',
|
|
143
|
+
latitude: '23.105349663628473',
|
|
144
|
+
address: ''
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (location && !location.address) {
|
|
149
|
+
location.address = await getAddress(location) || '经纬度获取成功,但地址获取失败。'
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return location
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
const getLocation = async () => {
|
|
157
|
+
await init()
|
|
158
|
+
// debugger
|
|
159
|
+
// 缓存30秒
|
|
160
|
+
if (datetime && Date.now() - datetime <= 30000 && lastLocation && !runing) {
|
|
161
|
+
return cloneDeep(lastLocation)
|
|
162
|
+
}
|
|
163
|
+
// 兼容同时间发起多个
|
|
164
|
+
if (runing && locationPromise) {
|
|
165
|
+
return locationPromise
|
|
166
|
+
}
|
|
167
|
+
// console.log('runing')
|
|
168
|
+
runing = true
|
|
169
|
+
locationPromise = getLocationPromise()
|
|
170
|
+
const locationRes = await locationPromise
|
|
171
|
+
runing = false
|
|
172
|
+
if (locationRes) {
|
|
173
|
+
datetime = Date.now()
|
|
174
|
+
lastLocation = locationRes
|
|
175
|
+
}
|
|
176
|
+
return locationRes
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const getDistance = async (p1: [number, number], p2: [number, number]) => {
|
|
180
|
+
await init()
|
|
181
|
+
return AMap.GeometryUtil.distance(p1, p2)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
getLocation,
|
|
186
|
+
getDistance
|
|
187
|
+
}
|
package/src/login.ts
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash-es'
|
|
2
|
+
import jwtDecode from 'jwt-decode'
|
|
3
|
+
import { apaasAxios } from './axios'
|
|
4
|
+
import tenantInfo from './tenantInfo'
|
|
5
|
+
import { lsProxy } from './storageProxy'
|
|
6
|
+
|
|
7
|
+
type JwtResult = {
|
|
8
|
+
LoginUser: IAny
|
|
9
|
+
exp: number
|
|
10
|
+
} | null
|
|
11
|
+
|
|
12
|
+
class Login {
|
|
13
|
+
private cache: IAny = {}
|
|
14
|
+
|
|
15
|
+
private getData (key: string) {
|
|
16
|
+
if (this.cache[key]) {
|
|
17
|
+
return this.cache[key]
|
|
18
|
+
} else {
|
|
19
|
+
const data = lsProxy.getItem(key)
|
|
20
|
+
this.cache[key] = data
|
|
21
|
+
return data
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private setData (key: string, value: any) {
|
|
26
|
+
this.cache[key] = value
|
|
27
|
+
lsProxy.setItem(key, value)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private removeData (key: string) {
|
|
31
|
+
delete this.cache[key]
|
|
32
|
+
lsProxy.removeItem(key)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getEnvname () {
|
|
36
|
+
return this.getData('envname')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setEnvname (value: string) {
|
|
40
|
+
this.setData('envname', value)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
removeEnvname () {
|
|
44
|
+
this.removeData('envname')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getToken () {
|
|
48
|
+
return this.getData('token')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setToken (value: string) {
|
|
52
|
+
this.setData('token', value)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
removeToken () {
|
|
56
|
+
this.removeData('token')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getTokenExpires () {
|
|
60
|
+
return this.getData('tokenexpires')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setTokenExpires (value: string) {
|
|
64
|
+
this.setData('tokenexpires', value)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
removeTokenExpires () {
|
|
68
|
+
this.removeData('tokenexpires')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getRefreshToken () {
|
|
72
|
+
return this.getData('refreshtoken')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setRefreshToken (value: string) {
|
|
76
|
+
this.setData('refreshtoken', value)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
removeRefreshToken () {
|
|
80
|
+
this.removeData('refreshtoken')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private updateToken () {
|
|
84
|
+
return apaasAxios.get('/api/auth/refreshtoken', {
|
|
85
|
+
params: {
|
|
86
|
+
refreshtoken: this.getRefreshToken()
|
|
87
|
+
},
|
|
88
|
+
isShowLoadding: false,
|
|
89
|
+
isShowErrorMessage: false
|
|
90
|
+
}).then((res: any) => {
|
|
91
|
+
// console.log(res)
|
|
92
|
+
const data = res?.data
|
|
93
|
+
if (data) {
|
|
94
|
+
this.setToken(data.token)
|
|
95
|
+
this.setRefreshToken(data.refreshtoken)
|
|
96
|
+
this.setTokenExpires(data.tokenexpires)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private refreshtokenTimer: number | null = null
|
|
102
|
+
|
|
103
|
+
startRefreshtoken () {
|
|
104
|
+
// 如果有登录 则过期前15秒更新token
|
|
105
|
+
// 如果没登录 每隔1分钟走token更新逻辑(如果刚开始没登录 后面才登录【不需要再在登陆后写刷新token逻辑】)
|
|
106
|
+
this.stopRefreshtoken()
|
|
107
|
+
const time = this.checkLogin() ? (Number(this.getTokenExpires()) - Date.now() - 1000 * 15) : (1000 * 60)
|
|
108
|
+
// const time = 5000
|
|
109
|
+
if (time > 0) {
|
|
110
|
+
this.refreshtokenTimer = window.setTimeout(async () => {
|
|
111
|
+
if (this.checkLogin()) {
|
|
112
|
+
await this.updateToken()
|
|
113
|
+
}
|
|
114
|
+
this.startRefreshtoken()
|
|
115
|
+
}, time)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private stopRefreshtoken () {
|
|
120
|
+
clearTimeout(this.refreshtokenTimer as number)
|
|
121
|
+
this.refreshtokenTimer = null
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
getUser (key?: string): any {
|
|
125
|
+
const user = this.getData('user')
|
|
126
|
+
const userObj = user ? JSON.parse(user) : null
|
|
127
|
+
if (!key) {
|
|
128
|
+
return userObj
|
|
129
|
+
} else {
|
|
130
|
+
return userObj ? (userObj[key] || '') : ''
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
setUser (value: string | IAny) {
|
|
135
|
+
let res
|
|
136
|
+
if (typeof value === 'string') {
|
|
137
|
+
res = JSON.parse(value)
|
|
138
|
+
} else {
|
|
139
|
+
res = cloneDeep(value)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const x in res) {
|
|
143
|
+
res[x.toLowerCase()] = res[x]
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.setData('user', JSON.stringify(res))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
setUserByToken (token: string) {
|
|
150
|
+
const jwtInfo = this.jwtDecode(token)
|
|
151
|
+
if (jwtInfo && jwtInfo.LoginUser) {
|
|
152
|
+
this.setUser(jwtInfo.LoginUser)
|
|
153
|
+
} else {
|
|
154
|
+
this.removeUser()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
removeUser () {
|
|
159
|
+
this.removeData('user')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private jwtDecode (token?: string) {
|
|
163
|
+
if (!token) {
|
|
164
|
+
console.error('token为空 jwt解析token出错')
|
|
165
|
+
return null
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
return jwtDecode<JwtResult>(token)
|
|
169
|
+
} catch (e) {
|
|
170
|
+
console.error('jwt解析token出错', token, e)
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 检测用户是否登录状态
|
|
176
|
+
checkLogin () {
|
|
177
|
+
let haslogged = false
|
|
178
|
+
const token = this.getToken()
|
|
179
|
+
const refreshtoken = this.getRefreshToken()
|
|
180
|
+
const tokenexpires = this.getTokenExpires()
|
|
181
|
+
const now = Date.now()
|
|
182
|
+
if (token && refreshtoken && tokenexpires && Number(tokenexpires) > now) {
|
|
183
|
+
// 优化成用 jwt 解析token 获取过期时间 不需要请求接口
|
|
184
|
+
const jwtInfo = this.jwtDecode(token)
|
|
185
|
+
if (jwtInfo?.exp) {
|
|
186
|
+
haslogged = Number(jwtInfo.exp + '000') > now
|
|
187
|
+
} else {
|
|
188
|
+
haslogged = false
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return haslogged
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 单点登录
|
|
195
|
+
async singleLogin (query: IAny) {
|
|
196
|
+
// 自动登录
|
|
197
|
+
query = cloneDeep(query)
|
|
198
|
+
const token = query.token
|
|
199
|
+
// 之所以不强制校验 refreshtoken tokenexpires 是因为安装卸载配置页面有可能放在产品运营中心 没有这两字段
|
|
200
|
+
if (token) {
|
|
201
|
+
this.setToken(token)
|
|
202
|
+
this.setUserByToken(token) // 解析token为用户信息存入
|
|
203
|
+
|
|
204
|
+
const refreshtoken = query.refreshtoken
|
|
205
|
+
const tokenexpires = query.tokenexpires
|
|
206
|
+
if (refreshtoken) {
|
|
207
|
+
this.setRefreshToken(refreshtoken)
|
|
208
|
+
}
|
|
209
|
+
if (tokenexpires) {
|
|
210
|
+
this.setTokenExpires(tokenexpires)
|
|
211
|
+
}
|
|
212
|
+
// debugger
|
|
213
|
+
|
|
214
|
+
// context 上下文字段 产品运营中心安装 卸载 配置 和 产品配置中心业务配置 页面需要用到
|
|
215
|
+
let context = query.context
|
|
216
|
+
if (context) {
|
|
217
|
+
context = decodeURIComponent(context)
|
|
218
|
+
lsProxy.setItem('context', context)
|
|
219
|
+
delete query.context
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// const tenant = await apassRequest.get('/api/auth/tenantlist', {}).then((res) => {
|
|
223
|
+
// return res?.data?.tenants?.[0]
|
|
224
|
+
// })
|
|
225
|
+
// if (tenant) {
|
|
226
|
+
// lsProxy.setItem('tenant', JSON.stringify(tenant))
|
|
227
|
+
// const normalizedTenant = tenantInfoApi.format(tenant as Tenant)
|
|
228
|
+
// normalizedTenant && tenantInfoApi.save(normalizedTenant)
|
|
229
|
+
// }
|
|
230
|
+
// console.log(tenant)
|
|
231
|
+
|
|
232
|
+
await tenantInfo.getAndSave()
|
|
233
|
+
// debugger
|
|
234
|
+
} else {
|
|
235
|
+
console.error('query 中没有 token,无法单点登录。')
|
|
236
|
+
}
|
|
237
|
+
// 单点登录后 无论是否成功 都需要删除 query 中相关参数
|
|
238
|
+
delete query.token
|
|
239
|
+
delete query.refreshtoken
|
|
240
|
+
delete query.tokenexpires
|
|
241
|
+
delete query.context
|
|
242
|
+
return {
|
|
243
|
+
query
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export default new Login()
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import CloudServ from '../cloudServ'
|
|
2
|
+
import { initServToken } from './servtoken'
|
|
3
|
+
import OSS from '../package/ali-oss/aliyun-oss-sdk.apaas.min.js'
|
|
4
|
+
// import * as OSS from '../package/ali-oss/aliyun-oss-sdk.apaas.min.js'
|
|
5
|
+
// const OSS = require('../package/ali-oss/aliyun-oss-sdk.apaas.min.js')
|
|
6
|
+
import ObsClient from '../package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js'
|
|
7
|
+
// import * as ObsClient from '../package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js'
|
|
8
|
+
// const ObsClient = require('../package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js')
|
|
9
|
+
import dayjs from 'dayjs'
|
|
10
|
+
import login from '../login'
|
|
11
|
+
// import { get } from 'lodash-es'
|
|
12
|
+
// import qs from 'qs'
|
|
13
|
+
|
|
14
|
+
// function getUrlPaths(url: string): string[] {
|
|
15
|
+
// let path = url.split('?')[0]
|
|
16
|
+
// if (!path) return []
|
|
17
|
+
// path = path.replace('http://', '')
|
|
18
|
+
// path = path.replace('https://', '')
|
|
19
|
+
// return path.split('/')
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
// console.log(OSS)
|
|
23
|
+
// debugger
|
|
24
|
+
const getContentType = (suffix: string) => {
|
|
25
|
+
const map: IAny = {
|
|
26
|
+
'.jpg': 'image/jpeg',
|
|
27
|
+
'.jpeg': 'image/jpeg',
|
|
28
|
+
'.png': 'image/png',
|
|
29
|
+
'.gif': 'image/gif'
|
|
30
|
+
// '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
31
|
+
}
|
|
32
|
+
return map[suffix.toLowerCase()] || ''
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// interface UrlInfo {
|
|
36
|
+
// [propName: string]: {
|
|
37
|
+
// url: string
|
|
38
|
+
// outTime: number
|
|
39
|
+
// }
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
// /**
|
|
43
|
+
// * @Description: 缓存DownloadUrl
|
|
44
|
+
// * @author: hyl
|
|
45
|
+
// */
|
|
46
|
+
// const cacheUrlInfo: UrlInfo = {}
|
|
47
|
+
|
|
48
|
+
// function setCacheUrl(key: string, url: string, expires: number) {
|
|
49
|
+
// const thisTime = new Date().getTime()
|
|
50
|
+
// let diff = expires * 1000 - thisTime
|
|
51
|
+
// if (diff < 0) return
|
|
52
|
+
// // 最多只缓存20分钟
|
|
53
|
+
// if (diff > 1000 * 60 * 20) diff = 1000 * 60 * 20
|
|
54
|
+
// const outTime = thisTime + diff
|
|
55
|
+
// cacheUrlInfo[key] = {
|
|
56
|
+
// url,
|
|
57
|
+
// outTime
|
|
58
|
+
// }
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
type Cope = { width?: number, height?: number } | string | boolean
|
|
63
|
+
|
|
64
|
+
const getNormalizeAliOssCope = (cope?: Cope) => {
|
|
65
|
+
let copeObj = ''
|
|
66
|
+
if (cope) {
|
|
67
|
+
if (cope === true) {
|
|
68
|
+
copeObj = 'image/resize,m_fixed,w_100,h_100'
|
|
69
|
+
} else if (typeof cope === 'string') {
|
|
70
|
+
// 'image/resize,m_fixed,w_100,h_100'
|
|
71
|
+
copeObj = cope
|
|
72
|
+
} else if (cope.width || cope.height) {
|
|
73
|
+
copeObj = 'image/resize,m_fixed'
|
|
74
|
+
if (cope.width) {
|
|
75
|
+
copeObj += `,w_${cope.width}`
|
|
76
|
+
}
|
|
77
|
+
if (cope.height) {
|
|
78
|
+
copeObj += `,h_${cope.height}`
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return copeObj
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
interface IDownload {
|
|
87
|
+
type?: 'att' | 'img',
|
|
88
|
+
source: string,
|
|
89
|
+
datetime: string | number,
|
|
90
|
+
storagetype?: StorageType,
|
|
91
|
+
cope?: Cope
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 根据文件信息最后生成一个云文件服务可以用的链接http://xxxxx.xxx.jpg
|
|
95
|
+
const getUrl = async ({
|
|
96
|
+
type = 'img',
|
|
97
|
+
source = '',
|
|
98
|
+
datetime = '',
|
|
99
|
+
storagetype = 'storage',
|
|
100
|
+
cope = ''
|
|
101
|
+
}: IDownload) => {
|
|
102
|
+
const cloudServStorage = CloudServ.get(storagetype)
|
|
103
|
+
if (!cloudServStorage) throw Error('无可用存储设置')
|
|
104
|
+
const servToken = await initServToken()
|
|
105
|
+
if (!servToken) throw Error('无可用servToken')
|
|
106
|
+
|
|
107
|
+
const isAliYun = CloudServ.isAliyun(storagetype)
|
|
108
|
+
const isHuawei = CloudServ.isHuawei(storagetype)
|
|
109
|
+
const tenantCode = login.getUser('tenantcode')
|
|
110
|
+
const isAbsoluteUrl = !!source.match(/\/att\//) || !!source.match(/\/img\//) || !!source.match(/att\//) || !!source.match(/img\//)
|
|
111
|
+
const suffix = source.slice(source.lastIndexOf('.'))
|
|
112
|
+
const date = dayjs(+datetime).format('YYYYMMDD')
|
|
113
|
+
let objectKey = isAbsoluteUrl ? source : `${source.slice(0, 3)}/${type}/${date}/${tenantCode}/${source}`
|
|
114
|
+
const copeObj = getNormalizeAliOssCope(cope)
|
|
115
|
+
const contentType = getContentType(suffix)
|
|
116
|
+
|
|
117
|
+
if (isAliYun) {
|
|
118
|
+
const ossClient = new OSS({
|
|
119
|
+
// region: cloudServ.cloudserv_storage_storageendpoint,
|
|
120
|
+
endpoint: cloudServStorage.cloudserv_storage_storageendpoint,
|
|
121
|
+
accessKeyId: servToken.accesskeyid,
|
|
122
|
+
accessKeySecret: servToken.accesskeysecret,
|
|
123
|
+
stsToken: servToken.securitytoken,
|
|
124
|
+
bucket: cloudServStorage.cloudserv_storage_storagebucket,
|
|
125
|
+
secure: true
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// TODO 这两个请求头不能改顺序,不知道什么情况!!改了顺序会报错
|
|
129
|
+
const responseHeader: IAny = {
|
|
130
|
+
// 'content-type': contentType || undefined,
|
|
131
|
+
'content-disposition': 'attachment; filename=' + (source && encodeURIComponent(source)) // 阿里云提供的下载名字
|
|
132
|
+
}
|
|
133
|
+
if (contentType) {
|
|
134
|
+
responseHeader['content-type'] = contentType
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const ossUrl = ossClient.signatureUrl(objectKey, {
|
|
138
|
+
response: responseHeader,
|
|
139
|
+
process: copeObj
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// // 假阿里云会自动拼cloudserv_storage_storagebucket,这里要去掉
|
|
143
|
+
// const paths = getUrlPaths(ossUrl)
|
|
144
|
+
// if (paths.length >= 3 && paths[1] === paths[2]) {
|
|
145
|
+
// ossUrl = ossUrl.replace(paths[1] + '/' + paths[2], paths[1])
|
|
146
|
+
// }
|
|
147
|
+
|
|
148
|
+
return ossUrl
|
|
149
|
+
} else if (isHuawei) {
|
|
150
|
+
const obs = new ObsClient({
|
|
151
|
+
access_key_id: servToken.accesskeyid,
|
|
152
|
+
secret_access_key: servToken.accesskeysecret,
|
|
153
|
+
server: cloudServStorage.cloudserv_storage_storageendpoint,
|
|
154
|
+
security_token: servToken.securitytoken
|
|
155
|
+
})
|
|
156
|
+
// 修复地址里面有//就不能下载了
|
|
157
|
+
if (objectKey && objectKey[0] === '/') {
|
|
158
|
+
objectKey = objectKey.slice(1)
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const Params: IAny = {
|
|
162
|
+
// Method: 'get',
|
|
163
|
+
Bucket: cloudServStorage.cloudserv_storage_storagebucket,
|
|
164
|
+
Key: objectKey
|
|
165
|
+
// Headers: responseHeader
|
|
166
|
+
// Expires: 3600,
|
|
167
|
+
// Headers: headers
|
|
168
|
+
}
|
|
169
|
+
if (contentType.startsWith('image') && copeObj) {
|
|
170
|
+
Params.QueryParams = {
|
|
171
|
+
'x-image-process': copeObj
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const res = obs.createSignedUrlSync(Params)
|
|
175
|
+
const signedUrl = res.SignedUrl
|
|
176
|
+
|
|
177
|
+
// const expires = get(qs.parse(signedUrl), 'Expires') as string
|
|
178
|
+
// if (expires) setCacheUrl(cacheKey, signedUrl, +expires)
|
|
179
|
+
|
|
180
|
+
return signedUrl
|
|
181
|
+
} catch (e: any) {
|
|
182
|
+
console.error(e)
|
|
183
|
+
throw Error(e)
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
throw Error('暂不支持非阿里云OSS/华为云OBS存储类型')
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export default {
|
|
191
|
+
getUrl
|
|
192
|
+
}
|