diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs index 34fee141..9ead01b6 100644 --- a/.commitlintrc.cjs +++ b/.commitlintrc.cjs @@ -17,12 +17,18 @@ module.exports = { 'perf', // 性能优化 ] ], - 'type-case': [0], - 'type-empty': [0], - 'scope-empty': [0], 'scope-case': [0], - 'subject-full-stop': [0, 'never'], - 'subject-case': [0, 'never'], - 'header-max-length': [0, 'always', 72] - } + }, + plugins: [ + { + rules: { + "commit-rule": ({ raw }) => { + return [ + /^\[(build|feat|fix|update|refactor|docs|chore|style|revert|perf)].+/g.test(raw), + `commit备注信息格式错误,格式为 <[type] 修改内容>,type支持${types.join(",")}` + ] + } + } + } + ] } \ No newline at end of file diff --git a/components.d.ts b/components.d.ts deleted file mode 100644 index 3e729ed1..00000000 --- a/components.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -// generated by unplugin-vue-components -// We suggest you to commit this file into source control -// Read more: https://github.com/vuejs/core/pull/3399 -import '@vue/runtime-core' - -export {} - -declare module '@vue/runtime-core' { - export interface GlobalComponents { - AAlert: typeof import('ant-design-vue/es')['Alert'] - ABadge: typeof import('ant-design-vue/es')['Badge'] - AButton: typeof import('ant-design-vue/es')['Button'] - ACard: typeof import('ant-design-vue/es')['Card'] - ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] - ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup'] - ACol: typeof import('ant-design-vue/es')['Col'] - ADatePicker: typeof import('ant-design-vue/es')['DatePicker'] - ADivider: typeof import('ant-design-vue/es')['Divider'] - AEmpty: typeof import('ant-design-vue/es')['Empty'] - AForm: typeof import('ant-design-vue/es')['Form'] - AFormItem: typeof import('ant-design-vue/es')['FormItem'] - AInput: typeof import('ant-design-vue/es')['Input'] - AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] - AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] - AModal: typeof import('ant-design-vue/es')['Modal'] - APagination: typeof import('ant-design-vue/es')['Pagination'] - APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] - ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] - ARow: typeof import('ant-design-vue/es')['Row'] - ASelect: typeof import('ant-design-vue/es')['Select'] - ASpin: typeof import('ant-design-vue/es')['Spin'] - ASwitch: typeof import('ant-design-vue/es')['Switch'] - ATable: typeof import('ant-design-vue/es')['Table'] - ATabPane: typeof import('ant-design-vue/es')['TabPane'] - ATabs: typeof import('ant-design-vue/es')['Tabs'] - ATimePicker: typeof import('ant-design-vue/es')['TimePicker'] - ATooltip: typeof import('ant-design-vue/es')['Tooltip'] - ATree: typeof import('ant-design-vue/es')['Tree'] - ATreeSelect: typeof import('ant-design-vue/es')['TreeSelect'] - AUpload: typeof import('ant-design-vue/es')['Upload'] - BadgeStatus: typeof import('./src/components/BadgeStatus/index.vue')['default'] - CardBox: typeof import('./src/components/CardBox/index.vue')['default'] - FormFormBuilder: typeof import('./src/components/Form/FormBuilder.vue')['default'] - GeoComponent: typeof import('./src/components/GeoComponent/index.vue')['default'] - MonacoEditor: typeof import('./src/components/MonacoEditor/index.vue')['default'] - PermissionButton: typeof import('./src/components/PermissionButton/index.vue')['default'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - Table: typeof import('./src/components/Table/index.vue')['default'] - TitleComponent: typeof import('./src/components/TitleComponent/index.vue')['default'] - ValueItem: typeof import('./src/components/ValueItem/index.vue')['default'] - } -} diff --git a/config/config.ts b/config/config.ts index 88915884..108726d5 100644 --- a/config/config.ts +++ b/config/config.ts @@ -1,6 +1,6 @@ export default { theme: { - 'primary-color': '#00A4FF', + 'primary-color': '#1d39c4', }, logo: '/favicon.ico', title: 'Jetlinks' diff --git a/package.json b/package.json index 896ac93a..26e555d8 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "typescript": "^4.9.3", "vite": "^4.0.0", "vite-plugin-html": "^3.2.0", + "vite-plugin-style-import": "^2.0.0", "vite-plugin-vue-setup-extend": "^0.4.0", "vue-tsc": "^1.0.11" }, diff --git a/src/api/device.ts b/src/api/device/instance.ts similarity index 100% rename from src/api/device.ts rename to src/api/device/instance.ts diff --git a/src/api/device/product.ts b/src/api/device/product.ts new file mode 100644 index 00000000..ac44c574 --- /dev/null +++ b/src/api/device/product.ts @@ -0,0 +1,3 @@ +import server from '@/utils/request' + +export const queryNoPagingPost = (data: any) => server.post(`/device-product/_query/no-paging?paging=false`, data) \ No newline at end of file diff --git a/src/components/Form/FormBuilder.vue b/src/components/Form/FormBuilder.vue index cac91d0a..afcbfa2d 100644 --- a/src/components/Form/FormBuilder.vue +++ b/src/components/Form/FormBuilder.vue @@ -241,7 +241,7 @@ watch(props.initValue, (newValue: any) => { }) defineExpose({ - resetModel, + reset: resetModel, formValidate, setItemValue, setData diff --git a/src/components/PermissionButton/index.vue b/src/components/PermissionButton/index.vue index cbeb5c37..d211e2ee 100644 --- a/src/components/PermissionButton/index.vue +++ b/src/components/PermissionButton/index.vue @@ -25,7 +25,7 @@ - + + diff --git a/src/components/Search/Item.vue b/src/components/Search/Item.vue new file mode 100644 index 00000000..6f44c425 --- /dev/null +++ b/src/components/Search/Item.vue @@ -0,0 +1,125 @@ + + + + + \ No newline at end of file diff --git a/src/components/Search/Search.vue b/src/components/Search/Search.vue new file mode 100644 index 00000000..2bcd6615 --- /dev/null +++ b/src/components/Search/Search.vue @@ -0,0 +1,72 @@ + + + + + \ No newline at end of file diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts new file mode 100644 index 00000000..4edb3b21 --- /dev/null +++ b/src/components/Search/index.ts @@ -0,0 +1,3 @@ +import Search from './Search.vue' + +export default Search \ No newline at end of file diff --git a/src/components/Search/util.ts b/src/components/Search/util.ts new file mode 100644 index 00000000..573b0d7d --- /dev/null +++ b/src/components/Search/util.ts @@ -0,0 +1,4 @@ +export const typeOptions = [ + { label: '或者', value: 'or' }, + { label: '并且', value: 'and' }, +] \ No newline at end of file diff --git a/src/components/Table/index.module.less b/src/components/Table/index.module.less new file mode 100644 index 00000000..a0e94e07 --- /dev/null +++ b/src/components/Table/index.module.less @@ -0,0 +1,52 @@ +.jtable-body { + width: 100%; + padding: 0 24px 24px; + background-color: white; + .jtable-body-header { + padding: 16px 0; + display: flex; + justify-content: space-between; + align-items: center; + .jtable-body-header-right { + display: flex; + gap: 8px; + .jtable-setting-item { + color: rgba(0, 0, 0, 0.75); + font-size: 16px; + cursor: pointer; + + &:hover { + color: @primary-color-hover; + } + + &.active { + color: @primary-color-active; + } + } + } + } + .jtable-content { + .jtable-alert { + margin-bottom: 16px; + } + .jtable-card { + .jtable-card-items { + display: grid; + grid-gap: 26px; + .jtable-card-item { + display: flex; + } + } + } + } + .jtable-pagination { + margin-top: 20px; + display: flex; + justify-content: flex-end; + :global { + .ant-pagination-item { + display: none !important; + } + } + } +} \ No newline at end of file diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx new file mode 100644 index 00000000..38e2e6af --- /dev/null +++ b/src/components/Table/index.tsx @@ -0,0 +1,268 @@ +import { UnorderedListOutlined, AppstoreOutlined } from '@ant-design/icons-vue' +import styles from './index.module.less' +import { Pagination, Table, Empty, Spin, Alert } from 'ant-design-vue' +import type { TableProps, ColumnProps } from 'ant-design-vue/es/table' +import type { TooltipProps } from 'ant-design-vue/es/tooltip' +import type { PopconfirmProps } from 'ant-design-vue/es/popconfirm' +import { CSSProperties, PropType } from 'vue'; + +enum ModelEnum { + TABLE = 'TABLE', + CARD = 'CARD', +} + +type RequestData = { + code: string; + result: { + data: Record[] | undefined; + pageIndex: number; + pageSize: number; + total: number; + }; + status: number; +} & Record; + +export interface ActionsType { + key: string; + text?: string; + disabled?: boolean; + permission?: boolean; + onClick?: (data: any) => void; + style?: CSSProperties; + tooltip?: TooltipProps; + popConfirm?: PopconfirmProps; + icon?: string; +} + +export interface JColumnProps extends ColumnProps{ + scopedSlots?: boolean; // 是否为插槽 true: 是 false: 否 +} + +export interface JTableProps extends TableProps{ + request?: (params: Record & { + pageSize: number; + pageIndex: number; + }) => Promise>; + cardBodyClass?: string; + columns: JColumnProps[]; + params?: Record & { + pageSize: number; + pageIndex: number; + }; + model?: keyof typeof ModelEnum | undefined; // 显示table还是card + actions?: ActionsType[]; + noPagination?: boolean; + rowSelection?: TableProps['rowSelection']; + cardProps?: Record; + dataSource?: Record[]; +} + +const JTable = defineComponent({ + name: 'JTable', + slots: [ + 'headerTitle', // 顶部左边插槽 + 'card', // 卡片内容 + ], + emits: [ + 'modelChange', // 切换卡片和表格 + ], + props: { + request: { + type: Function, + default: undefined + }, + cardBodyClass: { + type: String, + default: '' + }, + columns: { + type: Array, + default: () => [] + }, + params: { + type: Object, + default: () => {} + }, + model: { + type: [String, undefined], + default: undefined + }, + actions: { + type: Array as PropType, + default: () => [] + }, + noPagination: { + type: Boolean, + default: false + }, + rowSelection: { + type: Object as PropType, + default: () => undefined + }, + cardProps: { + type: Object, + default: undefined + }, + dataSource: { + type: Array, + default: () => [] + } + } as any, + setup(props: JTableProps ,{ slots, emit }){ + const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE + const _model = ref(props.model ? props.model : ModelEnum.CARD); // 模式切换 + const column = ref(4); + const _dataSource = ref[]>([]) + const pageIndex = ref(0) + const pageSize = ref(6) + const total = ref(0) + const _columns = ref(props?.columns || []) + const loading = ref(true) + + // alert关闭,取消选择 + const handleAlertClose = () => { + emit('cancelSelect') + } + + /** + * 请求数据 + */ + const handleSearch = async (_params?: Record) => { + loading.value = true + if(props.request) { + const resp = await props.request({ + pageSize: 12, + pageIndex: 1, + ..._params + }) + if(resp.status === 200){ + // 判断如果是最后一页且最后一页为空,就跳转到前一页 + if(resp.result?.data?.length === 0 && resp.result.total && resp.result.pageSize && resp.result.pageIndex) { + handleSearch({ + ..._params, + pageSize: pageSize.value, + pageIndex: pageIndex.value - 1, + }) + } else { + _dataSource.value = resp.result?.data || [] + pageIndex.value = resp.result?.pageIndex || 0 + pageSize.value = resp.result?.pageSize || 6 + total.value = resp.result?.total || 0 + } + } + } else { + _dataSource.value = props?.dataSource || [] + } + + loading.value = false + } + + watchEffect(() => { + handleSearch(props.params) + }) + + return () => +
+
+
+ {/* 顶部左边插槽 */} + {slots.headerTitle && slots.headerTitle()} +
+
+
{ + _model.value = ModelEnum.CARD + }}> + +
+
{ + _model.value = ModelEnum.TABLE + }}> + +
+
+
+ {/* content */} +
+ { + props?.rowSelection && props?.rowSelection?.selectedRowKeys && props.rowSelection.selectedRowKeys?.length ? +
+ 取消选择} + /> +
: null + } + { + _model.value === ModelEnum.CARD ? +
+ { + _dataSource.value.length ? +
+ { + _dataSource.value.map(item => slots.card ? +
{slots.card({row: item, actions: props?.actions || []})}
+ : null) + } +
: +
+ } +
: +
+ ) => { + const {column, record} = dt; + if((column?.key || column?.dataIndex) && column?.scopedSlots && (slots?.[column?.dataIndex] || slots?.[column?.key])) { + const _key = column?.key || column?.dataIndex + return slots?.[_key]!({row: record, actions: props.actions}) + } else { + return record?.[column?.dataIndex] || '' + } + } + }} + /> + + } + + {/* 分页 */} + { + _dataSource.value.length && !props.noPagination && +
+ { + return `第 ${range[0]} - ${range[1]} 条/总共 ${total} 条` + }} + onChange={(page, size) => { + handleSearch({ + ...props.params, + pageSize: size, + pageIndex: pageSize.value === size ? page : 1, + }) + }} + /> +
+ } + + + } +}) + +export default JTable diff --git a/src/components/Table/index.vue b/src/components/Table/index.vue index 6ac325ad..d596666f 100644 --- a/src/components/Table/index.vue +++ b/src/components/Table/index.vue @@ -79,7 +79,7 @@ - + + \ No newline at end of file diff --git a/src/views/demo/table/index.vue b/src/views/demo/table/index.vue index 3c311295..77d79fe3 100644 --- a/src/views/demo/table/index.vue +++ b/src/views/demo/table/index.vue @@ -38,14 +38,14 @@ 新增