# noob-components ## Project Overview A Vue 3 component library built with TypeScript and Vite, providing reusable UI components and composables for management applications. The library extends Element Plus with custom components, layouts, and utilities. ## Technology Stack - **Framework**: Vue 3 (Composition API) - **Language**: TypeScript - **Build Tool**: Vite - **Base UI Library**: Element Plus - **Styling**: SCSS with scoped styles - **State Management**: Vuex (for consuming applications) - **Internationalization**: vue3-i18n - **Package Manager**: npm/bun ## Project Structure ``` noob-components/ ├── packages/ │ ├── base/ # Base UI components │ │ ├── data/ # Data display components (ListTable, etc.) │ │ ├── item/ # Form input components (Input, Select, DateTime, etc.) │ │ └── layout/ # Layout components │ ├── manage/ # Management-specific components │ │ ├── common/ # Common components (login forms, etc.) │ │ └── router/ # Router layout components (index.vue, zhuBeiDong.vue) │ └── app.ts # Main export file ├── plugs/ │ ├── composables/ # Vue composables │ │ ├── useListTable.ts # Table data management │ │ ├── useModifyForm.ts # Form modification logic │ │ └── ... │ ├── http/ # HTTP utilities and API client │ ├── element/ # Element Plus utilities │ └── utils/ # General utilities ├── dist/ # Build output │ ├── noob-mengyxu.js │ ├── noob-mengyxu.css │ └── style.css └── vite.config.ts # Vite configuration ``` ## Key Components ### Router Layouts (`packages/manage/router/`) Two main layout components for management applications: - **index.vue**: Standard layout with horizontal/vertical menu support - **zhuBeiDong.vue**: Alternative layout with specific styling Both components: - Provide app structure with header, aside, and main content areas - Support theme switching (via `state.style`) - Support size adjustments (via `state.size`) - Handle user authentication checks - Use **scoped CSS** with `:deep()` for child component styling ### Login Components (`packages/manage/common/`) - **login2.vue**: Login form with vertical layout (labels above inputs) ### Data Components (`packages/base/data/`) - **list-table.vue**: Table component with pagination, sorting, filtering - Uses TypeScript interface-based props - Integrates with `useListTable` composable - Supports Element Plus table features ### Form Components (`packages/base/item/`) - **input.vue**: Text input wrapper - **select.vue**: Select dropdown wrapper - **datetime.vue**: Date/time picker wrapper - **modify-form.vue**: Form modification component All form components: - Support `.full` class for 100% width - Have default constrained width via `.form-item` - Use scoped styles ## Key Composables ### useListTable (`plugs/composables/useListTable.ts`) Manages table data with pagination and filtering. **Important implementation details:** - Uses `deepCopy(toRaw(example))` to avoid infinite reactivity loops - Automatically manages pagination params (`page`, `size`) - Supports both array and paginated response (`{ data: [], total: N }`) - Has `disableAutoQuery` option to disable automatic queries **Interface:** ```typescript interface TableColumn { code: string; // Property path (supports nested like "task.name") name?: string; // Display name i18n?: string; // i18n key type?: string; // Column type width?: string | number; fixed?: boolean | 'left' | 'right'; align?: 'left' | 'center' | 'right'; slot?: boolean; // Use custom slot dict?: string; // Dictionary for value mapping timestamp?: boolean; // Format as timestamp filesize?: boolean; // Format as file size } ``` ### useModifyForm (`plugs/composables/useModifyForm.ts`) Manages form state for add/edit operations. ## Styling Conventions ### CSS Scoping - **Router components** (`index.vue`, `zhuBeiDong.vue`): - Split into unscoped (for `body`) and scoped blocks - Use `:deep()` for child components from library - Example: `:deep(.head-icon)`, `:deep(.el-input)` - **Form components** (`input.vue`, `select.vue`, etc.): - Use scoped styles - Support `.full` class to override width ### CSS Variables Binding Components use `v-bind()` to bind Vuex state to CSS: ```scss color: v-bind("state.style.color"); background-color: v-bind("state.style.bodyBg"); font-size: v-bind("state.size.fontSize"); height: v-bind("state.size.headHeight"); ``` ### State Structure ```typescript state.style = { color: string; bodyBg: string; headBg: string; itemBg: string; selectionBg: string; selectionColor: string; } state.size = { fontSize: string; headHeight: string; asideWidth: string; mainHeight: string; tableHeight: string; headIconSize: string; size: 'small' | 'default' | 'large'; } ``` ## Build Configuration ### Library Build (`vite.config.ts`) - Entry: `packages/app.ts` - Output: `dist/noob-mengyxu.js` and `dist/noob-mengyxu.css` - CSS is extracted separately (not injected into JS) - Vue is externalized (peer dependency) ### Development Workflow 1. **Local development with linking:** ```bash bun link cd ../s6a_manage bun link noob-mengyxu ``` 2. **Important**: When using `bun link`, JS/templates load from source but CSS loads from `dist/` - After CSS changes, must rebuild: `npm run build:lib` ## Common Issues and Solutions ### Issue: CSS Conflicts from Multiple Router Components **Problem**: Multiple unscoped CSS rules causing variable conflicts **Solution**: - Use scoped styles with `:deep()` for child elements - Split into unscoped (body only) and scoped blocks ### Issue: Infinite Loop in useListTable with deepCopy **Problem**: `deepCopy(example)` inside `watchEffect` establishes reactive dependencies **Solution**: Use `deepCopy(toRaw(example))` for deep non-reactive clone ### Issue: Form Input Width Issues **Problem**: `.form-item` class collision between components **Solution**: - Add `.full { width: 100%; }` to base components - Remove conflicting styles from router components - Use `:deep()` when needed to style library components ### Issue: Header Icons Not Styled **Problem**: After scoping, library components don't have scoped attribute **Solution**: Change `.head-icon` to `:deep(.head-icon)` in router components ## TypeScript Conventions - Use interface-based prop definitions: `defineProps()` - Use `withDefaults()` for default values - Prefer `undefined` over `null` for optional props (simplifies types) - Use `() => []` or `() => ({})` for array/object defaults ## Exports Main export file: `packages/app.ts` Exports are organized into modules: - `Element`: Element Plus utilities - `NoobHead`: Header components - `NoobInput`, `NoobButton`, etc.: Form components - `ListTable`, `ModifyForm`: Data components - `Api`: HTTP client - `Styles`, `Size`: Theme utilities - Composables: `useListTable`, `useModifyForm`, etc. ## Recent Changes 1. **TypeScript Conversion**: Converted list-table.vue to interface-based props 2. **CSS Scoping**: Fixed conflicts by scoping router component styles 3. **Reactivity Fix**: Changed to `deepCopy(toRaw(example))` in useListTable 4. **Form Layout**: Fixed login form to use vertical layout (labels above inputs) 5. **Pagination**: Fixed handling of paginated responses `{ data: [], total: N }` ## Dependencies Key dependencies: - `vue`: ^3.x - `element-plus`: UI library - `vue3-i18n`: Internationalization - `vuex`: State management (for consumers) - `axios`: HTTP client - `js-md5`: Password hashing - `@vueuse/core`: Vue utilities - `lodash-es`: Utility functions