vue2-client 1.2.83 → 1.2.86

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/CHANGELOG.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Change Log
2
2
  > 所有关于本项目的变化都在该文档里。
3
3
 
4
- **1.2.81 - 1.2.83 -2022-07-21 @朱子峰**
4
+ **1.2.81 - 1.2.86 -2022-07-21 @朱子峰**
5
5
  - 功能新增:
6
6
  - 兼容V4登陆
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.2.83",
3
+ "version": "1.2.86",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
package/src/App.vue CHANGED
@@ -24,6 +24,7 @@ export default {
24
24
  },
25
25
  mounted () {
26
26
  this.setWeekModeTheme(this.weekMode)
27
+ localStorage.setItem('compatible', this.compatible)
27
28
  },
28
29
  watch: {
29
30
  weekMode (val) {
@@ -55,7 +56,7 @@ export default {
55
56
  }
56
57
  },
57
58
  computed: {
58
- ...mapState('setting', ['layout', 'theme', 'weekMode', 'lang'])
59
+ ...mapState('setting', ['layout', 'theme', 'weekMode', 'lang', 'compatible'])
59
60
  },
60
61
  methods: {
61
62
  ...mapMutations('setting', ['setDevice']),
@@ -1,225 +1,225 @@
1
- <template>
2
- <div class="certain-category-search-wrapper">
3
- <a-auto-complete
4
- :disabled="!mapAutocomplete"
5
- :dropdown-match-select-width="false"
6
- :dropdown-style="{ width: '400px' }"
7
- class="certain-category-search"
8
- dropdown-class-name="certain-category-search-dropdown"
9
- option-label-prop="value"
10
- placeholder="输入地址关键字搜索"
11
- @search="fetchFunction"
12
- @select="onSelect"
13
- >
14
- <a-spin v-if="searching" slot="notFoundContent" size="small" />
15
- <template slot="dataSource">
16
- <a-select-opt-group v-for="group in option" :key="group.title">
17
- <span
18
- slot="label">
19
- <a-icon type="bank" /> {{ group.title }}
20
- </span>
21
- <a-select-option v-for="address in group.children" :key="address.label + ' (' + address.value + ')'">
22
- <p class="addressName"><a-icon type="environment" /> <span v-html="highLight(address.label, address.word)">{{ address.label }}</span></p>
23
- <p v-if="address.address !== '[]'" class="addressRemark">
24
- {{ address.address }}
25
- </p>
26
- </a-select-option>
27
- </a-select-opt-group>
28
- </template>
29
- <a-input>
30
- <a-icon slot="suffix" class="certain-category-icon" type="search"/>
31
- </a-input>
32
- </a-auto-complete>
33
- </div>
34
- </template>
35
- <script>
36
-
37
- import { post } from '@vue2-client/services/api'
38
- import { GetGDMap } from '@vue2-client/utils/map-utils'
39
- import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
40
-
41
- export default {
42
- name: 'AddressSearchCombobox',
43
- data () {
44
- // 检索去抖
45
- this.fetchFunction = debounce(this.fetchFunction, 300)
46
- return {
47
- // 地址搜索联想
48
- mapAutocomplete: undefined,
49
- // 检索结果
50
- option: [],
51
- // 最后检索版本
52
- lastFetchId: 0,
53
- // 检索中
54
- searching: false
55
- }
56
- },
57
- model: {
58
- prop: 'searchResult',
59
- event: 'onSelect'
60
- },
61
- props: {
62
- searchResult: {
63
- type: String,
64
- default: undefined
65
- },
66
- // 返回数据格式
67
- searchResultType: {
68
- type: String,
69
- default: 'Default'
70
- // default: 'Array'
71
- // default: 'Object'
72
- },
73
- // Object 返回格式时 可以自定义key
74
- resultKeys: {
75
- type: Object,
76
- default: () => { return { address: 'address', coords: 'coords' } }
77
- }
78
- },
79
- created () {
80
- },
81
- mounted () {
82
- GetGDMap().then(aMap => {
83
- this.mapAutocomplete = new (aMap).Autocomplete({})
84
- })
85
- },
86
- methods: {
87
- onSelect (value) {
88
- let result
89
- if (this.searchResultType !== 'Default') {
90
- const _arr = value.replace(')', '').split('(')
91
- if (this.searchResultType === 'Array') {
92
- result = _arr
93
- } else {
94
- result = {}
95
- result[this.resultKeys.address] = _arr[0]
96
- result[this.resultKeys.coords] = _arr[1]
97
- }
98
- }
99
- this.$emit('onSelect', JSON.stringify(result) || value)
100
- // this.$emit('onClick', result || value)
101
- },
102
- // 懒加载检索方法
103
- fetchFunction (value) {
104
- if (value && this.mapAutocomplete) {
105
- this.searching = true
106
- this.lastFetchId += 1
107
- const fetchId = this.lastFetchId
108
- this.mapAutocomplete.search(value, (status, result) => {
109
- if (fetchId !== this.lastFetchId) {
110
- return
111
- }
112
- if (status === 'complete') {
113
- this.option = []
114
- const addressMap = {}
115
- result.tips.forEach((res) => {
116
- if (res.location) {
117
- if (!addressMap.hasOwnProperty(res.district)) {
118
- addressMap[res.district] = []
119
- }
120
- addressMap[res.district].push({
121
- label: res.name,
122
- value: res.location.lng + ',' + res.location.lat + ',',
123
- address: res.address + '',
124
- word: value
125
- })
126
- }
127
- })
128
- for (const key of Object.keys(addressMap)) {
129
- this.option.push({
130
- title: key,
131
- children: addressMap[key]
132
- })
133
- }
134
- }
135
- this.searching = false
136
- })
137
- }
138
- },
139
- // 获取数据
140
- getData (value, callback) {
141
- if (value !== '') {
142
- const logicName = this.attr.keyName
143
- const logic = logicName.substring(6)
144
- post('/webmeterapi/' + logic, value).then(res => {
145
- callback(res)
146
- })
147
- }
148
- },
149
- // 关键字高亮
150
- highLight (value, word) {
151
- // 如果标题中包含,关键字就替换一下
152
- if (value.includes(word)) {
153
- value = value.replace(word,
154
- // 这里是替换成html格式的数据,最好再加一个样式权重,保险一点
155
- '<span style="color:red!important;">' + word + '</span>'
156
- )
157
- return value
158
- // eslint-disable-next-line brace-style
159
- }
160
- // 不包含的话还用这个
161
- else {
162
- return value
163
- }
164
- }
165
- }
166
- }
167
- </script>
168
-
169
- <style>
170
- .certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title {
171
- color: #666;
172
- font-weight: bold;
173
- font-size: 14px;
174
- }
175
-
176
- .certain-category-search-dropdown .ant-select-dropdown-menu-item-group {
177
- border-bottom: 1px solid #f6f6f6;
178
- }
179
-
180
- .certain-category-search-dropdown .ant-select-dropdown-menu-item {
181
- padding-left: 16px;
182
- }
183
-
184
- .certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all {
185
- text-align: center;
186
- cursor: default;
187
- }
188
-
189
- .certain-category-search-dropdown .ant-select-dropdown-menu {
190
- max-height: 300px;
191
- }
192
- </style>
193
- <style scoped>
194
- .certain-category-search-wrapper
195
- >>> .certain-category-search.ant-select-auto-complete
196
- .ant-input-affix-wrapper
197
- .ant-input-suffix {
198
- right: 12px;
199
- }
200
- .certain-category-search-wrapper >>> .certain-search-item-count {
201
- position: absolute;
202
- color: #999;
203
- right: 16px;
204
- }
205
- .certain-category-search-wrapper >>> .certain-category-search.ant-select-focused,
206
- .certain-category-icon {
207
- color: #108ee9;
208
- }
209
- .certain-category-search-wrapper >>> .certain-category-icon {
210
- color: #6e6e6e;
211
- transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
212
- font-size: 16px;
213
- }
214
-
215
- .addressName {
216
- margin-bottom: 0;
217
- font-size: 14px;
218
- font-weight: bold;
219
- }
220
-
221
- .addressRemark {
222
- margin-bottom: 0;
223
- font-size: 12px;
224
- }
225
- </style>
1
+ <template>
2
+ <div class="certain-category-search-wrapper">
3
+ <a-auto-complete
4
+ :disabled="!mapAutocomplete"
5
+ :dropdown-match-select-width="false"
6
+ :dropdown-style="{ width: '400px' }"
7
+ class="certain-category-search"
8
+ dropdown-class-name="certain-category-search-dropdown"
9
+ option-label-prop="value"
10
+ placeholder="输入地址关键字搜索"
11
+ @search="fetchFunction"
12
+ @select="onSelect"
13
+ >
14
+ <a-spin v-if="searching" slot="notFoundContent" size="small" />
15
+ <template slot="dataSource">
16
+ <a-select-opt-group v-for="group in option" :key="group.title">
17
+ <span
18
+ slot="label">
19
+ <a-icon type="bank" /> {{ group.title }}
20
+ </span>
21
+ <a-select-option v-for="address in group.children" :key="address.label + ' <' + address.value + '>'">
22
+ <p class="addressName"><a-icon type="environment" /> <span v-html="highLight(address.label, address.word)">{{ address.label }}</span></p>
23
+ <p v-if="address.address !== '[]'" class="addressRemark">
24
+ {{ address.address }}
25
+ </p>
26
+ </a-select-option>
27
+ </a-select-opt-group>
28
+ </template>
29
+ <a-input>
30
+ <a-icon slot="suffix" class="certain-category-icon" type="search"/>
31
+ </a-input>
32
+ </a-auto-complete>
33
+ </div>
34
+ </template>
35
+ <script>
36
+
37
+ import { post } from '@vue2-client/services/api'
38
+ import { GetGDMap } from '@vue2-client/utils/map-utils'
39
+ import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
40
+
41
+ export default {
42
+ name: 'AddressSearchCombobox',
43
+ data () {
44
+ // 检索去抖
45
+ this.fetchFunction = debounce(this.fetchFunction, 300)
46
+ return {
47
+ // 地址搜索联想
48
+ mapAutocomplete: undefined,
49
+ // 检索结果
50
+ option: [],
51
+ // 最后检索版本
52
+ lastFetchId: 0,
53
+ // 检索中
54
+ searching: false
55
+ }
56
+ },
57
+ model: {
58
+ prop: 'searchResult',
59
+ event: 'onSelect'
60
+ },
61
+ props: {
62
+ searchResult: {
63
+ type: String,
64
+ default: undefined
65
+ },
66
+ // 返回数据格式
67
+ searchResultType: {
68
+ type: String,
69
+ default: 'Default'
70
+ // default: 'Array'
71
+ // default: 'Object'
72
+ },
73
+ // Object 返回格式时 可以自定义key
74
+ resultKeys: {
75
+ type: Object,
76
+ default: () => { return { address: 'address', coords: 'coords' } }
77
+ }
78
+ },
79
+ created () {
80
+ },
81
+ mounted () {
82
+ GetGDMap().then(aMap => {
83
+ this.mapAutocomplete = new (aMap).Autocomplete({})
84
+ })
85
+ },
86
+ methods: {
87
+ onSelect (value) {
88
+ let result
89
+ if (this.searchResultType !== 'Default') {
90
+ const _arr = value.replace('>', '').split('<')
91
+ if (this.searchResultType === 'Array') {
92
+ result = _arr
93
+ } else {
94
+ result = {}
95
+ result[this.resultKeys.address] = _arr[0]
96
+ result[this.resultKeys.coords] = _arr[1]
97
+ }
98
+ }
99
+ this.$emit('onSelect', JSON.stringify(result) || value)
100
+ // this.$emit('onClick', result || value)
101
+ },
102
+ // 懒加载检索方法
103
+ fetchFunction (value) {
104
+ if (value && this.mapAutocomplete) {
105
+ this.searching = true
106
+ this.lastFetchId += 1
107
+ const fetchId = this.lastFetchId
108
+ this.mapAutocomplete.search(value, (status, result) => {
109
+ if (fetchId !== this.lastFetchId) {
110
+ return
111
+ }
112
+ if (status === 'complete') {
113
+ this.option = []
114
+ const addressMap = {}
115
+ result.tips.forEach((res) => {
116
+ if (res.location) {
117
+ if (!addressMap.hasOwnProperty(res.district)) {
118
+ addressMap[res.district] = []
119
+ }
120
+ addressMap[res.district].push({
121
+ label: res.name,
122
+ value: res.location.lng + ',' + res.location.lat,
123
+ address: res.address + '',
124
+ word: value
125
+ })
126
+ }
127
+ })
128
+ for (const key of Object.keys(addressMap)) {
129
+ this.option.push({
130
+ title: key,
131
+ children: addressMap[key]
132
+ })
133
+ }
134
+ }
135
+ this.searching = false
136
+ })
137
+ }
138
+ },
139
+ // 获取数据
140
+ getData (value, callback) {
141
+ if (value !== '') {
142
+ const logicName = this.attr.keyName
143
+ const logic = logicName.substring(6)
144
+ post('/webmeterapi/' + logic, value).then(res => {
145
+ callback(res)
146
+ })
147
+ }
148
+ },
149
+ // 关键字高亮
150
+ highLight (value, word) {
151
+ // 如果标题中包含,关键字就替换一下
152
+ if (value.includes(word)) {
153
+ value = value.replace(word,
154
+ // 这里是替换成html格式的数据,最好再加一个样式权重,保险一点
155
+ '<span style="color:red!important;">' + word + '</span>'
156
+ )
157
+ return value
158
+ // eslint-disable-next-line brace-style
159
+ }
160
+ // 不包含的话还用这个
161
+ else {
162
+ return value
163
+ }
164
+ }
165
+ }
166
+ }
167
+ </script>
168
+
169
+ <style>
170
+ .certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title {
171
+ color: #666;
172
+ font-weight: bold;
173
+ font-size: 14px;
174
+ }
175
+
176
+ .certain-category-search-dropdown .ant-select-dropdown-menu-item-group {
177
+ border-bottom: 1px solid #f6f6f6;
178
+ }
179
+
180
+ .certain-category-search-dropdown .ant-select-dropdown-menu-item {
181
+ padding-left: 16px;
182
+ }
183
+
184
+ .certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all {
185
+ text-align: center;
186
+ cursor: default;
187
+ }
188
+
189
+ .certain-category-search-dropdown .ant-select-dropdown-menu {
190
+ max-height: 300px;
191
+ }
192
+ </style>
193
+ <style scoped>
194
+ .certain-category-search-wrapper
195
+ >>> .certain-category-search.ant-select-auto-complete
196
+ .ant-input-affix-wrapper
197
+ .ant-input-suffix {
198
+ right: 12px;
199
+ }
200
+ .certain-category-search-wrapper >>> .certain-search-item-count {
201
+ position: absolute;
202
+ color: #999;
203
+ right: 16px;
204
+ }
205
+ .certain-category-search-wrapper >>> .certain-category-search.ant-select-focused,
206
+ .certain-category-icon {
207
+ color: #108ee9;
208
+ }
209
+ .certain-category-search-wrapper >>> .certain-category-icon {
210
+ color: #6e6e6e;
211
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
212
+ font-size: 16px;
213
+ }
214
+
215
+ .addressName {
216
+ margin-bottom: 0;
217
+ font-size: 14px;
218
+ font-weight: bold;
219
+ }
220
+
221
+ .addressRemark {
222
+ margin-bottom: 0;
223
+ font-size: 12px;
224
+ }
225
+ </style>
@@ -33,8 +33,6 @@ const GetAppDataService = {
33
33
  // 追加参数
34
34
  localStorage.setItem(process.env.VUE_APP_DICTIONARY_KEY, JSON.stringify(params))
35
35
  localStorage.setItem(process.env.VUE_APP_BADGE_KEY, JSON.stringify(badgeItemArray))
36
- // 清除compatible
37
- localStorage.removeItem('compatible')
38
36
  })
39
37
  // 获取省市区数据
40
38
  await post(manageApi.getDivisionsOhChina, {}).then((res) => {
@@ -116,11 +116,18 @@ export default {
116
116
  const password = this.form.getFieldValue('password')
117
117
  this.logging = false
118
118
  const loginRes = res
119
- const V4Token = { token: res.data.access_token, expire: res.data.expires_in }
119
+ const V4Token = { token: res.access_token, expire: res.expires_in }
120
120
  this.setV4AccessToken(V4Token)
121
+ // 如果这是用户首次打开本系统,localStorage无法初始化,改用code判断
122
+ let pass = false
123
+ if (res.code) {
124
+ if (res.code === 200) {
125
+ pass = true
126
+ }
127
+ }
121
128
  // 向本地缓存中临时存储compatible
122
- localStorage.setItem('compatible', this.compatible)
123
- if (loginRes.code === 200) {
129
+ console.log(loginRes)
130
+ if (loginRes.access_token || pass) {
124
131
  const encrypt = new JSEncrypt()
125
132
  encrypt.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPvovSfXcwBbW8cKMCgwqNpsYuzF8RPAPFb7LGsnVo44JhM/xxzDyzoYtdfNmtbIuKVi9PzIsyp6rg+09gbuI6UGwBZ5DWBDBMqv5MPdOF5dCQkB2Bbr5yPfURPENypUz+pBFBg41d+BC+rwRiXELwKy7Y9caD/MtJyHydj8OUwIDAQAB')
126
133
  const data = encrypt.encrypt(JSON.stringify({ username: name, password: password }))
@@ -1,28 +1,31 @@
1
- import AMapLoader from '@amap/amap-jsapi-loader'
2
- let Amap
3
- async function GetGDMap () {
4
- if (!Amap) {
5
- Amap = await AMapLoader.load({
6
- key: '4889f1e58df01cb40415536c8907bf64', // 申请好的Web端开发者Key,首次调用 load 时必填
7
- version: '1.4.2', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
8
- plugins: ['AMap.ToolBar', 'AMap.Geolocation', 'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.Autocomplete'] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
9
- })
10
- }
11
- return Amap
12
- }
13
- async function GetLocation (address) {
14
- return new Promise(async (resolve, reject) => {
15
- new (await GetGDMap()).Geocoder({
16
- radius: 500 // 范围,默认:500
17
- }).getLocation(address, function (status, result) {
18
- console.log(result)
19
- if (status === 'complete' && result.geocodes.length) {
20
- resolve({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
21
- } else {
22
- // eslint-disable-next-line prefer-promise-reject-errors
23
- reject('根据经纬度查询地址失败')
24
- }
25
- })
26
- })
27
- }
28
- export { GetGDMap, GetLocation }
1
+ import AMapLoader from '@amap/amap-jsapi-loader'
2
+ let Amap
3
+ async function GetGDMap () {
4
+ if (!Amap) {
5
+ window._AMapSecurityConfig = {
6
+ securityJsCode: '275e59edb26ab1f917cfe7f05bea7979'
7
+ }
8
+ Amap = await AMapLoader.load({
9
+ key: '55a4807a6fc3adca5510f69578b1ae4a', // 申请好的Web端开发者Key,首次调用 load 时必填
10
+ version: '1.4.2', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
11
+ plugins: ['AMap.ToolBar', 'AMap.Geolocation', 'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.Autocomplete'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
12
+ })
13
+ }
14
+ return Amap
15
+ }
16
+ async function GetLocation (address) {
17
+ return new Promise(async (resolve, reject) => {
18
+ new (await GetGDMap()).Geocoder({
19
+ radius: 500 // 范围,默认:500
20
+ }).getLocation(address, function (status, result) {
21
+ console.log(result)
22
+ if (status === 'complete' && result.geocodes.length) {
23
+ resolve({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
24
+ } else {
25
+ // eslint-disable-next-line prefer-promise-reject-errors
26
+ reject('根据经纬度查询地址失败')
27
+ }
28
+ })
29
+ })
30
+ }
31
+ export { GetGDMap, GetLocation }
@@ -4,7 +4,7 @@ import Vue from 'vue'
4
4
  import { ACCESS_TOKEN } from '@vue2-client/store/mutation-types'
5
5
  import notification from 'ant-design-vue/es/notification'
6
6
 
7
- const setting = require('../config/default/setting.config')
7
+ const compatible = localStorage.getItem('compatible')
8
8
 
9
9
  // 跨域认证信息 header 名
10
10
  const xsrfHeaderName = 'Authorization'
@@ -156,7 +156,7 @@ function loadInterceptors () {
156
156
  // 让每个请求携带自定义 token 请根据实际情况自行修改
157
157
  if (token) {
158
158
  // 判断是否为V4环境
159
- if (setting.compatible === 'V4') {
159
+ if (compatible === 'V4') {
160
160
  // V4 环境则添加 V4请求头
161
161
  config.headers['ACCESS_TOKEN'] = localStorage.getItem('ACCESS_TOKEN')
162
162
  config.headers['ACCESS_TOKEN_EXPIRES'] = localStorage.getItem('ACCESS_TOKEN_EXPIRES')
@@ -171,7 +171,16 @@ function loadInterceptors () {
171
171
  }, errorHandler)
172
172
  // 加载响应拦截器
173
173
  axios.interceptors.response.use((response) => {
174
- return response.data
174
+ // 判断是否为V4环境
175
+ if (compatible === 'V4') {
176
+ if (response.data.data) {
177
+ return response.data.data
178
+ } else {
179
+ return response.data
180
+ }
181
+ } else {
182
+ return response.data
183
+ }
175
184
  }, errorHandler)
176
185
  }
177
186
 
@@ -181,12 +190,12 @@ const errorHandler = (error) => {
181
190
  const data = error.response.data
182
191
  // 从 localstorage 获取 token
183
192
  const token = localStorage.getItem(ACCESS_TOKEN)
184
- if (error.response.status === 403) {
193
+ if (error.response.status === 403 || data.code === 403) {
185
194
  notification.error({
186
195
  message: '禁止访问',
187
196
  description: data
188
197
  })
189
- } else if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
198
+ } else if ((error.response.status === 401 || data.code === 401) && !(data.result && data.result.isLogin)) {
190
199
  notification.error({
191
200
  message: '鉴权失败',
192
201
  description: data
@@ -198,7 +207,7 @@ const errorHandler = (error) => {
198
207
  }, 1500)
199
208
  })
200
209
  }
201
- } else if (error.response.status === 500) {
210
+ } else if (error.response.status === 500 || data.code === 500) {
202
211
  notification.error({
203
212
  message: '系统异常',
204
213
  description: data