@oinone/kunlun-vue-admin-base 6.3.4 → 6.3.6

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 (34) hide show
  1. package/dist/oinone-kunlun-vue-admin-base.css +1 -1
  2. package/dist/oinone-kunlun-vue-admin-base.esm.js +2224 -1695
  3. package/dist/oinone-kunlun-vue-admin-base.scss +1 -1
  4. package/dist/types/src/basic/BaseI18nRouterWidget.d.ts +1 -1
  5. package/dist/types/src/icon-manage/view/search/IconSearch.vue.d.ts +20 -0
  6. package/dist/types/src/provider/RootWidget.d.ts +3 -2
  7. package/dist/types/src/service/user/UserService.d.ts +2 -2
  8. package/dist/types/src/view/login/BaseLoginWidget.d.ts +58 -0
  9. package/dist/types/src/view/login/LoginWidget.d.ts +3 -56
  10. package/dist/types/src/view/login/SSOLogin.vue.d.ts +154 -0
  11. package/dist/types/src/view/login/SSOLoginWidget.d.ts +12 -0
  12. package/dist/types/src/view/login/index.d.ts +2 -0
  13. package/dist/types/src/view/search/DefaultSearch.vue.d.ts +20 -0
  14. package/dist/types/src/view/search/DefaultSearchTab.vue.d.ts +6 -0
  15. package/dist/types/src/view/search/SearchTabWidget.d.ts +1 -0
  16. package/dist/types/src/view/search/SearchWidget.d.ts +3 -0
  17. package/dist/types/src/view/search/types.d.ts +9 -0
  18. package/package.json +8 -8
  19. package/src/basic/BaseI18nRouterWidget.ts +1 -1
  20. package/src/provider/RootWidget.ts +9 -3
  21. package/src/service/user/UserService.ts +11 -4
  22. package/src/view/login/BaseLoginWidget.ts +278 -0
  23. package/src/view/login/LoginWidget.ts +6 -272
  24. package/src/view/login/SSOLogin.vue +312 -0
  25. package/src/view/login/SSOLoginWidget.ts +103 -0
  26. package/src/view/login/index.ts +2 -0
  27. package/src/view/reset-password/ForgetPasswordWidget.ts +5 -1
  28. package/src/view/reset-password/style/index.scss +2 -2
  29. package/src/view/search/DefaultSearch.vue +25 -23
  30. package/src/view/search/DefaultSearchTab.vue +9 -1
  31. package/src/view/search/SearchTabWidget.ts +8 -3
  32. package/src/view/search/SearchWidget.ts +16 -1
  33. package/src/view/search/style/index.scss +31 -9
  34. package/src/view/search/types.ts +9 -0
@@ -0,0 +1,312 @@
1
+ <template>
2
+ <div class="login-page" :style="loginContainerStyle" :key="node_code">
3
+ <video
4
+ ref="videoRef"
5
+ loop
6
+ autoplay
7
+ muted
8
+ class="login-page-strick-video"
9
+ v-if="isVideoBackground && !isStandLayout"
10
+ :controls="false"
11
+ :src="backgroundImage"
12
+ ></video>
13
+
14
+ <!-- logo在页面左上角 -->
15
+ <div class="login-page-container-img" v-if="logoInLeft" :style="logoStyle">
16
+ <img v-if="loginPageLogo" :src="loginPageLogo" alt="logo" />
17
+ </div>
18
+
19
+ <div class="login-page-container" @keyup.enter="login" :style="loginBlockStyle">
20
+ <div v-if="enableI18n && currentLanguage && currentLanguage.name" class="login-language-wrapper">
21
+ <a-dropdown>
22
+ <div class="login-language-current-row">
23
+ <oio-icon icon="oinone-a-yuyanxuanze4x" size="14" color="var(--oio-text-color-secondary)" />
24
+ <span class="login-language-current">{{ currentLanguage.name }}</span>
25
+ <oio-icon icon="oinone-zhutixiala" size="10" color="var(--oio-text-color-secondary)" />
26
+ </div>
27
+ <template #overlay>
28
+ <a-menu>
29
+ <a-menu-item v-for="language in languages" :key="language.code" @click="() => onLanguageChange(language)">
30
+ {{ language.name }}
31
+ </a-menu-item>
32
+ </a-menu>
33
+ </template>
34
+ </a-dropdown>
35
+ </div>
36
+
37
+ <!-- 账号登录 -->
38
+ <div class="login-page-title">{{ translateValueByKey(accountLoginLabel) }}</div>
39
+ <oio-form :data="authForm" class="login-page-form">
40
+ <oio-form-item
41
+ name="login"
42
+ :help="error['login']"
43
+ :validateStatus="error['login'] || error['password'] ? 'error' : ''"
44
+ >
45
+ <oio-input
46
+ class="login-input"
47
+ :placeholder="translateValueByKey(accountPlaceholder)"
48
+ v-model:value="authForm.login"
49
+ @blur="loginBlur"
50
+ @change="clearErrorMessage"
51
+ >
52
+ <template #prefix>
53
+ <user-outlined />
54
+ </template>
55
+ </oio-input>
56
+ </oio-form-item>
57
+ <oio-form-item
58
+ name="password"
59
+ :help="error['password']"
60
+ :validateStatus="error['login'] || error['password'] ? 'error' : ''"
61
+ >
62
+ <a-input-password
63
+ class="login-input"
64
+ :placeholder="translateValueByKey(passwordPlaceholder)"
65
+ v-model:value="authForm.password"
66
+ @change="clearErrorMessage"
67
+ >
68
+ <template #prefix>
69
+ <lock-outlined />
70
+ </template>
71
+ </a-input-password>
72
+ </oio-form-item>
73
+ </oio-form>
74
+ <oio-button type="primary" block @click="login">{{ translateValueByKey(loginLabel) }}</oio-button>
75
+ </div>
76
+ <div
77
+ class="login-page-ugly-bg"
78
+ v-if="isStandLayout"
79
+ :style="{
80
+ backgroundImage: `url(${backgroundImage})`
81
+ }"
82
+ >
83
+ <video
84
+ ref="videoRef"
85
+ loop
86
+ autoplay
87
+ muted
88
+ class="login-page-video"
89
+ v-if="isVideoBackground"
90
+ :controls="false"
91
+ :src="backgroundImage"
92
+ ></video>
93
+ </div>
94
+
95
+ <div class="login-page-footer" v-if="copyrightStatus">
96
+ <div>
97
+ Copyrights ©{{ copyright.year }}
98
+ <span style="cursor: pointer" @click="onCompanyUrl">{{ translateValueByKey(copyright.company) }}</span>
99
+ </div>
100
+ <div>{{ copyright.icp }}</div>
101
+ </div>
102
+ </div>
103
+ </template>
104
+ <script lang="ts" setup>
105
+ import { LockOutlined, UserOutlined } from '@ant-design/icons-vue';
106
+ import {
107
+ genStaticPath,
108
+ getCopyrightStatus,
109
+ OioLoginLogoPosition,
110
+ OioLoginThemeConfig,
111
+ OioLoginThemeName,
112
+ translateValueByKey
113
+ } from '@oinone/kunlun-engine';
114
+ import { OioButton, OioForm, OioFormItem, OioIcon, OioInput, VIDEO_SUFFIX_LIST } from '@oinone/kunlun-vue-ui-antd';
115
+ import { LoginData, RuntimeLanguage } from '@oinone/kunlun-vue-ui-common';
116
+ import {
117
+ Dropdown as ADropdown,
118
+ InputPassword as AInputPassword,
119
+ Menu as AMenu,
120
+ MenuItem as AMenuItem
121
+ } from 'ant-design-vue';
122
+ import { computed, defineProps, nextTick, onActivated, PropType, ref } from 'vue';
123
+
124
+ const props = defineProps({
125
+ loginMethod: { type: String, required: true },
126
+ loginUrl: { type: String, required: true },
127
+ login: { type: Function as PropType<() => void>, required: true },
128
+ loginBlur: { type: Function as PropType<() => void>, required: false },
129
+ error: { type: Object as PropType<LoginData>, required: true },
130
+ clearErrorMessage: { type: Function as PropType<() => void>, required: true },
131
+ authForm: { type: Object as PropType<LoginData>, required: true },
132
+ copyrightYear: { type: [Number, String], required: true },
133
+ currentLoginTheme: { type: Object, required: true },
134
+ systemMajorConfig: { type: Object as PropType<Record<string, any>>, required: true },
135
+ loginLabel: { type: String, required: true },
136
+ accountLoginLabel: { type: String, required: true },
137
+ accountPlaceholder: { type: String, required: true },
138
+ passwordPlaceholder: { type: String, required: true },
139
+ enableI18n: { type: Boolean },
140
+ languages: { type: Array as PropType<RuntimeLanguage[]>, required: true },
141
+ currentLanguage: { type: Object as PropType<RuntimeLanguage>, required: true },
142
+ onLanguageChange: { type: Function as PropType<(language: RuntimeLanguage) => void>, required: true },
143
+ node_code: String
144
+ });
145
+
146
+ const videoRef = ref<HTMLVideoElement>();
147
+
148
+ onActivated(() => {
149
+ nextTick(() => {
150
+ if (videoRef.value) {
151
+ videoRef.value.play();
152
+ }
153
+ });
154
+ });
155
+
156
+ /**
157
+ * 有大背景图,并且左侧布局
158
+ */
159
+ const useCenteredKeepLeft = {
160
+ justifyContent: 'flex-start',
161
+ paddingLeft: '14%'
162
+ };
163
+
164
+ /**
165
+ * 有大背景图,并且右侧布局
166
+ */
167
+ const useCenteredKeepRight = {
168
+ justifyContent: 'flex-end',
169
+ paddingRight: '14%'
170
+ };
171
+
172
+ /**
173
+ * logo的样式
174
+ */
175
+ const logoStyle = computed(() => {
176
+ return loginThemeConfig.value.logoPosition === OioLoginLogoPosition.LEFT ? { left: '60px' } : { right: '60px' };
177
+ });
178
+
179
+ /**
180
+ * 背景图
181
+ */
182
+ const backgroundImage = computed(() => {
183
+ return loginThemeConfig.value.backgroundImage;
184
+ });
185
+
186
+ /**
187
+ * logo
188
+ */
189
+ const loginPageLogo = computed(() => loginThemeConfig.value.logo || '');
190
+
191
+ /**
192
+ * 当前背景图是不是视频
193
+ */
194
+ const isVideoBackground = computed(() => {
195
+ if (backgroundImage.value) {
196
+ const isVideo = !!VIDEO_SUFFIX_LIST.find((suffix) => backgroundImage.value.endsWith(suffix));
197
+
198
+ return isVideo;
199
+ }
200
+
201
+ return false;
202
+ });
203
+
204
+ /**
205
+ * 默认背景图样式
206
+ */
207
+ const useCenteredStyle = computed(() => {
208
+ return {
209
+ display: 'flex',
210
+ justifyContent: 'center',
211
+ alignItems: 'center',
212
+ backgroundImage: isVideoBackground.value ? '' : `url(${backgroundImage.value})`
213
+ };
214
+ });
215
+
216
+ /**
217
+ * 登录页的样式
218
+ */
219
+ const loginContainerStyle = computed(() => {
220
+ const { name, backgroundColor } = loginThemeConfig.value;
221
+ let style = {
222
+ display: 'flex',
223
+ justifyContent: 'space-between',
224
+ alignItems: 'center',
225
+ backgroundColor
226
+ };
227
+
228
+ switch (name) {
229
+ case 'CENTER_STICK':
230
+ case 'CENTER_STICK_LOGO':
231
+ style = Object.assign(style, useCenteredStyle.value);
232
+ break;
233
+ case 'LEFT_STICK':
234
+ style = Object.assign(style, useCenteredStyle.value, useCenteredKeepLeft);
235
+ break;
236
+ case 'RIGHT_STICK':
237
+ style = Object.assign(style, useCenteredStyle.value, useCenteredKeepRight);
238
+ break;
239
+ case 'STAND_RIGHT':
240
+ style = Object.assign(style, {
241
+ flexDirection: 'row-Reverse'
242
+ });
243
+ break;
244
+ default:
245
+ break;
246
+ }
247
+
248
+ return style;
249
+ });
250
+
251
+ /**
252
+ * logo 是否显示在页面左侧
253
+ */
254
+ const logoInLeft = computed(() => {
255
+ return (
256
+ loginThemeConfig.value.logoPosition !== OioLoginLogoPosition.CENTER &&
257
+ loginThemeConfig.value.name !== OioLoginThemeName.CENTER_STICK_LOGO
258
+ );
259
+ });
260
+
261
+ const isStandLayout = computed(() => {
262
+ return [OioLoginThemeName.STAND_LEFT, OioLoginThemeName.STAND_RIGHT].includes(loginThemeConfig.value.name);
263
+ });
264
+
265
+ /**
266
+ * 登录form表单的样式
267
+ */
268
+ const loginBlockStyle = computed(() => {
269
+ const style: Record<string, string> = {};
270
+ const { name } = loginThemeConfig.value;
271
+ if ([OioLoginThemeName.STAND_LEFT, OioLoginThemeName.STAND_RIGHT].includes(name)) {
272
+ style.boxShadow = 'none';
273
+ style.margin = '0 150px';
274
+ }
275
+
276
+ return style;
277
+ });
278
+
279
+ /**
280
+ * 登录主题配置
281
+ */
282
+ const loginThemeConfig = computed<Required<OioLoginThemeConfig>>(() => {
283
+ const name = props.currentLoginTheme.name || OioLoginThemeName.STAND_RIGHT;
284
+ const defaultImage = [OioLoginThemeName.STAND_LEFT, OioLoginThemeName.STAND_RIGHT].includes(name)
285
+ ? genStaticPath('login_bg_left.jpg')
286
+ : genStaticPath('login_big_image@2x-1.png');
287
+
288
+ return {
289
+ name,
290
+ backgroundImage: props.currentLoginTheme.backgroundImage || defaultImage,
291
+ backgroundColor: props.currentLoginTheme.backgroundColor!,
292
+ logo: props.currentLoginTheme.logo,
293
+ logoPosition: props.currentLoginTheme.logoPosition || OioLoginLogoPosition.LEFT
294
+ };
295
+ });
296
+
297
+ const copyrightStatus = getCopyrightStatus();
298
+
299
+ const copyright = computed(() => {
300
+ return {
301
+ year: props.copyrightYear || '',
302
+ company: props.systemMajorConfig?.partnerName || '',
303
+ icp: props.systemMajorConfig?.icpDesc || ''
304
+ };
305
+ });
306
+
307
+ const onCompanyUrl = () => {
308
+ if (props.systemMajorConfig.officialWebsite) {
309
+ window.open(props.systemMajorConfig.officialWebsite, '_blank');
310
+ }
311
+ };
312
+ </script>
@@ -0,0 +1,103 @@
1
+ import { translateValueByKey } from '@oinone/kunlun-engine';
2
+ import { UrlHelper } from '@oinone/kunlun-shared';
3
+ import { SPI } from '@oinone/kunlun-spi';
4
+ import { RouterWidget } from '@oinone/kunlun-vue-router';
5
+ import { Widget } from '@oinone/kunlun-vue-widget';
6
+ import { BaseLoginWidget } from './BaseLoginWidget';
7
+ import SSOLogin from './SSOLogin.vue';
8
+
9
+ @SPI.ClassFactory(
10
+ RouterWidget.Token({
11
+ widget: 'sso-login'
12
+ })
13
+ )
14
+ export class SSOLoginWidget extends BaseLoginWidget {
15
+ public initialize(props) {
16
+ super.initialize(props);
17
+ this.setComponent(SSOLogin);
18
+ return this;
19
+ }
20
+
21
+ protected get keyMapping(): Record<string, string> {
22
+ return {
23
+ login: 'username',
24
+ client_id: 'clientId',
25
+ redirect_uri: 'redirectUri'
26
+ };
27
+ }
28
+
29
+ protected mappingForKey(key: string): string {
30
+ return this.keyMapping[key] || key;
31
+ }
32
+
33
+ @Widget.Reactive()
34
+ protected get loginMethod(): string {
35
+ return 'POST';
36
+ }
37
+
38
+ @Widget.Reactive()
39
+ protected get loginUrl() {
40
+ return UrlHelper.appendBasePath('/pamirs/sso/oauth2/login');
41
+ }
42
+
43
+ @Widget.Method()
44
+ public async login() {
45
+ const rst = await this.beforeClick();
46
+ if (!rst) {
47
+ return;
48
+ }
49
+
50
+ const { login, password } = this.authForm;
51
+ if (!login || !password) {
52
+ this.error.login = login ? '' : translateValueByKey(this.errorMessages.loginEmpty);
53
+ this.error.password = password ? '' : translateValueByKey(this.errorMessages.passwordEmpty);
54
+ return;
55
+ }
56
+
57
+ const formData: Record<string, string> = {};
58
+ formData[this.mappingForKey('login')] = login;
59
+ formData[this.mappingForKey('password')] = password;
60
+ Object.entries(this.getUrlParameters()).forEach(([key, value]) => {
61
+ if (key === 'error') {
62
+ return;
63
+ }
64
+ formData[this.mappingForKey(key)] = value;
65
+ });
66
+ this.submitLoginFormData(formData);
67
+ }
68
+
69
+ protected submitLoginFormData(formData: Record<string, string>) {
70
+ // 1. 创建 form 元素
71
+ const form = document.createElement('form');
72
+ form.action = this.loginUrl; // 提交的目标地址(服务端可能返回 302 重定向)
73
+ form.method = this.loginMethod; // 提交方法(POST/GET)
74
+ form.style.display = 'none'; // 隐藏表单
75
+
76
+ // 2. 添加表单数据(键值对)
77
+ Object.entries(formData).forEach(([key, value]) => {
78
+ const input = document.createElement('input');
79
+ input.name = key; // 字段名
80
+ input.value = value; // 字段值
81
+ form.appendChild(input);
82
+ });
83
+
84
+ // 3. 将表单添加到页面并提交
85
+ document.body.appendChild(form);
86
+ form.submit(); // 触发提交,浏览器会自动处理 302 重定向
87
+
88
+ // 4. 清理(可选,提交后页面会跳转,可能无需清理)
89
+ document.body.removeChild(form);
90
+ }
91
+
92
+ protected getUrlParameters(): Record<string, string> {
93
+ return this.matched?.segmentParams['sso-login'] || {};
94
+ }
95
+
96
+ protected async beforeMount() {
97
+ await super.beforeMount();
98
+ const { error } = this.getUrlParameters();
99
+ if (error) {
100
+ this.error.password = error;
101
+ }
102
+ }
103
+ }
@@ -1 +1,3 @@
1
+ export * from './BaseLoginWidget';
1
2
  export * from './LoginWidget';
3
+ export * from './SSOLoginWidget';
@@ -101,7 +101,11 @@ export class ForgetPasswordWidget extends BaseI18nRouterWidget {
101
101
  if (!phone) {
102
102
  return false;
103
103
  }
104
- const { broken, errorMsg } = await UserService.fetchVerificationCodeByForget(phone);
104
+ const { broken, errorMsg } = await UserService.fetchVerificationCodeByForget(
105
+ phone,
106
+ undefined,
107
+ this.selectedCountry?.data?.phoneCode
108
+ );
105
109
  if (broken) {
106
110
  if (errorMsg) {
107
111
  OioMessage.error(errorMsg);
@@ -66,7 +66,7 @@
66
66
  background: #fafafc;
67
67
  }
68
68
 
69
- .ant-input-affix-wrapper {
69
+ .oio-input.ant-input-affix-wrapper {
70
70
  background-color: #fafafc;
71
71
  border-radius: 4px;
72
72
  border: solid 1px #e6e6e6;
@@ -86,7 +86,7 @@
86
86
  }
87
87
  }
88
88
 
89
- .ant-input-affix-wrapper > input.ant-input {
89
+ .oio-input.ant-input-affix-wrapper > input.ant-input {
90
90
  height: 46px !important;
91
91
  box-shadow: 0 0 0 1000px #fafafc inset;
92
92
  background-color: #fafafc;
@@ -165,6 +165,7 @@ function createSearchBar(
165
165
  type: ButtonType.link,
166
166
  iconPlacement: IconPlacement.AFTER,
167
167
  icon: 'oinone-xiala',
168
+ iconColor: 'var(--oio-primary-color)',
168
169
  onClick: options.onExpand
169
170
  },
170
171
  { default: () => expandText }
@@ -241,7 +242,7 @@ export default defineComponent({
241
242
  let invisible = false;
242
243
  let hasExpandButton = false;
243
244
 
244
- if (props.template && !props.disabledExpand) {
245
+ if (props.template) {
245
246
  const { widgets } = props.template;
246
247
  if (widgets && widgets.length) {
247
248
  let fields: DslDefinition[] = [];
@@ -253,18 +254,22 @@ export default defineComponent({
253
254
  cateFields: props.cateFields,
254
255
  dslNodeType: DslDefinitionType.ELEMENT,
255
256
  widget: 'SearchTab',
256
- widgets: cateWidgets
257
+ widgets: cateWidgets,
258
+ showTopCateAll: props.showTopCateAll,
259
+ showSecondCateAll: props.showSecondCateAll,
260
+ topCateJustify: props.topCateJustify
257
261
  })!
258
262
  );
259
263
  }
260
264
 
261
- const finalExpandSize = props.invisibleSearch ? props.foldSize + 1 : props.foldSize;
262
- appendFieldDslDefinition(fields, widgets, finalExpandSize, props.foldSize, props.cateFields);
263
- if (fields.length) {
265
+ if (!props.disabledExpand) {
266
+ const finalExpandSize = props.invisibleSearch ? props.foldSize + 1 : props.foldSize;
267
+ appendFieldDslDefinition(fields, widgets, finalExpandSize, props.foldSize, props.cateFields);
264
268
  hasExpandButton = fields.length > finalExpandSize;
265
269
  if (hasExpandButton) {
266
270
  fields = fields.slice(0, finalExpandSize);
267
271
  }
272
+
268
273
  if (!props.invisibleSearch) {
269
274
  const searchActionBar: VNode[] = createSearchBar(false, {
270
275
  hasExpandButton,
@@ -294,25 +299,22 @@ export default defineComponent({
294
299
  );
295
300
  fields.push(searchBarCol);
296
301
  }
297
- } else {
298
- hasExpandButton = false;
299
- fields = widgets;
302
+ defaultChildren.push(
303
+ withDirectives(
304
+ DslRender.render({
305
+ internal: true,
306
+ dslNodeType: DslDefinitionType.PACK,
307
+ widgets: fields,
308
+ widget: InternalWidget.Row,
309
+ cols: DEFAULT_COLS,
310
+ resolveOptions: {
311
+ mode: ResolveMode.NORMAL
312
+ }
313
+ })!,
314
+ [[vShow, !props.isExpand]]
315
+ )
316
+ );
300
317
  }
301
- defaultChildren.push(
302
- withDirectives(
303
- DslRender.render({
304
- internal: true,
305
- dslNodeType: DslDefinitionType.PACK,
306
- widgets: fields,
307
- widget: InternalWidget.Row,
308
- cols: DEFAULT_COLS,
309
- resolveOptions: {
310
- mode: ResolveMode.NORMAL
311
- }
312
- })!,
313
- [[vShow, !props.isExpand]]
314
- )
315
- );
316
318
  }
317
319
  }
318
320
 
@@ -27,6 +27,9 @@ export default defineComponent({
27
27
  type: Array as PropType<any[]>,
28
28
  default: () => []
29
29
  },
30
+ topCateJustify: {
31
+ type: String
32
+ },
30
33
  cateFields: {
31
34
  type: Array as PropType<string[]>
32
35
  },
@@ -104,11 +107,16 @@ export default defineComponent({
104
107
  render() {
105
108
  const cateSearchNodes = [] as VNode[];
106
109
  if (this.topCateFieldOptions?.length) {
110
+ const className = ['oio-cate-search'];
111
+ if (this.topCateJustify) {
112
+ className.push(`oio-cate-search-${this.topCateJustify.toLocaleLowerCase()}`);
113
+ }
114
+
107
115
  cateSearchNodes.push(
108
116
  createVNode(
109
117
  OioTabs,
110
118
  {
111
- class: 'oio-cate-search',
119
+ class: className,
112
120
  activeKey: this.topCateActive,
113
121
  'onUpdate:activeKey': (val) => (this.topCateActive = val),
114
122
  onChange: this.onChangeTopCate
@@ -2,7 +2,7 @@ import { SPI } from '@oinone/kunlun-spi';
2
2
  import { IModelField, IModelFieldOption, ModelFieldType, ViewType } from '@oinone/kunlun-meta';
3
3
  import { Widget } from '@oinone/kunlun-vue-widget';
4
4
  import { ActiveRecord, RuntimeModelField } from '@oinone/kunlun-engine';
5
- import { BooleanHelper, CallChaining } from '@oinone/kunlun-shared';
5
+ import { BooleanHelper, CallChaining, Optional } from '@oinone/kunlun-shared';
6
6
  import DefaultSearchTab from './DefaultSearchTab.vue';
7
7
  import { BaseElementWidget } from '../../basic';
8
8
  import { CATE_ALL_OPTION } from './types';
@@ -43,7 +43,7 @@ export class SearchTabWidget extends BaseElementWidget {
43
43
 
44
44
  @Widget.Reactive()
45
45
  protected get showTopCateAll(): boolean {
46
- return BooleanHelper.toBoolean(this.getDsl().showTopCateAll) || true;
46
+ return Optional.ofNullable(BooleanHelper.toBoolean(this.getDsl().showTopCateAll)).orElse(true);
47
47
  }
48
48
 
49
49
  @Widget.Reactive()
@@ -64,9 +64,14 @@ export class SearchTabWidget extends BaseElementWidget {
64
64
  );
65
65
  }
66
66
 
67
+ @Widget.Reactive()
68
+ protected get topCateJustify(): string | undefined {
69
+ return this.getDsl().topCateJustify;
70
+ }
71
+
67
72
  @Widget.Reactive()
68
73
  protected get showSecondCateAll(): boolean {
69
- return BooleanHelper.toBoolean(this.getDsl().showSecondCateAll) || true;
74
+ return Optional.ofNullable(BooleanHelper.toBoolean(this.getDsl().showSecondCateAll)).orElse(true);
70
75
  }
71
76
 
72
77
  @Widget.Reactive()
@@ -6,7 +6,7 @@ import {
6
6
  } from '@oinone/kunlun-engine';
7
7
  import { Entity, ViewType } from '@oinone/kunlun-meta';
8
8
  import { getRouterInstance } from '@oinone/kunlun-router';
9
- import { BooleanHelper, NumberHelper } from '@oinone/kunlun-shared';
9
+ import { BooleanHelper, NumberHelper, Optional } from '@oinone/kunlun-shared';
10
10
  import { SPI } from '@oinone/kunlun-spi';
11
11
  import { OioMessage } from '@oinone/kunlun-vue-ui-antd';
12
12
  import { isAllInvisible, Widget } from '@oinone/kunlun-vue-widget';
@@ -57,6 +57,21 @@ export class SearchWidget extends BaseSearchWidget {
57
57
  return [topCateField, secondCateField];
58
58
  }
59
59
 
60
+ @Widget.Reactive()
61
+ protected get topCateJustify(): string | undefined {
62
+ return this.getDsl().topCateJustify;
63
+ }
64
+
65
+ @Widget.Reactive()
66
+ protected get showTopCateAll(): boolean {
67
+ return Optional.ofNullable(BooleanHelper.toBoolean(this.getDsl().showTopCateAll)).orElse(true);
68
+ }
69
+
70
+ @Widget.Reactive()
71
+ protected get showSecondCateAll(): boolean {
72
+ return Optional.ofNullable(BooleanHelper.toBoolean(this.getDsl().showSecondCateAll)).orElse(true);
73
+ }
74
+
60
75
  public initialize(props) {
61
76
  super.initialize(props);
62
77
  this.setComponent(DefaultSearch);
@@ -10,10 +10,29 @@ $labelMarginRight: 16px;
10
10
  box-shadow: none;
11
11
  margin-bottom: var(--oio-margin-md);
12
12
  height: auto;
13
- &.oio-tabs.ant-tabs-top .ant-tabs-nav .ant-tabs-tab {
14
- padding: var(--oio-padding-md) 0;
15
- font-size: var(--oio-font-size-lg);
16
- font-weight: bold;
13
+
14
+ &.oio-cate-search-center {
15
+ .ant-tabs-nav-wrap {
16
+ justify-content: center;
17
+ }
18
+ }
19
+
20
+ &.oio-cate-search-end {
21
+ .ant-tabs-nav-wrap {
22
+ justify-content: end;
23
+ }
24
+ }
25
+ &.oio-tabs.ant-tabs-top {
26
+ .ant-tabs-tab + .ant-tabs-tab {
27
+ margin-left: 40px;
28
+ }
29
+
30
+ .ant-tabs-nav {
31
+ .ant-tabs-tab {
32
+ padding: var(--oio-padding-md) 0;
33
+ font-size: var(--oio-font-size-lg);
34
+ }
35
+ }
17
36
  }
18
37
  .ant-tabs-content-holder {
19
38
  display: none;
@@ -28,9 +47,8 @@ $labelMarginRight: 16px;
28
47
  padding: 0 var(--oio-padding-md);
29
48
  margin-right: var(--oio-margin-md);
30
49
  border-radius: var(--oio-border-radius);
31
- background: var(--oio-tag-select-background);
32
50
  font-size: var(--oio-font-size);
33
- color: var(--oio-text-color);
51
+ color: var(--oio-text-color-secondary);
34
52
  height: var(--oio-height);
35
53
  line-height: var(--oio-height);
36
54
  font-weight: 400;
@@ -39,10 +57,14 @@ $labelMarginRight: 16px;
39
57
  margin-right: 0;
40
58
  }
41
59
 
42
- &:hover,
60
+ &:hover {
61
+ background: var(--oio-hover-background-color);
62
+ color: var(--oio-hover-text-color);
63
+ }
64
+
43
65
  &.active {
44
- color: #fff;
45
- background: var(--oio-primary-color);
66
+ color: var(--oio-selected-text-color);
67
+ background: var(--oio-selected-background-color);
46
68
  }
47
69
  }
48
70
  }