Skip to content

Latest commit

 

History

History
376 lines (322 loc) · 8.68 KB

File metadata and controls

376 lines (322 loc) · 8.68 KB

naive ui

tooltip

// tooltip 中内容太长,导致超出屏幕,使用以下设置:
// - width: 'trigger', 宽度指定为父元素宽度
tooltip: {
  width: 'trigger'
}
// tooltip 背景色和前景色差距不大导致不易读
// - filter: 'brightness', 提高前景色亮度
tooltip: {
  contentStyle: {
	filter: 'brightness(3)'
  }
}

data-table

// 当表格出现横向滚动条时,最右侧的"操作"列(固定列)没有完全覆盖下方内容,导致出现视觉上的错位。

// 表格中的字段使用ecllipsis时,文本不能垂直居中
h(
  NEllipsis,
  { lineClamp: 1, tooltip: { width: 'trigger' }, style: {'vertical-align': 'middle'} },
  () => 'xxx'
)

date-picker

// 前后端需要使用日期字符串
h(NDatePicker, {
    valueFormat: 'yyyy-MM-dd',
    class: 'w-full',
    type: 'date',
    formattedValue: formItem.value.value,
    onUpdateFormattedValue: (value) => {
         formItem.value.value = value
    },
    placeholder: '设备有效截止日期',
})

card + scrollbar

// naive ui card -ncard 设置高度,内部使用滚动条
// 因为card-content 使用了flex-1 所以就算给content-style 设置指定的高度
// n-scrollbar 滚动条高度100% 获取到的真实高度为空

// 此时应该将content 高度设置为0

input-number

import {toNumber} from '@/utils/number/number'

/**
 * 转换为数值
 * 只有当结果既不是 NaN 也不是无穷大时才返回结果
 * @param value
 * @returns
 */
export function toNumber(value: any): number | null {
  const result = lodashToNumber(value)

  if (!isNaN(result) && isFinite(result)) {
    return result
  }

  return null
}

// 回显的时候需要保证value 是数值或null,如果先编辑再新增,此时表单项的值如果是undefined,value可能还是为上一次编辑的值,因此toNumber 需要返回null
<n-input-number v-model:value="toNumber(value)" />

input

回显时值必须是文本,否则会报错

/**
 * 转换为字符串
 * @param value
 * @returns
 */
export function toString(value: any): string | null {
  if (value === undefined || value === null) {
    return null
  }

  return String(value)
}

表单项禁止使用的字段

// constructor 会导致报错
{
  label: '施工单位',
  key: 'constructor',
  value: ref(null),

  render: (formItem) => {
    return h(NInput, {
      value: formItem.value.value,
      maxlength: 100,
      showCount: true,
      clearable: true,
      onUpdateValue: (val) => {
        formItem.value.value = val
      },
      placeholder: '施工单位',
    })
  },
},

文件上传

获取文件上传后的响应数据

function handleFinish(options) {
  // {
  //   "code": 200,
  //   "msg": "操作成功",
  //   "data": {
  //       "url": "http://172.16.97.202:9800/auth/2025/10/27/637efdecc24f45229fe219e0d4b79a89.png",
  //       "fileName": "下载.png",
  //       "ossId": "1982734315162771457"
  //   }
  // }
  const res = options.event.currentTarget.response;
}

layout 布局固定头部和顶部,有侧边栏可以滚动

h(NLayout, {
style: {height: `calc(100vh - ${headerHeight.value}px - 86px)` }
}, {
default: () => [
  h(NLayoutHeader, {
	style: 'height: 64px; padding: 24px',
	bordered: true
  }, {
	default: () => 666
  }),
  h(NLayout, {
	hasSider: true,
	position: 'absolute',
	style: 'top: 64px; bottom: 64px'
  }, {
	default: () => [
	  h(NLayoutSider, {
		bordered: true,
		nativeScrollbar: false,
		contentStyle: 'padding: 24px;'
	  }, {
		default: () => h('div', {style: {height: '500px', background: 'red'}}, '123')
	  }),
	  h(NLayout, {
		contentStyle: 'padding: 24px;',
		nativeScrollbar: false
	  }, {
		default: () => 234
	  })
	]
  }),
  h(NLayoutFooter, {
	bordered: true,
	position: 'absolute',
	style: 'height: 64px; padding: 24px'
  }, {
	default: () => 999
  })
]
})
  <n-layout :style="{ height: `calc(100vh - ${headerHeight}px - 86px)` }">
    <!-- Header -->
    <n-layout-header style="height: 64px; padding: 24px" bordered>
      666
    </n-layout-header>

    <!-- Main Content with Sider -->
    <n-layout has-sider position="absolute" style="top: 64px; bottom: 64px">
      <n-layout-sider bordered :native-scrollbar="false" content-style="padding: 24px;">
        <div style="height: 500px; background: red;">123</div>
      </n-layout-sider>

      <n-layout content-style="padding: 24px;" :native-scrollbar="false">
        234
      </n-layout>
    </n-layout>

    <!-- Footer -->
    <n-layout-footer bordered position="absolute" style="height: 64px; padding: 24px">
      999
    </n-layout-footer>
  </n-layout>

highlight.js 使用方式

import hljs from 'highlight.js/lib/core'
import json from 'highlight.js/lib/languages/json'

hljs.registerLanguage('json', json)

h('div', {
  style: { whiteSpace: 'pre' },
  innerHTML: hljs.highlight(value, { language: 'json' }).value
})

使用 vue-draggable-plus 拖动表格行 datatable

import { useDraggable } from 'vue-draggable-plus'

const  tableRef = ref<any>()

async function draggableTable() {
	if (tableRef.value && table.dataList.value.length > 0) {
	  await nextTick()
	  const itemsContainer = tableRef.value.$el.querySelector('.n-data-table-tbody')
	  if (itemsContainer) {
		useDraggable(itemsContainer, table.dataList, {
		  animation: 150,
		  onUpdate() {
			console.log('update')
		  }
		})
	  }
	  {
		console.warn('draggableTable itemsContainer is null')
	  }
	}
	}
// 拖动表格排序

async function draggableTable() {
async function draggableTable() {
        if (tableRef.value && table.dataList.value.length > 0) {
          await nextTick()
          const itemsContainer = tableRef.value.$el.querySelector('.n-data-table-tbody')
          if (itemsContainer) {
            useDraggable(itemsContainer, table.dataList, {
              animation: 150,
              onUpdate(event: any) {
                const { newIndex, oldIndex } = event
                const rowData = table.dataList.value[newIndex]
                if (newIndex > oldIndex) {
                  // 向下移动
                  const preMaxOrder = table.dataList.value
                    .slice(0, newIndex)
                    .reduce((max, item) => {
                      return Math.max(max, item.itemOrder ?? 0)
                    }, newIndex - 1)
                  rowData.itemOrder = preMaxOrder + 1
                  onUpdateItem(rowData)
                } else {
                  // 向上移动
                  const nextMinOrder = table.dataList.value.slice(newIndex+1).reduce((min, item) => {
                    return Math.min(min, item.itemOrder ?? 0)
                  }, newIndex + 1)
                  rowData.itemOrder = nextMinOrder - 1
                  onUpdateItem(rowData)
                }
              }
            })
          }
          {
            console.warn('draggableTable itemsContainer is null')
          }
        }
      }```
	  
## ellipsis 使用	  

// align-middle 文本垂直居中 h(NEllipsis, {class: 'align-middle'}, { default: () => h('span', {}, item?.option?.categoryName) })



## 组件 颜色如何做到调整背景颜色其他内部颜色自动跟随变化
naive ui 组件默认支持以下属性:
theme => 只能获取到最原始的配置,只能切换dark和light,具体样式大概率被其他设置覆盖
themeOverrides => 可以使用
builtinThemeOverrides

naive ui组件中有以下变量(决定最后的css样式):
mergedTheme -> themeRef -> useTheme()
cssVars -> cssVarsRef -> themeRef

组件初始化完成后获取mergedTheme,再手动设置到themeOverrides

## 带装饰的标题
厂商与负责人 ```

popover/tooltip 下input自动聚焦

input 的 ref 使用函数,el为input组件实例

h(NTooltip, {

},
{
trigger: () => h(NButton, {
		size: 'small',
		text: true,
	},
	{
		icon: () => h(NIcon, {component: StepForwardFilled}),
	}),
default: () =>h(NInput, {
	ref: async (el:any)=>{
	  await nextTick()
	  el?.focus()
	},

})
])

含过滤时,搜索框有clearable,搜索框不能使用v-model="pattern",必须使用:value="pattern" @update:value="(val)=>pattern=val!=null&&val!=undefined?val:''",否则会报错

表格 table

// 滚动条
:scroll-x="tableColumns.reduce((sum, col) => sum + (col.width as number ?? 0), 0)"

修改弹出框面板宽度,主题参数覆盖

<n-cascader
    v-model:value="value_"
    :options="options"
    remote
    :filterable="true"
    :clearable="clearable"
    @load="handleLoad"
    :show-path="true"
    check-strategy="child"
    :render-label="renderLabel"
    @update:value="handleUpdateValue"
    :theme-overrides="{columnWidth:'fit-content'}"
  />