@tongfun/tf-widget 0.1.27 → 0.1.28

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.
@@ -1,202 +0,0 @@
1
-
2
- //通用按钮
3
- .common-header-button{
4
- min-width: 2.5vw;
5
- height: 2.222vh;
6
- opacity: 1;
7
- background: #0c4c8e;
8
- border-color: #0c4c8e;
9
- border-radius: 2px;
10
- padding: 0;
11
- margin-right: 0.4166vw;
12
- ::v-deep span{
13
- opacity: 1;
14
- font-size: 0.625vw;
15
- font-family: Source Han Sans SC, Source Han Sans SC-Regular;
16
- font-weight: 400;
17
- color: #ffffff;
18
- }
19
- }
20
- // 统一按钮悬浮样式
21
- .common-header-button:hover{
22
- background: #0c4c8e;
23
- border-color: #0c4c8e;
24
- }
25
- // 统一按钮focus样式
26
- .common-header-button:focus{
27
- background: #0c4c8e;
28
- border-color: #0c4c8e;
29
- }
30
- // 去除button自带margin-left
31
- ::v-deep .el-button+.el-button{
32
- margin-left: 0;
33
- }
34
-
35
- //模态框取消按钮为浅色
36
- .close{
37
- background-color: #e5e5e5;
38
- border-color: #e5e5e5;
39
- ::v-deep span{
40
- color: #666;
41
- }
42
- }
43
- .close:hover{
44
- background-color: #e5e5e5;
45
- color: #666;
46
- border-color: #e5e5e5;
47
- }
48
- .close:focus{
49
- background-color: #e5e5e5;
50
- color: #666;
51
- border-color: #e5e5e5;
52
-
53
- }
54
-
55
-
56
- //通用下拉按钮
57
- .common-header-drop-button{
58
- height: 2.222vh;
59
- margin-right: 0.4166vw;
60
- ::v-deep .el-button-group{
61
- height: 100%;
62
- display: flex;
63
- }
64
- ::v-deep .el-button{
65
- width: 2.5vw;
66
- height: 2.222vh;
67
- opacity: 1;
68
- background: #0c4c8e;
69
- padding: 0;
70
- border-radius: 2px 0 0 2px;
71
- border: 1px solid #0c4c8e;
72
- margin-right: 0;
73
- }
74
- ::v-deep span{
75
- font-size: 0.625vw;
76
- font-family: Source Han Sans SC, Source Han Sans SC-Regular;
77
- }
78
- ::v-deep .el-dropdown__caret-button{
79
- width: 0.625vw;
80
- height: 2.222vh;
81
- background-color: #87a7c8;
82
- border-radius: 0 2px 2px 0;
83
- padding: 0;
84
- border: 0 solid #87a7c8;
85
- .el-dropdown__icon, el-icon-arrow-down{
86
- margin: 0;
87
- }
88
- }
89
- ::v-deep .el-dropdown__caret-button::before{
90
- background-color: #87a7c8;
91
- }
92
- ::v-deep .el-dropdown__icon{
93
- width: 0.625vw;
94
- font-size: 0.625vw;
95
- }
96
- }
97
-
98
- // 通用下拉按钮(文字较多时)
99
- .common-header-drop-button-more{
100
- ::v-deep .el-button{
101
- width: 3.5vw;
102
- }
103
- ::v-deep .el-dropdown__caret-button{
104
- width: 0.625vw;
105
- }
106
- }
107
-
108
- .common-table{
109
- //表头配置
110
- ::v-deep .elx-header--row{
111
- .elx-header--column:nth-child(1){
112
- .elx-cell{
113
- width: 63px !important;
114
- height: 3.2407vh !important;
115
- }
116
- }
117
- }
118
- ::v-deep .elx-table--header{
119
- color: #085497;
120
- font-size: 0.7291vw;
121
- background: #edf0f5;
122
- border-radius: 4px 4px 0 0;
123
- .elx-cell{
124
- width: 100% !important;
125
- padding: 0;
126
- .elx-cell--title{
127
- width: 100% !important;
128
- }
129
- }
130
- }
131
- ::v-deep .elx-header--column{
132
- font-weight: normal;
133
- height: 3.2407vh !important;
134
- background-image: none !important;
135
- }
136
- ::v-deep .elx-body--column{
137
- height: 3.2407vh !important;
138
- border-top: 1px solid #E0EAFC;
139
- border-right: 1px solid #E0EAFC;
140
- font-size: 0.625vw;
141
- font-weight: normal;
142
- color: #666666;
143
- background-image: none !important;
144
- }
145
- // 首列左侧增加border
146
- ::v-deep .elx-body--row{
147
- .elx-body--column:nth-child(1){
148
- border-left: 1px solid #E0EAFC;
149
- }
150
- }
151
- // 末行底部增加border
152
- ::v-deep .elx-body--row:nth-last-child(1){
153
- .elx-body--column{
154
- border-bottom: 1px solid #E0EAFC;
155
- }
156
- }
157
-
158
- // ::v-deep .elx-table--body{
159
- // //border-collapse: collapse;
160
- // }
161
- ::v-deep .row--current{
162
- background: #EFF7FF;
163
- }
164
- ::v-deep .elx-table--body-wrapper{
165
- background: #FFFFFF;
166
- height: 70vh;
167
- }
168
- @media screen and (max-width: 1366px){
169
- ::v-deep .elx-table--body-wrapper{
170
- height: 65vh;
171
- }
172
- }
173
- ::v-deep .fixed-right--wrapper{
174
- border: none;
175
- }
176
- ::v-deep .elx-table--footer-wrapper{
177
- border: none;
178
- }
179
- ::v-deep .elx-footer--column{
180
- background-image: none !important;
181
- }
182
- // 合计行
183
- ::v-deep .elx-footer--row{
184
- td {
185
- height: 3.2407vh !important;
186
- //border-top: 1px solid #E0EAFC;
187
- }
188
- }
189
- // 表格控制按钮增大
190
- ::v-deep .el-icon-setting:before{
191
- font-size: 1.0416vw;
192
- }
193
- /deep/ .el-table__fixed-right {
194
- height: 100% !important; //设置高优先,以覆盖内联样式
195
- }
196
- /deep/ .el-table__fixed {
197
- height: 110px !important; //设置高优先,以覆盖内联样式
198
- }
199
- ::v-deep .elx-table--fixed-right-wrapper.scrolling--middle{
200
- box-shadow: none; // 去除列表控制的fix显示shadow
201
- }
202
- }
@@ -1,24 +0,0 @@
1
- export default {
2
- bind: function (el, { value }) {
3
- const time = value || 2000
4
- el._flag = true
5
- el._timer = null
6
- el.handler = (e) => {
7
- if (!el._flag) {
8
- // 无需执行时的操作
9
- e.stopImmediatePropagation()
10
- return
11
- }
12
- el._flag = false
13
- el._timer = setTimeout(() => {
14
- el._flag = true
15
- clearTimeout(el._timer)
16
- el._timer = null
17
- }, time)
18
- }
19
- el.addEventListener('click', el.handler, true)
20
- },
21
- unbind: function (el, binding) {
22
- el.removeEventListener('click', el.handler, true)
23
- }
24
- }
package/src/index.js DELETED
@@ -1,31 +0,0 @@
1
-
2
- import TfWidget from '../package/tf-widget'
3
- import SvgIcon from '../package/svg-icon'
4
- import TfLayout from '../package/tf-layout'
5
- import TDataList from '../package/t-data-list'
6
- import Tinput from '../package/t-input'
7
- import TfIconPicker from '../package/tf-icon-picker'
8
- const components = [
9
- TfWidget,
10
- SvgIcon,
11
- TfLayout,
12
- TDataList,
13
- Tinput,
14
- TfIconPicker
15
- ]
16
-
17
- const install = function (Vue) {
18
- components.forEach(component => {
19
- Vue.component(component.name, component)
20
- })
21
- }
22
-
23
- export default {
24
- install,
25
- TfWidget,
26
- SvgIcon,
27
- TfLayout,
28
- TDataList,
29
- Tinput,
30
- TfIconPicker
31
- }
@@ -1,293 +0,0 @@
1
- import { getTableData, getTableSum, getTableLayout } from '@/api/tableV3.js'
2
- import { getOperator } from '../../package/t-data-list/src/js/util'
3
- export default {
4
- data () {
5
- return {
6
- /**
7
- * 通用过滤查询参数
8
- */
9
- // 被指定为搜索建议的查询的字段列表
10
- suggestFieldList: [],
11
- // 搜索建议的高级条件
12
- searchSuggestCondition: [],
13
- // 方案切换的高级条件
14
- queryPlanCondition: [],
15
-
16
- // 数据查询接口的参数
17
- query: {
18
- // 常用条件
19
- conditionAlwaysList: [],
20
- // 分组条件
21
- conditionGroup: null,
22
- // 高级过滤条件
23
- conditionMultiList: [],
24
- // 表头的过滤条件
25
- conditionQuickList: [],
26
- // 分页条件
27
- pageNum: 1,
28
- pageSize: 200
29
- },
30
-
31
- /**
32
- * 数据查询结果相关
33
- */
34
- // 列表的字段信息(表头,可能包含了表头过滤的配置信息和其他的布局信息)
35
- tableLayout: [],
36
- // 列表数据
37
- tableData: {
38
- total: 1,
39
- records: []
40
- },
41
- // 列表底部合计
42
- tableSum: ['合计'],
43
-
44
- /**
45
- * 列表操作过程中使用组件变量
46
- */
47
- // 被标记为id的字段,这个属性只在弹窗中才被使用
48
- // 但是因为获取布局依赖了这个属性所以提取为公共属性,但是只有弹窗中才被使用
49
- idField: null,
50
- // 列表选中行的完整数据
51
- selectedRows: [],
52
- // 列表选中行的id数组
53
- ids: [],
54
-
55
- /**
56
- * 通过provie传递全局数据
57
- */
58
- syncData: {
59
- displayField: '',
60
- tableLoading: false,
61
- tableSelectionClear: true // 表格数据刷新之后是否清空已选的标识
62
- }
63
- }
64
- },
65
- computed: {
66
- /**
67
- * 高级过滤条件由多个条件来源的数据拼凑而成,使用计算属性来达到缓存的目的
68
- * 且无法确定需求上的变动是否需要动态让某个来源的条件消失,所以更改为计算属性
69
- * 来源如下:
70
- * 搜索建议和右上角复用搜索建议的接口的搜索框拼凑的高级过滤条件
71
- * 来自限定搜索范围的条件生成的高级过滤条件
72
- * 来自方案中填写点击查询按钮,或者进行切换方案的时候产生高级过滤条件
73
- */
74
- multiCondition () {
75
- const multiResult = []
76
- // 拼接方案中的高级过滤条件
77
- multiResult.push(...this.queryPlanCondition)
78
- // 拼接限定查询的条件
79
- multiResult.push(...this.limitationCondition)
80
-
81
- // 搜索建议永远被拼接到最后面
82
- // 并且在前面有条件的时候,将搜索建议的条件用双层括号整个进行包裹((a)(b))
83
- // 避免后端sql 优先级问题导致结果不准确
84
- const stillEmpty = multiResult.length === 0
85
- this.searchSuggestCondition.forEach((item, index) => {
86
- if (index === 0) {
87
- item.leftBracket = stillEmpty ? '(' : '(('
88
- }
89
- if (index === multiResult.length - 1) {
90
- item.rightBracket = stillEmpty ? ')' : '))'
91
- }
92
- })
93
- multiResult.push(...this.searchSuggestCondition)
94
-
95
- // 处理条件的排序的序号
96
- multiResult.forEach((item, index) => {
97
- item.sort = index
98
- })
99
- return multiResult
100
- },
101
- // 限定查询范围的条件
102
- limitationCondition () {
103
- if (!this.limitation) {
104
- return []
105
- }
106
- const result = []
107
- for (const key in this.limitation) {
108
- const fieldItem = this.tableLayout.find(v => v.field === key)
109
- if (!fieldItem) continue
110
-
111
- let value = ''
112
- if (fieldItem.componentValueType === 'PARAM_BASIC') {
113
- value = this.limitation[key]?.name
114
- } else if (fieldItem.componentValueType === 'PARAM_ENUM') {
115
- value = this.limitation[key]?.id
116
- } else {
117
- value = this.limitation[key]
118
- }
119
-
120
- value && result.push(this.createMultiCondition(fieldItem, value))
121
- }
122
- return result
123
- }
124
- },
125
- provide () {
126
- return {
127
- getDbRow: this.getDbRow,
128
- target: this.target,
129
- enumOptionCache: {},
130
- selectedRows: this.selectedRows,
131
- ids: this.ids,
132
- showSummary: this.queryType === 'LIST',
133
- syncData: this.syncData,
134
- queryType: this.queryType
135
- }
136
- },
137
- methods: {
138
- /**
139
- * 获取表单的布局
140
- */
141
- async getTableLayout () {
142
- const res = await getTableLayout(this.target)
143
- if (res.code !== 0) {
144
- return this.$message.error(res.msg)
145
- }
146
- this.tableLayout = res.data.sort((a, b) => a.sort - b.sort)
147
- this.suggestFieldList = res.data.filter(item => item.isSuggest)
148
- this.displayField = this.syncData.displayField = res.data.find(item => item.isDisplayField)?.field
149
- this.idField = res.data.find(item => item.isId).field
150
- },
151
-
152
- /**
153
- * 列表数据
154
- * 获取列表数据有三个地方进行调用
155
- * 1 搜索建议: 场景为SELECTOR ,不获取合计
156
- * 2 列表中数据查询:使场景为LIST, 获取合计
157
- * 3 弹窗中数据: 场景为SELECTOR,不获取合计
158
- *
159
- * 关于是否获取合计,还有一层判断来自获取合计的借口对场景进行判断
160
- * 此函数的判断只判断针对翻页页码变化这类不获取合计,至于弹窗中还是列表中的判断,在获取合计的借口中进行判断
161
- */
162
- async getTableData (isSuggest = false, getSum = false) {
163
- if (!isSuggest) {
164
- this.syncData.tableLoading = true
165
- }
166
- const queryParams = !isSuggest
167
- ? JSON.parse(JSON.stringify(this.query))
168
- : {
169
- conditionAlwaysList: [],
170
- conditionGroup: null,
171
- conditionMultiList: [],
172
- conditionQuickList: [],
173
- pageNum: 1,
174
- pageSize: 20
175
- }
176
-
177
- this.enableSum && getSum && await this.getTableSum()
178
- try {
179
- // 查询数据之前赋值高级过滤条件
180
- queryParams.conditionMultiList = this.multiCondition
181
- const res = await getTableData(this.target, queryParams, this.queryType)
182
- if (res.code !== 0) {
183
- this.$message.error(res.msg)
184
- this.syncData.tableSelectionClear = true
185
- return !isSuggest ? undefined : []
186
- }
187
- if (isSuggest) {
188
- return res.data.record
189
- }
190
- this.tableData.total = Number(res.data.total)
191
- this.tableData.records = res.data.record
192
- } catch (err) {
193
- // 恢复成默认值
194
- this.syncData.tableSelectionClear = true
195
- } finally {
196
- this.syncData.tableLoading = false
197
- }
198
- },
199
- // 表格数据合计
200
- async getTableSum () {
201
- // 只有列表中显示合计,
202
- if (this.queryType !== 'LIST') {
203
- return
204
- }
205
- const params = JSON.parse(JSON.stringify(this.query))
206
- delete params.pageNum
207
- delete params.pageSize
208
- params.conditionMultiList = this.multiCondition
209
- const res = await getTableSum(this.target, params)
210
- if (res.code !== 0) {
211
- return this.$message.error(res.msg)
212
- }
213
- // 没有合计的时候后端返回空对象,有数据该对象只有一个sum属性
214
- if (!res.data.sum) {
215
- return
216
- }
217
- const sumData = res.data.sum
218
- const sumArr = ['合计']
219
- const tableVisibleColumn = this.tableLayout.filter(item => item.visible)
220
- for (const key in sumData) {
221
- const index = tableVisibleColumn.findIndex(item => item.field === key)
222
- sumArr[index + 1] = sumData[key]
223
- }
224
- this.tableSum = sumArr
225
- },
226
- /**
227
- * 处理条件变更和重新获取数据的逻辑
228
- * 基础资料搜索建议和列表页面右上角的搜索输入框的条件处理
229
- * @param {string} queryString 用户输入的内容
230
- * @param {boolean} inputMode 输入框模式:true,否则是列表模式,输入框模式不进行数据查询
231
- */
232
- handleSuggestMultiCondition (queryString, inputMode = true) {
233
- const conditionMultiList = []
234
- for (const item of this.suggestFieldList) {
235
- conditionMultiList.push(this.createMultiCondition(item, queryString, false, false))
236
- }
237
- this.searchSuggestCondition = conditionMultiList
238
- // todo: 列表和弹窗 还有一个子分类,弹窗不进行合计调用
239
- if (inputMode) {
240
- return
241
- }
242
- // 处于列表中,还是处于基础资料的弹窗中,不同的地方在于,列表会进行合计,弹窗则会仅仅筛选已经审核的数据
243
- // 以上逻辑在后端,前端仅仅需要传querytype的参数
244
- this.queryType === 'LIST'
245
- ? this.getTableData(false, true)
246
- : this.getTableData(false, false)
247
- },
248
- /**
249
- * 创建一个高级过滤条件
250
- * @param {object} fieldObj 后端传递给前端的列表布局中一个字段的配置信息
251
- * @param {*} value 高级过滤条件字段
252
- * @param {boolean} isStrict 条件是否是严格匹配 "等于" 否则采用模糊匹配 "包含"
253
- * @param {boolean} isAndRelation and还是or sql中多个条件的分隔符号
254
- * @returns
255
- */
256
- createMultiCondition (fieldObj, value, isStrict = true, isAndRelation = true) {
257
- // isSuggest
258
- const relation = isAndRelation ? 'AND' : 'OR'
259
- const operator = getOperator(fieldObj.componentValueType, isStrict)?.value
260
- return {
261
- leftBracket: '(',
262
- field: fieldObj.field,
263
- fieldType: fieldObj.componentType,
264
- operator,
265
- sort: '',
266
- value,
267
- rightBracket: ')',
268
- relation
269
- }
270
- },
271
- // 每页条数变化
272
- handleSizeChange (newSize) {
273
- this.query.pageSize = newSize
274
- this.query.pageNum = 1
275
- this.getTableData(false, false)
276
- },
277
- // 翻页
278
- handleCurrentChange (newNum) {
279
- this.query.pageNum = newNum
280
- this.getTableData(false, false)
281
- },
282
- // 分组条件改变
283
- handleGroupChange (group) {
284
- this.query.conditionGroup = group
285
- this.getTableData(false, true)
286
- },
287
- // 表头快捷过滤条件变更
288
- handleHeadChange (newHeadCondition) {
289
- this.query.conditionQuickList = newHeadCondition
290
- this.getTableData(false, true)
291
- }
292
- }
293
- }
package/src/utils/auth.js DELETED
@@ -1,22 +0,0 @@
1
- const TOKEN = 'token' // 用户token
2
- // const RETOKEN = 'RefreshToken' // 刷线token
3
-
4
- // 设置用户token
5
- export function setToken (token) {
6
- localStorage.setItem(TOKEN, token)
7
- }
8
-
9
- // 清除用户token
10
- export function removeToken () {
11
- localStorage.removeItem(TOKEN)
12
- }
13
-
14
- // 更新token
15
- export function changeToken (token) {
16
- localStorage.setItem(TOKEN, token)
17
- }
18
-
19
- // 获取用户token
20
- export function getToken () {
21
- return localStorage.getItem(TOKEN)
22
- }
@@ -1,42 +0,0 @@
1
- import axios from 'axios'
2
- import { statusCode } from './stato-anormale'
3
- import { Base64 } from 'js-base64'
4
- import { getToken } from '@/utils/auth'
5
- import { Message } from 'element-ui'
6
- const clientId = 'tongfuncloud_web'
7
- const clientSecret = 'tongfuncloud_web_secret'
8
- axios.defaults.headers['Content-type'] = 'application/json'
9
-
10
- const service = axios.create({
11
- withCredentials: true, // send cookies when cross-domain requests
12
- timeout: 15000 // request timeout
13
- })
14
- // request interceptor
15
- service.interceptors.request.use(
16
- config => {
17
- config.headers['client-type'] = 'WEB'
18
- config.headers.token = 'Bearer ' + getToken()
19
- config.headers.Authorization = `Basic ${Base64.encode(`${clientId}:${clientSecret}`)}`
20
- // 测试组件时使用下方头部信息,过期则修改后再测试
21
- // config.headers.token = 'Bearer eyJ0eXAiOiJKc29uV2ViVG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJtb2JpbGUiOiIxMzE1MTYyODY1NyIsIm5hbWUiOiLmnLHmmI7mmI4iLCJ0b2tlbl90eXBlIjoidG9rZW4iLCJwVXNlcmlkIjoiMTM2ODg0NjcxOTU3OTU4NjU2MSIsInVzZXJpZCI6IjE0MTczNjg0NjMwODg4MTIwMzIiLCJ0ZW5hbnQiOiIwMDAxIiwiYWNjb3VudCI6InpodW1pbmdtaW5nIiwiaWF0IjoxNjM2MDgxNzM1LCJuYmYiOjE2MzYwODE3MzUsImV4cCI6MTYzNjExMDUzNX0.TTSbWUYTOd6znNko8sNyKz9KqLyeyO5AC4WgBvVNvBo'
22
- // config.headers.Authorization = 'Basic dG9uZ2Z1bmNsb3VkX3dlYjp0b25nZnVuY2xvdWRfd2ViX3NlY3JldA=='
23
- return config
24
- },
25
- error => {
26
- return Promise.reject(error)
27
- }
28
- )
29
- service.interceptors.response.use(
30
- response => {
31
- return response.data
32
- },
33
- error => {
34
- const { response } = error
35
- if (response.status === 400) {
36
- return Message.error(response.data.msg)
37
- }
38
- if (statusCode[response.data.code]) Message.error(statusCode[response.data.code])
39
- }
40
- )
41
-
42
- export default service
@@ -1,59 +0,0 @@
1
- export const statusCode = {
2
- '-2': '系统繁忙~请稍后再试~',
3
- '-3': '参数类型解析异常',
4
- '-4': '运行SQL出现异常',
5
- '-5': '空指针异常',
6
- '-6': '无效参数异常',
7
- '-7': '请求类型异常',
8
- '-8': '加载资源出错',
9
- '-9': '统一验证参数异常',
10
- '-10': '操作异常',
11
- '-11': 'Mapper类转换异常',
12
- '-12': '验证码校验失败',
13
- '-13': 'JSON解析异常',
14
- 401: '未认证',
15
- 403: '被禁止',
16
- 404: '未找到资源',
17
- 405: '不支持当前请求类型',
18
- 429: '请求超过次数限制',
19
- 500: '内部服务错误',
20
- 502: '网关出错啦!',
21
- 504: '请求网关超时',
22
- 1001: '请求中必须至少包含一个有效文件',
23
- 2000: '新增数据失败!',
24
- 2001: '修改数据失败!',
25
- 2002: '批量新增数据过多!',
26
- 40000: '无效的基本身份验证令牌',
27
- 40001: '会话超时,请重新登录!',
28
- 40002: '不合法的token,请认真比对 token 的签名!',
29
- 40003: '缺少token参数!',
30
- 40004: '生成token失败!',
31
- 40005: '解析用户身份错误,请重新登录!',
32
- 40006: '用户名或密码错误!',
33
- 40007: '用户已经被禁用!',
34
- 40008: '您已在另一个设备登录!',
35
- 40009: '请先登录!',
36
- 40029: '无效的oauth_code!',
37
- 41027: '账号与密码不匹配,请重新输入!',
38
- 41028: '该账户已被禁用,请联系平台客服!',
39
- 41029: '用户不存在!',
40
- 41030: '参数异常!',
41
- 41031: '注册方式错误!',
42
- 41032: '用户已存在但未认证!',
43
- 41034: '手机号已被其他用户绑定!',
44
- 41035: '短信验证码输入错误!',
45
- 41036: '邮箱验证码输入错误!',
46
- 41037: '图形验证码验证错误!',
47
- 41040: '新增数据失败!',
48
- 41041: '修改数据失败!',
49
- 41042: '身份证号码不合法!',
50
- 41043: '用户实名认证次数超过限制,请联系客服!',
51
- 41044: '该身份证号码已被绑定,请联系客服!',
52
- 41045: '身份验证失败!',
53
- 41046: '姓名和身份证号不一致!',
54
- 41100: '该企业中不存在你的用户信息,请核实你的租户信息!',
55
- 41101: '你已被所在的租户禁止进入!',
56
- 41105: '租户信息不存在!',
57
- 49000: 'token转换获取失败!',
58
- 49001: '验证码错误!'
59
- }