1
0
Эх сурвалжийг харах

Merge branch 'main' into global-search

Li Kui 8 сар өмнө
parent
commit
1f4ec6369c
23 өөрчлөгдсөн 422 нэмэгдсэн , 19 устгасан
  1. 1 0
      cspell.json
  2. 1 0
      packages/@core/ui-kit/shadcn-ui/package.json
  3. 2 0
      packages/@core/ui-kit/shadcn-ui/src/components/index.ts
  4. 34 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/input/Input.vue
  5. 1 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/input/index.ts
  6. 28 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberField.vue
  7. 22 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldContent.vue
  8. 39 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldDecrement.vue
  9. 39 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldIncrement.vue
  10. 16 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldInput.vue
  11. 5 0
      packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/index.ts
  12. 51 0
      packages/business/widgets/src/preferences/blocks/input-item.vue
  13. 25 0
      packages/business/widgets/src/preferences/blocks/layout/copyright.vue
  14. 14 3
      packages/business/widgets/src/preferences/blocks/layout/sidebar.vue
  15. 0 3
      packages/business/widgets/src/preferences/blocks/layout/tabbar.vue
  16. 65 0
      packages/business/widgets/src/preferences/blocks/number-field-item.vue
  17. 1 1
      packages/business/widgets/src/preferences/blocks/select-item.vue
  18. 1 1
      packages/business/widgets/src/preferences/blocks/switch-item.vue
  19. 24 0
      packages/business/widgets/src/preferences/preferences-widget.vue
  20. 18 2
      packages/business/widgets/src/preferences/preferences.vue
  21. 12 5
      packages/locales/src/langs/en-US.yaml
  22. 11 4
      packages/locales/src/langs/zh-CN.yaml
  23. 12 0
      pnpm-lock.yaml

+ 1 - 0
cspell.json

@@ -9,6 +9,7 @@
     "taze",
     "acmr",
     "antd",
+    "lucide",
     "brotli",
     "defu",
     "iconify",

+ 1 - 0
packages/@core/ui-kit/shadcn-ui/package.json

@@ -49,6 +49,7 @@
     "@vben-core/typings": "workspace:*",
     "@vueuse/core": "^10.11.0",
     "class-variance-authority": "^0.7.0",
+    "lucide-vue-next": "^0.400.0",
     "radix-vue": "^1.9.0",
     "vue": "^3.4.31",
     "vue-sonner": "^1.1.3"

+ 2 - 0
packages/@core/ui-kit/shadcn-ui/src/components/index.ts

@@ -34,6 +34,8 @@ export * from './ui/checkbox';
 export * from './ui/dialog';
 export * from './ui/dropdown-menu';
 export * from './ui/hover-card';
+export * from './ui/input';
+export * from './ui/number-field';
 export * from './ui/pin-input';
 export * from './ui/popover';
 export * from './ui/scroll-area';

+ 34 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/input/Input.vue

@@ -0,0 +1,34 @@
+<script setup lang="ts">
+import type { HTMLAttributes } from 'vue';
+
+import { cn } from '@vben-core/toolkit';
+
+import { useVModel } from '@vueuse/core';
+
+const props = defineProps<{
+  class?: HTMLAttributes['class'];
+  defaultValue?: number | string;
+  modelValue?: number | string;
+}>();
+
+const emits = defineEmits<{
+  (e: 'update:modelValue', payload: number | string): void;
+}>();
+
+const modelValue = useVModel(props, 'modelValue', emits, {
+  defaultValue: props.defaultValue,
+  passive: true,
+});
+</script>
+
+<template>
+  <input
+    v-model="modelValue"
+    :class="
+      cn(
+        'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
+        props.class,
+      )
+    "
+  />
+</template>

+ 1 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/input/index.ts

@@ -0,0 +1 @@
+export { default as Input } from './Input.vue';

+ 28 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberField.vue

@@ -0,0 +1,28 @@
+<script setup lang="ts">
+import type { NumberFieldRootEmits, NumberFieldRootProps } from 'radix-vue';
+
+import { type HTMLAttributes, computed } from 'vue';
+
+import { cn } from '@vben-core/toolkit';
+
+import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue';
+
+const props = defineProps<
+  { class?: HTMLAttributes['class'] } & NumberFieldRootProps
+>();
+const emits = defineEmits<NumberFieldRootEmits>();
+
+const delegatedProps = computed(() => {
+  const { class: _, ...delegated } = props;
+
+  return delegated;
+});
+
+const forwarded = useForwardPropsEmits(delegatedProps, emits);
+</script>
+
+<template>
+  <NumberFieldRoot v-bind="forwarded" :class="cn('grid gap-1.5', props.class)">
+    <slot></slot>
+  </NumberFieldRoot>
+</template>

+ 22 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldContent.vue

@@ -0,0 +1,22 @@
+<script setup lang="ts">
+import type { HTMLAttributes } from 'vue';
+
+import { cn } from '@vben-core/toolkit';
+
+const props = defineProps<{
+  class?: HTMLAttributes['class'];
+}>();
+</script>
+
+<template>
+  <div
+    :class="
+      cn(
+        'relative [&>[data-slot=input]]:has-[[data-slot=decrement]]:pl-5 [&>[data-slot=input]]:has-[[data-slot=increment]]:pr-5',
+        props.class,
+      )
+    "
+  >
+    <slot></slot>
+  </div>
+</template>

+ 39 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldDecrement.vue

@@ -0,0 +1,39 @@
+<script setup lang="ts">
+import type { NumberFieldDecrementProps } from 'radix-vue';
+
+import { type HTMLAttributes, computed } from 'vue';
+
+import { cn } from '@vben-core/toolkit';
+
+import { Minus } from 'lucide-vue-next';
+import { NumberFieldDecrement, useForwardProps } from 'radix-vue';
+
+const props = defineProps<
+  { class?: HTMLAttributes['class'] } & NumberFieldDecrementProps
+>();
+
+const delegatedProps = computed(() => {
+  const { class: _, ...delegated } = props;
+
+  return delegated;
+});
+
+const forwarded = useForwardProps(delegatedProps);
+</script>
+
+<template>
+  <NumberFieldDecrement
+    data-slot="decrement"
+    v-bind="forwarded"
+    :class="
+      cn(
+        'absolute left-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20',
+        props.class,
+      )
+    "
+  >
+    <slot>
+      <Minus class="h-4 w-4" />
+    </slot>
+  </NumberFieldDecrement>
+</template>

+ 39 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldIncrement.vue

@@ -0,0 +1,39 @@
+<script setup lang="ts">
+import type { NumberFieldIncrementProps } from 'radix-vue';
+
+import { type HTMLAttributes, computed } from 'vue';
+
+import { cn } from '@vben-core/toolkit';
+
+import { Plus } from 'lucide-vue-next';
+import { NumberFieldIncrement, useForwardProps } from 'radix-vue';
+
+const props = defineProps<
+  { class?: HTMLAttributes['class'] } & NumberFieldIncrementProps
+>();
+
+const delegatedProps = computed(() => {
+  const { class: _, ...delegated } = props;
+
+  return delegated;
+});
+
+const forwarded = useForwardProps(delegatedProps);
+</script>
+
+<template>
+  <NumberFieldIncrement
+    data-slot="increment"
+    v-bind="forwarded"
+    :class="
+      cn(
+        'absolute right-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20',
+        props.class,
+      )
+    "
+  >
+    <slot>
+      <Plus class="h-4 w-4" />
+    </slot>
+  </NumberFieldIncrement>
+</template>

+ 16 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/NumberFieldInput.vue

@@ -0,0 +1,16 @@
+<script setup lang="ts">
+import { cn } from '@vben-core/toolkit';
+
+import { NumberFieldInput } from 'radix-vue';
+</script>
+
+<template>
+  <NumberFieldInput
+    :class="
+      cn(
+        'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent py-1 text-center text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
+      )
+    "
+    data-slot="input"
+  />
+</template>

+ 5 - 0
packages/@core/ui-kit/shadcn-ui/src/components/ui/number-field/index.ts

@@ -0,0 +1,5 @@
+export { default as NumberField } from './NumberField.vue';
+export { default as NumberFieldContent } from './NumberFieldContent.vue';
+export { default as NumberFieldDecrement } from './NumberFieldDecrement.vue';
+export { default as NumberFieldIncrement } from './NumberFieldIncrement.vue';
+export { default as NumberFieldInput } from './NumberFieldInput.vue';

+ 51 - 0
packages/business/widgets/src/preferences/blocks/input-item.vue

@@ -0,0 +1,51 @@
+<script setup lang="ts">
+import type { SelectListItem } from '@vben/types';
+
+import { useSlots } from 'vue';
+
+import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify';
+import { Input, VbenTooltip } from '@vben-core/shadcn-ui';
+
+defineOptions({
+  name: 'PreferenceSelectItem',
+});
+
+withDefaults(
+  defineProps<{
+    disabled?: boolean;
+    items?: SelectListItem[];
+    placeholder?: string;
+  }>(),
+  {
+    disabled: false,
+    placeholder: '',
+    items: () => [],
+  },
+);
+
+const inputValue = defineModel<string>();
+
+const slots = useSlots();
+</script>
+
+<template>
+  <div
+    :class="{
+      'hover:bg-accent': !slots.tip,
+      'pointer-events-none opacity-50': disabled,
+    }"
+    class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"
+  >
+    <span class="flex items-center text-sm">
+      <slot></slot>
+
+      <VbenTooltip v-if="slots.tip" side="bottom">
+        <template #trigger>
+          <MdiQuestionMarkCircleOutline class="ml-1 cursor-help" />
+        </template>
+        <slot name="tip"></slot>
+      </VbenTooltip>
+    </span>
+    <Input v-model="inputValue" class="h-8 w-[160px]" />
+  </div>
+</template>

+ 25 - 0
packages/business/widgets/src/preferences/blocks/layout/copyright.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { $t } from '@vben/locales';
 
+import InputItem from '../input-item.vue';
 import SwitchItem from '../switch-item.vue';
 
 defineOptions({
@@ -8,10 +9,34 @@ defineOptions({
 });
 
 const copyrightEnable = defineModel<boolean>('copyrightEnable');
+const copyrightDate = defineModel<string>('copyrightDate');
+const copyrightIcp = defineModel<string>('copyrightIcp');
+const copyrightIcpLink = defineModel<string>('copyrightIcpLink');
+const copyrightCompanyName = defineModel<string>('copyrightCompanyName');
+const copyrightCompanySiteLink = defineModel<string>(
+  'copyrightCompanySiteLink',
+);
 </script>
 
 <template>
   <SwitchItem v-model="copyrightEnable">
     {{ $t('preferences.copyright.enable') }}
   </SwitchItem>
+
+  <InputItem v-model="copyrightCompanyName" :disabled="!copyrightEnable">
+    {{ $t('preferences.copyright.company-name') }}
+  </InputItem>
+  <InputItem v-model="copyrightCompanySiteLink" :disabled="!copyrightEnable">
+    {{ $t('preferences.copyright.company-site-link') }}
+  </InputItem>
+  <InputItem v-model="copyrightDate" :disabled="!copyrightEnable">
+    {{ $t('preferences.copyright.date') }}
+  </InputItem>
+
+  <InputItem v-model="copyrightIcp" :disabled="!copyrightEnable">
+    {{ $t('preferences.copyright.icp') }}
+  </InputItem>
+  <InputItem v-model="copyrightIcpLink" :disabled="!copyrightEnable">
+    {{ $t('preferences.copyright.icp-link') }}
+  </InputItem>
 </template>

+ 14 - 3
packages/business/widgets/src/preferences/blocks/layout/sidebar.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { $t } from '@vben/locales';
 
+import NumberFieldItem from '../number-field-item.vue';
 import SwitchItem from '../switch-item.vue';
 
 defineOptions({
@@ -10,6 +11,7 @@ defineOptions({
 defineProps<{ disabled: boolean }>();
 
 const sidebarEnable = defineModel<boolean>('sidebarEnable');
+const sidebarWidth = defineModel<number>('sidebarWidth');
 const sidebarCollapsedShowTitle = defineModel<boolean>(
   'sidebarCollapsedShowTitle',
 );
@@ -18,15 +20,24 @@ const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
 
 <template>
   <SwitchItem v-model="sidebarEnable" :disabled="disabled">
-    {{ $t('preferences.side-visible') }}
+    {{ $t('preferences.sidebar.visible') }}
   </SwitchItem>
   <SwitchItem v-model="sidebarCollapsed" :disabled="!sidebarEnable || disabled">
-    {{ $t('preferences.collapse') }}
+    {{ $t('preferences.sidebar.collapsed') }}
   </SwitchItem>
   <SwitchItem
     v-model="sidebarCollapsedShowTitle"
     :disabled="!sidebarEnable || disabled"
   >
-    {{ $t('preferences.collapse-show-title') }}
+    {{ $t('preferences.sidebar.collapsed-show-title') }}
   </SwitchItem>
+  <NumberFieldItem
+    v-model="sidebarWidth"
+    :disabled="!sidebarEnable || disabled"
+    :max="320"
+    :min="160"
+    :step="10"
+  >
+    {{ $t('preferences.sidebar.width') }}
+  </NumberFieldItem>
 </template>

+ 0 - 3
packages/business/widgets/src/preferences/blocks/layout/tabbar.vue

@@ -20,7 +20,4 @@ const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
   <SwitchItem v-model="tabbarShowIcon" :disabled="!tabbarEnable">
     {{ $t('preferences.tabbar.icon') }}
   </SwitchItem>
-  <!-- <SwitchItem v-model="sideCollapseShowTitle" :disabled="!tabsVisible">
-    {{ $t('preferences.collapse-show-title') }}
-  </SwitchItem> -->
 </template>

+ 65 - 0
packages/business/widgets/src/preferences/blocks/number-field-item.vue

@@ -0,0 +1,65 @@
+<script setup lang="ts">
+import type { SelectListItem } from '@vben/types';
+
+import { useSlots } from 'vue';
+
+import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify';
+import {
+  NumberField,
+  NumberFieldContent,
+  NumberFieldDecrement,
+  NumberFieldIncrement,
+  NumberFieldInput,
+  VbenTooltip,
+} from '@vben-core/shadcn-ui';
+
+defineOptions({
+  name: 'PreferenceSelectItem',
+});
+
+withDefaults(
+  defineProps<{
+    disabled?: boolean;
+    items?: SelectListItem[];
+    placeholder?: string;
+  }>(),
+  {
+    disabled: false,
+    placeholder: '',
+    items: () => [],
+  },
+);
+
+const inputValue = defineModel<number>();
+
+const slots = useSlots();
+</script>
+
+<template>
+  <div
+    :class="{
+      'hover:bg-accent': !slots.tip,
+      'pointer-events-none opacity-50': disabled,
+    }"
+    class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"
+  >
+    <span class="flex items-center text-sm">
+      <slot></slot>
+
+      <VbenTooltip v-if="slots.tip" side="bottom">
+        <template #trigger>
+          <MdiQuestionMarkCircleOutline class="ml-1 cursor-help" />
+        </template>
+        <slot name="tip"></slot>
+      </VbenTooltip>
+    </span>
+
+    <NumberField v-model="inputValue" v-bind="$attrs" class="w-[160px]">
+      <NumberFieldContent>
+        <NumberFieldDecrement />
+        <NumberFieldInput />
+        <NumberFieldIncrement />
+      </NumberFieldContent>
+    </NumberField>
+  </div>
+</template>

+ 1 - 1
packages/business/widgets/src/preferences/blocks/select-item.vue

@@ -54,7 +54,7 @@ const slots = useSlots();
       </VbenTooltip>
     </span>
     <Select v-model="selectValue">
-      <SelectTrigger class="h-7 w-[140px]">
+      <SelectTrigger class="h-8 w-[160px]">
         <SelectValue :placeholder="placeholder" />
       </SelectTrigger>
       <SelectContent>

+ 1 - 1
packages/business/widgets/src/preferences/blocks/switch-item.vue

@@ -26,7 +26,7 @@ function handleClick() {
     :class="{
       'pointer-events-none opacity-50': disabled,
     }"
-    class="hover:bg-accent my-1 flex w-full items-center justify-between rounded-md px-2 py-2"
+    class="hover:bg-accent my-1 flex w-full items-center justify-between rounded-md px-2 py-2.5"
     @click="handleClick"
   >
     <span class="flex items-center text-sm">

+ 24 - 0
packages/business/widgets/src/preferences/preferences-widget.vue

@@ -19,7 +19,12 @@ import Preferences from './preferences.vue';
     :breadcrumb-show-home="preferences.breadcrumb.showHome"
     :breadcrumb-show-icon="preferences.breadcrumb.showIcon"
     :breadcrumb-style-type="preferences.breadcrumb.styleType"
+    :copyright-company-name="preferences.copyright.companyName"
+    :copyright-company-site-link="preferences.copyright.companySiteLink"
+    :copyright-date="preferences.copyright.date"
     :copyright-enable="preferences.copyright.enable"
+    :copyright-icp="preferences.copyright.icp"
+    :copyright-icp-link="preferences.copyright.icpLink"
     :footer-enable="preferences.footer.enable"
     :footer-fixed="preferences.footer.fixed"
     :header-enable="preferences.header.enable"
@@ -36,6 +41,7 @@ import Preferences from './preferences.vue';
     :sidebar-collapsed="preferences.sidebar.collapsed"
     :sidebar-collapsed-show-title="preferences.sidebar.collapsedShowTitle"
     :sidebar-enable="preferences.sidebar.enable"
+    :sidebar-width="preferences.sidebar.width"
     :tabbar-enable="preferences.tabbar.enable"
     :tabbar-show-icon="preferences.tabbar.showIcon"
     :theme-builtin-type="preferences.theme.builtinType"
@@ -86,9 +92,24 @@ import Preferences from './preferences.vue';
     @update:breadcrumb-style-type="
       (val) => updatePreferences({ breadcrumb: { styleType: val } })
     "
+    @update:copyright-company-name="
+      (val) => updatePreferences({ copyright: { companyName: val } })
+    "
+    @update:copyright-company-site-link="
+      (val) => updatePreferences({ copyright: { companySiteLink: val } })
+    "
+    @update:copyright-date="
+      (val) => updatePreferences({ copyright: { date: val } })
+    "
     @update:copyright-enable="
       (val) => updatePreferences({ copyright: { enable: val } })
     "
+    @update:copyright-icp="
+      (val) => updatePreferences({ copyright: { icp: val } })
+    "
+    @update:copyright-icp-link="
+      (val) => updatePreferences({ copyright: { icpLink: val } })
+    "
     @update:footer-enable="
       (val) => updatePreferences({ footer: { enable: val } })
     "
@@ -129,6 +150,9 @@ import Preferences from './preferences.vue';
     @update:sidebar-enable="
       (val) => updatePreferences({ sidebar: { enable: val } })
     "
+    @update:sidebar-width="
+      (val) => updatePreferences({ sidebar: { width: val } })
+    "
     @update:tabbar-enable="
       (val) => updatePreferences({ tabbar: { enable: val } })
     "

+ 18 - 2
packages/business/widgets/src/preferences/preferences.vue

@@ -77,6 +77,7 @@ const themeMode = defineModel<ThemeModeType>('themeMode');
 const themeRadius = defineModel<string>('themeRadius');
 
 const sidebarEnable = defineModel<boolean>('sidebarEnable');
+const sidebarWidth = defineModel<number>('sidebarWidth');
 const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
 const sidebarCollapsedShowTitle = defineModel<boolean>(
   'sidebarCollapsedShowTitle',
@@ -108,6 +109,13 @@ const footerEnable = defineModel<boolean>('footerEnable');
 const footerFixed = defineModel<boolean>('footerFixed');
 
 const copyrightEnable = defineModel<boolean>('copyrightEnable');
+const copyrightCompanyName = defineModel<string>('copyrightCompanyName');
+const copyrightCompanySiteLink = defineModel<string>(
+  'copyrightCompanySiteLink',
+);
+const copyrightDate = defineModel<string>('copyrightDate');
+const copyrightIcp = defineModel<string>('copyrightIcp');
+const copyrightIcpLink = defineModel<string>('copyrightIcpLink');
 
 const shortcutKeysEnable = defineModel<boolean>('shortcutKeysEnable');
 const shortcutKeysGlobalSearch = defineModel<boolean>(
@@ -272,11 +280,12 @@ async function handleReset() {
               <Content v-model="appContentCompact" />
             </Block>
 
-            <Block :title="$t('preferences.sidebar')">
+            <Block :title="$t('preferences.sidebar.title')">
               <Sidebar
                 v-model:sidebar-collapsed="sidebarCollapsed"
                 v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
                 v-model:sidebar-enable="sidebarEnable"
+                v-model:sidebar-width="sidebarWidth"
                 :disabled="!isSideMode"
               />
             </Block>
@@ -325,7 +334,14 @@ async function handleReset() {
               />
             </Block>
             <Block :title="$t('preferences.copyright.title')">
-              <Copyright v-model:copyright-enable="copyrightEnable" />
+              <Copyright
+                v-model:copyright-company-name="copyrightCompanyName"
+                v-model:copyright-company-site-link="copyrightCompanySiteLink"
+                v-model:copyright-date="copyrightDate"
+                v-model:copyright-enable="copyrightEnable"
+                v-model:copyright-icp="copyrightIcp"
+                v-model:copyright-icp-link="copyrightIcpLink"
+              />
             </Block>
           </template>
 

+ 12 - 5
packages/locales/src/langs/en-US.yaml

@@ -160,15 +160,11 @@ preferences:
   normal: Normal
   plain: Plain
   rounded: Rounded
-  collapse: Collpase Menu
-  collapse-show-title: Display menu name
   interface-control: Interface Layout Control
   copy: Copy Preferences
   copy-success: Copy successful. Please replace in `src/preferences.ts` of the app
   clear-and-logout: Clear Cache & Logout
   reset-success: Preferences reset successfully
-  sidebar: Sidebar
-  side-visible: Display Sidebar
   mode: Mode
   logo-visible: Display Logo
   # general
@@ -176,6 +172,12 @@ preferences:
   language: Language
   dynamic-title: Dynamic Title
   ai-assistant: Ai Assistant
+  sidebar:
+    title: Sidebar
+    width: Width
+    visible: Display Sidebar
+    collapsed: Collpase Menu
+    collapsed-show-title: Display menu name
   tabbar:
     title: Tabbar
     enable: Enable Tab Bar
@@ -246,7 +248,12 @@ preferences:
     fixed: Fixed at the bottom
   copyright:
     title: Copyright
-    enable: Enable CopyRight
+    enable: Enable copyright
+    company-name: Company name
+    company-site-link: Company homepage
+    date: Date
+    icp: ICP number
+    icp-link: ICP Site Link
   shortcut-keys:
     title: Shortcut Keys
     global: Global

+ 11 - 4
packages/locales/src/langs/zh-CN.yaml

@@ -145,8 +145,6 @@ preferences:
   wide: 流式
   compact: 定宽
   follow-system: 跟随系统
-  collapse: 折叠菜单
-  collapse-show-title: 显示菜单名
   vertical: 垂直
   vertical-tip: 侧边垂直菜单模式
   horizontal: 水平
@@ -166,8 +164,6 @@ preferences:
   copy-success: 拷贝成功,请在 app 下的 `src/preferences.ts`内进行覆盖
   clear-and-logout: 清空缓存 & 退出登录
   reset-success: 重置偏好设置成功
-  sidebar: 侧边栏
-  side-visible: 显示侧边栏
   mode: 模式
   logo-visible: 显示 Logo
   # general
@@ -175,6 +171,12 @@ preferences:
   language: 语言
   dynamic-title: 动态标题
   ai-assistant: Ai 助手
+  sidebar:
+    title: 侧边栏
+    width: 宽度
+    visible: 显示侧边栏
+    collapsed: 折叠菜单
+    collapsed-show-title: 显示菜单名
   tabbar:
     title: 标签栏
     enable: 启用标签栏
@@ -246,6 +248,11 @@ preferences:
   copyright:
     title: 版权
     enable: 启用版权
+    company-name: 公司名
+    company-site-link: 公司主页
+    date: 日期
+    icp: ICP 备案号
+    icp-link: ICP 网站链接
   shortcut-keys:
     title: 快捷键
     global: 全局

+ 12 - 0
pnpm-lock.yaml

@@ -760,6 +760,9 @@ importers:
       class-variance-authority:
         specifier: ^0.7.0
         version: 0.7.0
+      lucide-vue-next:
+        specifier: ^0.400.0
+        version: 0.400.0(vue@3.4.31(typescript@5.5.3))
       radix-vue:
         specifier: ^1.9.0
         version: 1.9.0(vue@3.4.31(typescript@5.5.3))
@@ -6552,6 +6555,11 @@ packages:
     resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
     engines: {node: '>=10'}
 
+  lucide-vue-next@0.400.0:
+    resolution: {integrity: sha512-JQMby6HuSr/ALLL3IAjpca/hP499vWy4+zqzCrTsAzdg0BHM0Lge84bMMxvpqqXnU24uRQkmOZCi5ksecTogfw==}
+    peerDependencies:
+      vue: ^3.4.31
+
   magic-string@0.25.9:
     resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
 
@@ -15771,6 +15779,10 @@ snapshots:
     dependencies:
       yallist: 4.0.0
 
+  lucide-vue-next@0.400.0(vue@3.4.31(typescript@5.5.3)):
+    dependencies:
+      vue: 3.4.31(typescript@5.5.3)
+
   magic-string@0.25.9:
     dependencies:
       sourcemap-codec: 1.4.8