jgy-public-component 0.0.21 → 0.0.22

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.cjs","sources":["../src/components/JButton/JButton.vue","../src/components/JUploadImg/JUploadImg.vue","../src/components/JIconRender/JIconRender.vue","../src/components/JSearchHeader/JSearchHeader.vue","../src/components/JImportExcel/JImportExcel.vue","../src/components/JSidebar/JSideMenuItem.vue","../src/components/JSidebar/JSidebar.vue","../src/components/JAdminLayout/JAdminLayout.vue","../src/utils/transform.ts","../src/router/helpers.ts","../src/router/guards.ts","../src/index.ts"],"sourcesContent":["<template>\r\n <button\r\n class=\"j-button\"\r\n :class=\"[\r\n `j-button--${type}`,\r\n `j-button--${size}`,\r\n {\r\n 'j-button--plain': plain,\r\n 'j-button--round': round,\r\n 'j-button--disabled': disabled,\r\n 'j-button--loading': loading,\r\n },\r\n ]\"\r\n :disabled=\"disabled || loading\"\r\n @click=\"handleClick\"\r\n >\r\n <span v-if=\"loading\" class=\"j-button__loading-icon\" />\r\n <span v-if=\"$slots.default\" class=\"j-button__text\">\r\n <slot />\r\n </span>\r\n </button>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport type { ButtonType, ButtonSize } from './types'\r\n\r\ninterface Props {\r\n type?: ButtonType\r\n size?: ButtonSize\r\n plain?: boolean\r\n round?: boolean\r\n disabled?: boolean\r\n loading?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n type: 'default',\r\n size: 'medium',\r\n plain: false,\r\n round: false,\r\n disabled: false,\r\n loading: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n click: [event: MouseEvent]\r\n}>()\r\n\r\nfunction handleClick(event: MouseEvent) {\r\n if (!props.disabled && !props.loading) {\r\n emit('click', event)\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.j-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: $spacing-xs;\r\n padding: 8px 16px;\r\n font-size: $font-size-base;\r\n font-weight: 400;\r\n line-height: 1;\r\n white-space: nowrap;\r\n cursor: pointer;\r\n border: 1px solid $color-border;\r\n border-radius: $border-radius-base;\r\n background-color: $color-white;\r\n color: $color-text-regular;\r\n transition: $transition-fast;\r\n outline: none;\r\n user-select: none;\r\n\r\n &:hover {\r\n color: $color-primary;\r\n border-color: $color-primary;\r\n background-color: color.adjust($color-primary, $lightness: 40%);\r\n }\r\n\r\n // 尺寸\r\n &--small {\r\n padding: 5px 12px;\r\n font-size: $font-size-xs;\r\n }\r\n\r\n &--medium {\r\n padding: 8px 16px;\r\n font-size: $font-size-base;\r\n }\r\n\r\n &--large {\r\n padding: 12px 20px;\r\n font-size: $font-size-md;\r\n }\r\n\r\n // 类型\r\n &--primary {\r\n background-color: $color-primary;\r\n border-color: $color-primary;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-primary, $lightness: 10%);\r\n border-color: color.adjust($color-primary, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--success {\r\n background-color: $color-success;\r\n border-color: $color-success;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-success, $lightness: 10%);\r\n border-color: color.adjust($color-success, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--danger {\r\n background-color: $color-danger;\r\n border-color: $color-danger;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-danger, $lightness: 10%);\r\n border-color: color.adjust($color-danger, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--warning {\r\n background-color: $color-warning;\r\n border-color: $color-warning;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-warning, $lightness: 10%);\r\n border-color: color.adjust($color-warning, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n // 朴素按钮\r\n &--plain {\r\n &.j-button--primary {\r\n background-color: color.adjust($color-primary, $lightness: 40%);\r\n color: $color-primary;\r\n &:hover {\r\n background-color: $color-primary;\r\n color: $color-white;\r\n }\r\n }\r\n }\r\n\r\n // 圆角\r\n &--round {\r\n border-radius: $border-radius-round;\r\n }\r\n\r\n // 禁用\r\n &--disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n }\r\n\r\n // 加载\r\n &--loading {\r\n opacity: 0.7;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n }\r\n\r\n &__loading-icon {\r\n display: inline-block;\r\n width: 14px;\r\n height: 14px;\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: j-spin 0.6s linear infinite;\r\n }\r\n\r\n @keyframes j-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"j-upload-img-container\">\r\n <!-- 多图模式 -->\r\n <template v-if=\"multiple\">\r\n <div class=\"images-wrapper\">\r\n <draggable\r\n v-model=\"imageList\"\r\n class=\"images-list\"\r\n item-key=\"uid\"\r\n :animation=\"200\"\r\n :disabled=\"disabled\"\r\n @end=\"handleDragEnd\"\r\n >\r\n <template #item=\"{ element, index }\">\r\n <div class=\"image-item\">\r\n <el-image\r\n :src=\"element.url\"\r\n :preview-src-list=\"imageList.map(img => img.url)\"\r\n :initial-index=\"index\"\r\n fit=\"cover\"\r\n class=\"image-preview\"\r\n :preview-teleported=\"true\"\r\n :hide-on-click-modal=\"true\"\r\n />\r\n <div v-if=\"!disabled\" class=\"delete-btn\" @click.stop=\"handleRemove(index)\">\r\n <el-icon class=\"icon-delete\">\r\n <Delete />\r\n </el-icon>\r\n </div>\r\n </div>\r\n </template>\r\n </draggable>\r\n\r\n <!-- 多图上传按钮 -->\r\n <el-upload\r\n v-if=\"!disabled && (!limit || imageList.length < limit)\"\r\n class=\"image-uploader\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n :disabled=\"uploading\"\r\n list-type=\"picture-card\"\r\n :accept=\"accept\"\r\n >\r\n <el-icon v-if=\"!uploading\" class=\"uploader-icon\">\r\n <Plus />\r\n </el-icon>\r\n <el-icon v-else class=\"uploader-icon is-loading\">\r\n <Loading />\r\n </el-icon>\r\n </el-upload>\r\n </div>\r\n </template>\r\n\r\n <!-- 单图模式 -->\r\n <template v-else>\r\n <!-- 已有图片:独立展示,hover 显示操作遮罩 -->\r\n <div v-if=\"imageUrl\" class=\"image-item single-image-item\">\r\n <el-image\r\n :src=\"imageUrl\"\r\n fit=\"cover\"\r\n class=\"image-preview\"\r\n />\r\n <div class=\"image-actions\">\r\n <el-icon class=\"action-icon\" @click.stop=\"handlePreviewSingle\">\r\n <ZoomIn />\r\n </el-icon>\r\n <el-icon v-if=\"!disabled\" class=\"action-icon\" @click.stop=\"handleRemoveSingle\">\r\n <Delete />\r\n </el-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- 无图片:显示上传按钮 -->\r\n <el-upload\r\n v-else\r\n class=\"image-uploader\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n :disabled=\"disabled || uploading\"\r\n :accept=\"accept\"\r\n list-type=\"picture-card\"\r\n >\r\n <el-icon class=\"uploader-icon\">\r\n <Plus v-if=\"!uploading\" />\r\n <Loading v-else class=\"is-loading\" />\r\n </el-icon>\r\n </el-upload>\r\n\r\n <!-- 大图预览 -->\r\n <el-image-viewer\r\n v-if=\"showPreview\"\r\n :url-list=\"[imageUrl]\"\r\n :teleported=\"true\"\r\n @close=\"showPreview = false\"\r\n />\r\n </template>\r\n\r\n <div v-if=\"showTipText\" class=\"upload-tip\">\r\n <span>{{ tip }}</span>\r\n <span v-if=\"multiple && limit\"> (最多 {{ limit }} 张)</span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch } from 'vue'\r\nimport { ElMessage, ElImage, ElIcon, ElUpload, ElImageViewer } from 'element-plus'\r\nimport type { UploadFile } from 'element-plus'\r\nimport { Plus, Loading, Delete, ZoomIn } from '@element-plus/icons-vue'\r\nimport draggable from 'vuedraggable'\r\nimport type { ImageItem } from './types'\r\n\r\ndefineOptions({\r\n name: 'JUploadImg'\r\n})\r\n\r\nconst props = withDefaults(defineProps<{\r\n modelValue?: string | string[]\r\n disabled?: boolean\r\n multiple?: boolean\r\n limit?: number\r\n maxSize?: number\r\n accept?: string\r\n tip?: string\r\n showTip?: boolean\r\n /** 自定义上传函数,接收 File 返回图片 URL */\r\n uploadFn?: (file: File) => Promise<string>\r\n}>(), {\r\n modelValue: '',\r\n disabled: false,\r\n multiple: false,\r\n limit: 9,\r\n maxSize: 2,\r\n accept: 'image/jpeg,image/png,image/jpg,image/gif',\r\n tip: '只能上传jpg/png/gif格式的图片,且不超过2MB',\r\n showTip: true,\r\n uploadFn: undefined\r\n})\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: string | string[]): void\r\n (e: 'success', url: string): void\r\n (e: 'error', error: any): void\r\n}>()\r\n\r\n// 单图模式\r\nconst imageUrl = ref<string>('')\r\nconst showPreview = ref(false)\r\nconst showTipText = props.showTip\r\n\r\nconst handlePreviewSingle = () => {\r\n showPreview.value = true\r\n}\r\n\r\nconst handleRemoveSingle = () => {\r\n imageUrl.value = ''\r\n emit('update:modelValue', '')\r\n ElMessage.success('删除成功')\r\n}\r\n\r\n// 多图模式\r\nconst imageList = ref<ImageItem[]>([])\r\nconst uploading = ref(false)\r\n\r\n// 初始化图片列表(多图模式)\r\nconst initImageList = (urls: string[]) => {\r\n imageList.value = urls.map((url, index) => ({\r\n uid: Date.now() + index,\r\n url\r\n }))\r\n}\r\n\r\n// 监听外部值变化\r\nwatch(() => props.modelValue, (val) => {\r\n if (props.multiple) {\r\n if (Array.isArray(val) && val.length > 0) {\r\n initImageList(val)\r\n } else {\r\n imageList.value = []\r\n }\r\n } else {\r\n if (typeof val === 'string') {\r\n imageUrl.value = val\r\n } else {\r\n imageUrl.value = ''\r\n }\r\n }\r\n}, { immediate: true })\r\n\r\n// 拖拽结束(多图模式)\r\nconst handleDragEnd = () => {\r\n emitMultipleUpdate()\r\n}\r\n\r\n// 删除图片(多图模式)\r\nconst handleRemove = (index: number) => {\r\n imageList.value.splice(index, 1)\r\n emitMultipleUpdate()\r\n ElMessage.success('删除成功')\r\n}\r\n\r\n// 文件改变时触发\r\nconst handleFileChange = async (uploadFile: UploadFile) => {\r\n const file = uploadFile.raw as File\r\n\r\n if (!file) {\r\n ElMessage.error('文件不存在,请重试')\r\n return\r\n }\r\n\r\n if (file.size > props.maxSize * 1024 * 1024) {\r\n ElMessage.error(`图片大小不能超过 ${props.maxSize}MB`)\r\n return\r\n }\r\n\r\n if (!props.uploadFn) {\r\n ElMessage.error('未配置上传函数 (uploadFn)')\r\n return\r\n }\r\n\r\n try {\r\n uploading.value = true\r\n const url = await props.uploadFn(file)\r\n\r\n if (props.multiple) {\r\n imageList.value.push({ uid: Date.now(), url })\r\n emitMultipleUpdate()\r\n } else {\r\n imageUrl.value = url\r\n emit('update:modelValue', url)\r\n }\r\n\r\n emit('success', url)\r\n ElMessage.success('上传成功')\r\n } catch (error) {\r\n console.error('上传出错:', error)\r\n ElMessage.error('上传失败,请重试')\r\n emit('error', error)\r\n } finally {\r\n uploading.value = false\r\n }\r\n}\r\n\r\n// 触发多图更新\r\nconst emitMultipleUpdate = () => {\r\n const urls = imageList.value.map(item => item.url)\r\n emit('update:modelValue', urls)\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-upload-img-container {\r\n display: inline-block;\r\n}\r\n\r\n/* 多图模式样式 */\r\n.images-wrapper {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n align-items: flex-start;\r\n}\r\n\r\n.images-list {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n}\r\n\r\n.image-item {\r\n position: relative;\r\n width: 74px;\r\n height: 74px;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 6px;\r\n overflow: hidden;\r\n cursor: move;\r\n}\r\n\r\n.image-preview {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.delete-btn {\r\n position: absolute;\r\n top: 2px;\r\n right: 2px;\r\n width: 20px;\r\n height: 20px;\r\n background-color: rgba(0, 0, 0, 0.6);\r\n border-radius: 50%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n opacity: 0;\r\n transition: opacity 0.3s;\r\n cursor: pointer;\r\n z-index: 1;\r\n}\r\n\r\n.image-item:hover .delete-btn {\r\n opacity: 1;\r\n}\r\n\r\n.delete-btn:hover {\r\n background-color: rgba(0, 0, 0, 0.8);\r\n}\r\n\r\n.icon-delete {\r\n font-size: 12px;\r\n color: #fff;\r\n}\r\n\r\n/* 单图和多图共用样式 */\r\n.image-uploader {\r\n display: inline-block;\r\n vertical-align: top;\r\n}\r\n\r\n.image-uploader :deep(.el-upload) {\r\n border: 1px dashed var(--el-border-color);\r\n border-radius: 6px;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n transition: var(--el-transition-duration-fast);\r\n width: 74px !important;\r\n height: 74px !important;\r\n}\r\n\r\n.image-uploader :deep(.el-upload:hover) {\r\n border-color: var(--el-color-primary);\r\n}\r\n\r\n.uploader-icon {\r\n font-size: 20px;\r\n color: #8c939d;\r\n width: 74px;\r\n height: 74px;\r\n text-align: center;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.single-image-item {\r\n cursor: default;\r\n}\r\n\r\n.image-actions {\r\n position: absolute;\r\n inset: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 12px;\r\n opacity: 0;\r\n transition: opacity 0.3s;\r\n}\r\n\r\n.single-image-item:hover .image-actions,\r\n.image-item:hover .image-actions {\r\n opacity: 1;\r\n}\r\n\r\n.action-icon {\r\n font-size: 18px;\r\n color: #fff;\r\n cursor: pointer;\r\n transition: transform 0.2s;\r\n}\r\n\r\n.action-icon:hover {\r\n transform: scale(1.2);\r\n}\r\n\r\n.upload-tip {\r\n margin-top: 8px;\r\n font-size: 12px;\r\n color: #909399;\r\n line-height: 1.5;\r\n}\r\n</style>\r\n","<template>\r\n <Icon v-if=\"icon\" :icon=\"icon\" :width=\"size\" :height=\"size\" v-bind=\"$attrs\" />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { Icon } from '@iconify/vue'\r\n\r\ndefineOptions({\r\n name: 'JIconRender'\r\n})\r\n\r\nwithDefaults(defineProps<{\r\n icon: string\r\n size?: string | number\r\n}>(), {\r\n size: 24,\r\n})\r\n</script>\r\n","<template>\r\n <el-card shadow=\"never\" class=\"j-search-header-card\">\r\n <el-form inline class=\"search-form\">\r\n <div\r\n ref=\"formItemsRef\"\r\n class=\"form-items-wrapper\"\r\n :class=\"{ 'is-animated': isAnimated }\"\r\n >\r\n <slot />\r\n </div>\r\n </el-form>\r\n\r\n <div class=\"action-bar\" :style=\"{ marginTop: expanded ? '0px' : '10px' }\">\r\n <div class=\"action-left\">\r\n <el-button v-if=\"showAdd\" type=\"primary\" :icon=\"Plus\" @click=\"emit('add')\">\r\n {{ addText }}\r\n </el-button>\r\n <el-button\r\n v-if=\"showBatchDelete\"\r\n type=\"danger\"\r\n :icon=\"Delete\"\r\n :disabled=\"selectedCount === 0\"\r\n @click=\"emit('batchDelete')\"\r\n >\r\n 批量删除{{ selectedCount ? `(${selectedCount})` : '' }}\r\n </el-button>\r\n <el-button v-if=\"showSearch\" type=\"primary\" :icon=\"Search\" @click=\"emit('search')\">搜索</el-button>\r\n <el-button v-if=\"showReset\" :icon=\"Refresh\" @click=\"emit('reset')\">重置</el-button>\r\n <slot name=\"actions\" />\r\n </div>\r\n <el-button\r\n v-if=\"shouldCollapse\"\r\n link\r\n type=\"primary\"\r\n @click=\"toggleExpand\"\r\n >\r\n {{ expanded ? '收起' : '展开' }}\r\n <el-icon class=\"toggle-icon\" :class=\"{ 'is-expanded': expanded }\">\r\n <ArrowDown />\r\n </el-icon>\r\n </el-button>\r\n </div>\r\n </el-card>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted, onBeforeUnmount } from 'vue'\r\nimport { ElCard, ElForm, ElButton, ElIcon } from 'element-plus'\r\nimport { Search, Refresh, Plus, Delete, ArrowDown } from '@element-plus/icons-vue'\r\n\r\ndefineOptions({\r\n name: 'JSearchHeader'\r\n})\r\n\r\nconst props = withDefaults(defineProps<{\r\n selectedCount?: number\r\n addText?: string\r\n defaultVisible?: number\r\n showAdd?: boolean\r\n showBatchDelete?: boolean\r\n showSearch?: boolean\r\n showReset?: boolean\r\n}>(), {\r\n selectedCount: 0,\r\n addText: '新增',\r\n defaultVisible: 5,\r\n showAdd: true,\r\n showBatchDelete: true,\r\n showSearch: true,\r\n showReset: true\r\n})\r\n\r\nconst emit = defineEmits<{\r\n search: []\r\n reset: []\r\n add: []\r\n batchDelete: []\r\n}>()\r\n\r\nconst formItemsRef = ref<HTMLElement>()\r\nconst expanded = ref(false)\r\nconst isAnimated = ref(false)\r\nconst itemCount = ref(0)\r\nconst collapsedHeight = ref(0)\r\n\r\nconst shouldCollapse = computed(() => itemCount.value > props.defaultVisible)\r\n\r\nconst measureItems = () => {\r\n if (!formItemsRef.value) return\r\n const items = Array.from(formItemsRef.value.children) as HTMLElement[]\r\n itemCount.value = items.length\r\n\r\n const lastVisibleItem = items[props.defaultVisible - 1]\r\n if (lastVisibleItem && formItemsRef.value) {\r\n const wrapperRect = formItemsRef.value.getBoundingClientRect()\r\n const lastVisibleRect = lastVisibleItem.getBoundingClientRect()\r\n collapsedHeight.value = lastVisibleRect.bottom - wrapperRect.top\r\n }\r\n}\r\n\r\nconst toggleExpand = () => {\r\n const el = formItemsRef.value\r\n if (!el) return\r\n\r\n if (!expanded.value) {\r\n expanded.value = true\r\n el.style.maxHeight = el.scrollHeight + 'px'\r\n const onEnd = () => {\r\n el.style.maxHeight = 'none'\r\n el.removeEventListener('transitionend', onEnd)\r\n }\r\n el.addEventListener('transitionend', onEnd)\r\n } else {\r\n measureItems()\r\n expanded.value = false\r\n el.style.maxHeight = el.scrollHeight + 'px'\r\n el.offsetHeight\r\n el.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n}\r\n\r\nlet observer: MutationObserver | null = null\r\n\r\nonMounted(() => {\r\n measureItems()\r\n if (shouldCollapse.value && formItemsRef.value) {\r\n formItemsRef.value.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n isAnimated.value = true\r\n })\r\n })\r\n if (formItemsRef.value) {\r\n observer = new MutationObserver(() => {\r\n measureItems()\r\n if (shouldCollapse.value && !expanded.value && formItemsRef.value) {\r\n formItemsRef.value.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n })\r\n observer.observe(formItemsRef.value, { childList: true })\r\n }\r\n})\r\n\r\nonBeforeUnmount(() => {\r\n observer?.disconnect()\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.j-search-header-card :deep(.el-card__body) {\r\n padding: 16px 20px 12px;\r\n}\r\n\r\n.search-form {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: 0;\r\n}\r\n\r\n.form-items-wrapper {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n overflow: hidden;\r\n}\r\n\r\n.form-items-wrapper.is-animated {\r\n transition: max-height 0.3s ease-in-out;\r\n}\r\n\r\n.form-items-wrapper :deep(.el-form-item) {\r\n margin-bottom: 10px;\r\n margin-right: 16px;\r\n}\r\n\r\n.action-bar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding-top: 10px;\r\n border-top: 1px solid #ebeef5;\r\n}\r\n\r\n.action-left {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.toggle-icon {\r\n margin-left: 2px;\r\n transition: transform 0.25s;\r\n}\r\n\r\n.toggle-icon.is-expanded {\r\n transform: rotate(180deg);\r\n}\r\n</style>\r\n","<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n :title=\"props.title\"\r\n width=\"900px\"\r\n :close-on-click-modal=\"false\"\r\n @open=\"handleOpen\"\r\n @close=\"handleClose\"\r\n >\r\n <!-- 上传区域 -->\r\n <el-card shadow=\"never\" class=\"j-import-upload-card\">\r\n <div class=\"j-import-upload-card-title\">导入 EXCEL</div>\r\n <el-divider style=\"margin: 10px 0\" />\r\n <div class=\"j-import-upload-row\">\r\n <el-upload\r\n accept=\".xlsx,.xls\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n >\r\n <el-button size=\"small\">点击上传</el-button>\r\n </el-upload>\r\n <el-link\r\n v-if=\"dataColumns.length\"\r\n type=\"primary\"\r\n class=\"j-import-no-wrap\"\r\n @click=\"handleDownloadTemplate\"\r\n >\r\n 下载导入模板.xlsx\r\n </el-link>\r\n </div>\r\n </el-card>\r\n\r\n <!-- 统计信息 + 确认导入 -->\r\n <el-row class=\"j-import-stats-row\" :gutter=\"20\" align=\"middle\">\r\n <el-col :span=\"18\">\r\n <el-row class=\"j-import-stats-cols\">\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.total }}</div>\r\n <div class=\"j-import-stat-label\">导入数量</div>\r\n </el-col>\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.fail }}</div>\r\n <div class=\"j-import-stat-label\">失败数量</div>\r\n </el-col>\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.success }}</div>\r\n <div class=\"j-import-stat-label\">成功数量</div>\r\n </el-col>\r\n </el-row>\r\n </el-col>\r\n <el-col :span=\"6\" class=\"j-import-confirm-col\">\r\n <el-button\r\n type=\"primary\"\r\n size=\"small\"\r\n :loading=\"submitting\"\r\n :disabled=\"!renderData.length\"\r\n @click=\"handleConfirm\"\r\n >\r\n 确认导入\r\n </el-button>\r\n </el-col>\r\n </el-row>\r\n\r\n <!-- 数据表格 -->\r\n <el-table :data=\"renderData\" border size=\"small\" max-height=\"360\" class=\"j-import-data-table\">\r\n <el-table-column\r\n v-for=\"col in dataColumns\"\r\n :key=\"col.prop\"\r\n :prop=\"col.prop\"\r\n :label=\"col.label\"\r\n :min-width=\"120\"\r\n show-overflow-tooltip\r\n />\r\n <el-table-column label=\"状态\" width=\"110\" align=\"center\" fixed=\"right\">\r\n <template #default=\"{ row }\">\r\n <span v-if=\"row._status === -1\" class=\"j-import-status-fail\">\r\n {{ row._error || '创建失败' }}\r\n </span>\r\n <span v-else>{{ statusMap[row._status] }}</span>\r\n </template>\r\n </el-table-column>\r\n <el-table-column label=\"操作\" width=\"80\" align=\"center\" fixed=\"right\">\r\n <template #default=\"{ $index, row }\">\r\n <el-button\r\n v-if=\"row._status === 0\"\r\n size=\"small\"\r\n @click=\"handleDel($index)\"\r\n >\r\n 删除\r\n </el-button>\r\n </template>\r\n </el-table-column>\r\n </el-table>\r\n\r\n <template #footer>\r\n <el-button @click=\"handleClose\">关闭</el-button>\r\n </template>\r\n </el-dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from 'vue'\r\nimport { ElMessage, ElDialog, ElCard, ElDivider, ElUpload, ElButton, ElLink, ElRow, ElCol, ElTable, ElTableColumn } from 'element-plus'\r\nimport type { UploadFile } from 'element-plus'\r\nimport * as XLSX from 'xlsx'\r\nimport type { JImportExcelProps } from './types'\r\n\r\ndefineOptions({ name: 'JImportExcel' })\r\n\r\nconst props = withDefaults(defineProps<JImportExcelProps>(), {\r\n excludeFields: () => ['id', 'ctime', 'mtime'],\r\n title: 'Excel 批量导入',\r\n})\r\n\r\nconst emit = defineEmits<{\r\n success: []\r\n}>()\r\n\r\nconst visible = defineModel<boolean>({ default: false })\r\nconst submitting = ref(false)\r\nconst fieldMap = ref<Record<string, string>>({})\r\nconst renderData = ref<Record<string, any>[]>([])\r\nconst stats = ref({ total: 0, success: 0, fail: 0 })\r\n\r\nconst statusMap: Record<number, string> = {\r\n 0: '待创建',\r\n 1: '创建成功',\r\n 2: '创建中',\r\n [-1]: '创建失败',\r\n}\r\n\r\n/** 过滤后的表头列 */\r\nconst dataColumns = computed(() => {\r\n return Object.entries(fieldMap.value)\r\n .filter(([key]) => !props.excludeFields.includes(key))\r\n .map(([key, label]) => ({ id: key, label, prop: key }))\r\n})\r\n\r\n/** 弹窗打开时获取字段列表 */\r\nconst handleOpen = async () => {\r\n try {\r\n const res = await props.getFieldListApi()\r\n fieldMap.value = res.data.tableFieldsInfo ?? {}\r\n } catch {\r\n ElMessage.error('获取字段列表失败')\r\n }\r\n}\r\n\r\n/** 文件上传解析 */\r\nconst handleFileChange = (uploadFile: UploadFile) => {\r\n const raw = uploadFile.raw\r\n if (!raw) return\r\n\r\n const validTypes = [\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n 'application/vnd.ms-excel',\r\n ]\r\n if (!validTypes.includes(raw.type) && !raw.name.match(/\\.xlsx?$/i)) {\r\n ElMessage.warning('请上传 .xlsx 或 .xls 格式文件')\r\n return\r\n }\r\n\r\n const reader = new FileReader()\r\n reader.onload = (e) => {\r\n try {\r\n const workbook = XLSX.read(e.target!.result, { type: 'binary' })\r\n const wsName = workbook.SheetNames[0] as string\r\n const ws = workbook.Sheets[wsName]!\r\n const rows = XLSX.utils.sheet_to_json(ws, {\r\n header: 1,\r\n defval: '',\r\n }) as any[][]\r\n\r\n const dataRows = rows.slice(1).filter((row) => row.some((cell) => cell !== ''))\r\n\r\n if (!dataRows.length) {\r\n ElMessage.warning('文件内容为空')\r\n return\r\n }\r\n\r\n // 按后端字段顺序一一映射,空单元格由 defval 补 '',避免后续列顶上来\r\n const list: Record<string, any>[] = dataRows.map((row) => {\r\n const item: Record<string, any> = { _status: 0, _error: '' }\r\n dataColumns.value.forEach((col, index) => {\r\n item[col.prop] = row[index] !== undefined ? row[index] : ''\r\n })\r\n return item\r\n })\r\n\r\n renderData.value = list\r\n stats.value = { total: list.length, success: 0, fail: 0 }\r\n } catch {\r\n ElMessage.error('解析文件失败,请检查文件格式')\r\n }\r\n }\r\n reader.readAsBinaryString(raw)\r\n}\r\n\r\n/** 删除行 */\r\nconst handleDel = (idx: number) => {\r\n renderData.value.splice(idx, 1)\r\n stats.value.total = renderData.value.length\r\n}\r\n\r\n/** 确认导入 */\r\nconst handleConfirm = async () => {\r\n const data = renderData.value\r\n .filter((row) => row._status === 0)\r\n .map(({ _status, _error, ...rest }) => rest)\r\n\r\n if (!data.length) {\r\n ElMessage.warning('没有可导入的数据')\r\n return\r\n }\r\n\r\n submitting.value = true\r\n try {\r\n const res = await props.importApi(data)\r\n if (res.code === 1) {\r\n // 全部成功\r\n renderData.value.forEach((row) => {\r\n if (row._status === 0) row._status = 1\r\n })\r\n stats.value.success = renderData.value.filter((r) => r._status === 1).length\r\n ElMessage.success('导入成功')\r\n emit('success')\r\n } else {\r\n ElMessage.error(res.msg || '导入失败')\r\n }\r\n } catch {\r\n ElMessage.error('导入失败,请重试')\r\n } finally {\r\n submitting.value = false\r\n }\r\n}\r\n\r\n/** 下载导入模板 */\r\nconst handleDownloadTemplate = () => {\r\n try {\r\n const wb = XLSX.utils.book_new()\r\n const headers = dataColumns.value.map((col) => col.label)\r\n const tr: Record<string, string> = {}\r\n headers.forEach((h) => (tr[h] = ''))\r\n const ws = XLSX.utils.json_to_sheet([tr])\r\n XLSX.utils.book_append_sheet(wb, ws, '模板')\r\n XLSX.writeFile(wb, '导入模板.xlsx')\r\n } catch {\r\n ElMessage.error('模板下载失败')\r\n }\r\n}\r\n\r\nconst handleClose = () => {\r\n if (!submitting.value) {\r\n visible.value = false\r\n renderData.value = []\r\n stats.value = { total: 0, success: 0, fail: 0 }\r\n }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-import-upload-card {\r\n margin-bottom: 16px;\r\n}\r\n.j-import-upload-card-title {\r\n font-size: 14px;\r\n color: #606266;\r\n}\r\n.j-import-upload-row {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n.j-import-no-wrap {\r\n white-space: nowrap;\r\n}\r\n.j-import-stats-row {\r\n margin: 12px 0;\r\n}\r\n.j-import-stats-cols {\r\n text-align: center;\r\n line-height: 1.5;\r\n}\r\n.j-import-stat-item {\r\n padding: 0 8px;\r\n}\r\n.j-import-stat-num {\r\n font-size: 20px;\r\n}\r\n.j-import-stat-label {\r\n font-size: 12px;\r\n color: #909399;\r\n}\r\n.j-import-confirm-col {\r\n text-align: right;\r\n padding-top: 10px;\r\n}\r\n.j-import-data-table {\r\n margin-top: 10px;\r\n}\r\n.j-import-status-fail {\r\n color: #f56c6c;\r\n font-size: 12px;\r\n}\r\n</style>\r\n","<template>\r\n <!-- 有子菜单:渲染 el-sub-menu -->\r\n <el-sub-menu\r\n v-if=\"menuItem.children && menuItem.children.length > 0\"\r\n :index=\"menuItem.path\"\r\n :class=\"[`j-sidebar__depth-${depth}`]\"\r\n >\r\n <template #title>\r\n <JIconRender v-if=\"menuItem.icon && depth === 0\" :icon=\"menuItem.icon\" />\r\n <span class=\"j-sidebar__menu-item-title\">{{ menuItem.title || menuItem.name }}</span>\r\n </template>\r\n <!-- 递归渲染子菜单 -->\r\n <JSideMenuItem\r\n v-for=\"child in menuItem.children\"\r\n :key=\"child.path\"\r\n :menu-item=\"child\"\r\n :is-collapse=\"isCollapse\"\r\n :depth=\"depth + 1\"\r\n @menu-click=\"(item) => emit('menu-click', item)\"\r\n />\r\n </el-sub-menu>\r\n\r\n <!-- 无子菜单:渲染 el-menu-item -->\r\n <el-menu-item\r\n v-else\r\n :index=\"menuItem.path\"\r\n :class=\"[`j-sidebar__depth-${depth}`]\"\r\n @click=\"handleClick\"\r\n >\r\n <JIconRender v-if=\"menuItem.icon && depth === 0\" :icon=\"menuItem.icon\" />\r\n <template #title>\r\n <span>{{ menuItem.title || menuItem.name }}</span>\r\n </template>\r\n </el-menu-item>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport type { SidebarMenuItem } from './types'\r\nimport { ElSubMenu, ElMenuItem } from 'element-plus'\r\nimport { JIconRender } from '../JIconRender'\r\n\r\ndefineOptions({\r\n name: 'JSideMenuItem'\r\n})\r\n\r\ninterface Props {\r\n menuItem: SidebarMenuItem\r\n isCollapse?: boolean\r\n depth?: number\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), { depth: 0 })\r\n\r\nconst emit = defineEmits<{\r\n 'menu-click': [item: SidebarMenuItem]\r\n}>()\r\n\r\nconst handleClick = () => {\r\n emit('menu-click', props.menuItem)\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-sidebar__menu-item-title {\r\n padding: 0 10px;\r\n}\r\n\r\n/* 二级菜单:灰色标题,作为分类标签 */\r\n.j-sidebar__depth-1 > :deep(.el-sub-menu__title) {\r\n color: #909399;\r\n font-size: 13px;\r\n}\r\n\r\n/* 二级叶子菜单(无子项)也用灰色 */\r\n:deep(.j-sidebar__depth-1.el-menu-item) {\r\n color: #909399;\r\n font-size: 13px;\r\n}\r\n\r\n/* 三级菜单:文字稍大 */\r\n:deep(.j-sidebar__depth-2.el-menu-item) {\r\n font-size: 15px;\r\n}\r\n</style>\r\n","<template>\r\n <div\r\n :class=\"['j-sidebar', innerCollapsed ? 'j-sidebar--collapsed' : 'j-sidebar--expanded']\"\r\n :style=\"{ width: innerCollapsed ? `${collapsedWidth}px` : `${expandedWidth}px` }\"\r\n >\r\n <!-- Logo 区域 -->\r\n <div class=\"j-sidebar__logo\">\r\n <slot name=\"logo\" :collapsed=\"innerCollapsed\">\r\n <h2 class=\"j-sidebar__title\">\r\n {{ innerCollapsed ? (collapsedTitle || title?.charAt(0) || '') : title }}\r\n </h2>\r\n </slot>\r\n </div>\r\n\r\n <!-- 菜单区域 -->\r\n <div class=\"j-sidebar__menu-wrapper\">\r\n <el-menu\r\n :default-active=\"activeMenu\"\r\n class=\"j-sidebar__menu\"\r\n :router=\"router\"\r\n :collapse=\"innerCollapsed\"\r\n :collapse-transition=\"false\"\r\n >\r\n <JSideMenuItem\r\n v-for=\"route in menus\"\r\n :key=\"route.path\"\r\n :menu-item=\"route\"\r\n :is-collapse=\"innerCollapsed\"\r\n @menu-click=\"(item) => emit('menu-click', item)\"\r\n />\r\n </el-menu>\r\n </div>\r\n\r\n <!-- 底部折叠按钮 -->\r\n <div class=\"j-sidebar__footer\">\r\n <slot name=\"footer\" :collapsed=\"innerCollapsed\" :toggle=\"toggleCollapse\">\r\n <button\r\n class=\"j-sidebar__collapse-btn\"\r\n @click=\"toggleCollapse\"\r\n >\r\n <JIconRender :icon=\"innerCollapsed ? 'mdi:chevron-right' : 'mdi:chevron-left'\" />\r\n </button>\r\n </slot>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch } from 'vue'\r\nimport { ElMenu } from 'element-plus'\r\nimport type { SidebarMenuItem } from './types'\r\nimport JSideMenuItem from './JSideMenuItem.vue'\r\nimport { JIconRender } from '../JIconRender'\r\n\r\ndefineOptions({\r\n name: 'JSidebar'\r\n})\r\n\r\ninterface Props {\r\n menus: SidebarMenuItem[]\r\n activeMenu?: string\r\n title?: string\r\n collapsedTitle?: string\r\n collapsed?: boolean\r\n collapsedWidth?: number\r\n expandedWidth?: number\r\n router?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n activeMenu: '',\r\n title: '',\r\n collapsedTitle: '',\r\n collapsed: false,\r\n collapsedWidth: 80,\r\n expandedWidth: 200,\r\n router: true,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:collapsed': [value: boolean]\r\n 'menu-click': [item: SidebarMenuItem]\r\n}>()\r\n\r\nconst innerCollapsed = ref(props.collapsed)\r\n\r\nwatch(() => props.collapsed, (val) => {\r\n innerCollapsed.value = val\r\n})\r\n\r\nconst toggleCollapse = () => {\r\n innerCollapsed.value = !innerCollapsed.value\r\n emit('update:collapsed', innerCollapsed.value)\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.j-sidebar {\r\n position: relative;\r\n background-color: $color-white;\r\n box-shadow: 2px 0 6px rgba(0, 21, 41, 0.08);\r\n overflow-x: hidden;\r\n transition: width 0.3s ease-in-out;\r\n flex-shrink: 0;\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n}\r\n\r\n.j-sidebar__logo {\r\n padding: 0 $spacing-md;\r\n display: flex;\r\n align-items: center;\r\n height: 50px;\r\n flex-shrink: 0;\r\n}\r\n\r\n\r\n.j-sidebar__title {\r\n margin: 0;\r\n font-size: $font-size-lg;\r\n font-weight: bold;\r\n color: $color-primary;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n}\r\n\r\n.j-sidebar__menu-wrapper {\r\n flex: 1;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n}\r\n\r\n.j-sidebar__menu {\r\n border: none;\r\n width: 100%;\r\n}\r\n\r\n.j-sidebar__footer {\r\n flex-shrink: 0;\r\n padding: $spacing-sm;\r\n display: flex;\r\n}\r\n\r\n// 折叠状态:覆盖 el-menu 样式,图标+文字上下排列\r\n.j-sidebar--collapsed {\r\n :deep(.el-menu--collapse) {\r\n width: 100%;\r\n\r\n .el-menu-item,\r\n .el-sub-menu__title {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n height: auto;\r\n line-height: normal;\r\n padding: $spacing-sm 0 !important;\r\n\r\n .el-icon,\r\n .iconify {\r\n margin: 0;\r\n }\r\n\r\n span {\r\n display: block !important;\r\n visibility: visible !important;\r\n overflow: visible !important;\r\n width: auto !important;\r\n height: auto !important;\r\n font-size: $font-size-xs;\r\n margin-top: $spacing-xs;\r\n }\r\n }\r\n\r\n // 隐藏子菜单展开箭头\r\n .el-sub-menu__icon-arrow {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n.j-sidebar__collapse-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: $spacing-sm;\r\n border: none;\r\n border-radius: $border-radius-base;\r\n background-color: transparent;\r\n color: $color-text-secondary;\r\n cursor: pointer;\r\n transition: $transition-fast;\r\n\r\n &:hover {\r\n background-color: $color-bg-base;\r\n color: $color-primary;\r\n }\r\n\r\n}\r\n</style>\r\n","<template>\n <div class=\"j-admin-layout\" :style=\"layoutStyle\">\n <JSidebar\n v-if=\"sideMenus.length > 0\"\n v-model:collapsed=\"innerCollapsed\"\n :menus=\"sideMenus\"\n :active-menu=\"activeMenu\"\n :title=\"title\"\n :collapsed-title=\"collapsedTitle\"\n :collapsed-width=\"sidebarCollapsedWidth\"\n :expanded-width=\"sidebarExpandedWidth\"\n @menu-click=\"handleSideMenuClick\"\n >\n <template v-if=\"$slots.sidebarFooter\" #footer=\"{ collapsed: sidebarCollapsed, toggle }\">\n <slot name=\"sidebarFooter\" :collapsed=\"sidebarCollapsed\" :toggle=\"toggle\" />\n </template>\n </JSidebar>\n\n <div class=\"j-admin-layout__right-panel\">\n <div class=\"j-admin-layout__header\">\n <div class=\"j-admin-layout__header-left\">\n <div v-if=\"sideMenus.length === 0\" class=\"j-admin-layout__logo\">\n <slot name=\"logo\">\n <h2>{{ logoTitle || title }}</h2>\n </slot>\n </div>\n\n <el-menu\n mode=\"horizontal\"\n :default-active=\"activeTopMenu\"\n class=\"j-admin-layout__top-menu\"\n @select=\"handleTopMenuSelect\"\n >\n <el-menu-item\n v-for=\"menu in topMenus\"\n :key=\"menu.path\"\n :index=\"menu.path\"\n >\n <JIconRender v-if=\"menu.icon\" :icon=\"menu.icon\" class=\"j-admin-layout__top-menu-icon\" />\n <span>{{ menu.title || menu.name }}</span>\n </el-menu-item>\n </el-menu>\n </div>\n\n <div class=\"j-admin-layout__header-right\">\n <slot name=\"headerRight\" :username=\"username\">\n <el-dropdown v-if=\"showProfile || showLogout\">\n <span class=\"j-admin-layout__user\">\n {{ username }}\n <el-icon>\n <ArrowDown />\n </el-icon>\n </span>\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item v-if=\"showProfile\" @click=\"emit('profile')\">\n {{ profileText }}\n </el-dropdown-item>\n <el-dropdown-item v-if=\"showLogout\" @click=\"emit('logout')\">\n {{ logoutText }}\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </slot>\n </div>\n </div>\n\n <div class=\"j-admin-layout__content-container\">\n <slot name=\"tabs\" />\n <div\n :class=\"[\n 'j-admin-layout__content',\n { 'j-admin-layout__content--scrollbar-hidden': hideContentScrollbar }\n ]\"\n >\n <slot />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ElMenu, ElMenuItem, ElDropdown, ElDropdownMenu, ElDropdownItem, ElIcon } from 'element-plus'\nimport { ArrowDown } from '@element-plus/icons-vue'\nimport { JSidebar, type SidebarMenuItem } from '../JSidebar'\nimport { JIconRender } from '../JIconRender'\nimport type { AdminLayoutMenuItem } from './types'\n\ndefineOptions({\n name: 'JAdminLayout'\n})\n\ninterface Props {\n topMenus: AdminLayoutMenuItem[]\n sideMenus: AdminLayoutMenuItem[]\n activeTopMenu?: string\n activeMenu?: string\n title?: string\n logoTitle?: string\n collapsedTitle?: string\n collapsed?: boolean\n username?: string\n profileText?: string\n logoutText?: string\n sidebarCollapsedWidth?: number\n sidebarExpandedWidth?: number\n headerHeight?: string\n contentPadding?: string\n contentBackground?: string\n headerBackground?: string\n showProfile?: boolean\n showLogout?: boolean\n hideContentScrollbar?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n activeTopMenu: '',\n activeMenu: '',\n title: '',\n logoTitle: '',\n collapsedTitle: '',\n collapsed: false,\n username: '',\n profileText: '个人资料',\n logoutText: '退出登录',\n sidebarCollapsedWidth: 80,\n sidebarExpandedWidth: 200,\n headerHeight: '50px',\n contentPadding: '10px',\n contentBackground: '#f0f2f5',\n headerBackground: '#ffffff',\n showProfile: true,\n showLogout: true,\n hideContentScrollbar: false,\n})\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean]\n 'top-menu-select': [path: string]\n 'side-menu-click': [item: SidebarMenuItem]\n profile: []\n logout: []\n}>()\n\nconst innerCollapsed = computed({\n get: () => props.collapsed,\n set: value => emit('update:collapsed', value),\n})\n\nconst layoutStyle = computed(() => ({\n '--j-admin-layout-header-height': props.headerHeight,\n '--j-admin-layout-content-padding': props.contentPadding,\n '--j-admin-layout-content-bg': props.contentBackground,\n '--j-admin-layout-header-bg': props.headerBackground,\n}))\n\nconst handleTopMenuSelect = (path: string) => {\n emit('top-menu-select', path)\n}\n\nconst handleSideMenuClick = (item: SidebarMenuItem) => {\n emit('side-menu-click', item)\n}\n</script>\n\n<style scoped lang=\"scss\">\n.j-admin-layout {\n width: 100vw;\n height: 100vh;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n}\n\n.j-admin-layout__right-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--j-admin-layout-content-bg);\n}\n\n.j-admin-layout__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: var(--j-admin-layout-header-bg);\n box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);\n height: var(--j-admin-layout-header-height);\n flex-shrink: 0;\n z-index: 100;\n}\n\n.j-admin-layout__header-left {\n display: flex;\n align-items: center;\n flex: 1;\n height: 100%;\n min-width: 0;\n}\n\n.j-admin-layout__logo {\n padding: 0 $spacing-md;\n display: flex;\n align-items: center;\n height: var(--j-admin-layout-header-height);\n flex-shrink: 0;\n}\n\n.j-admin-layout__logo h2 {\n margin: 0;\n font-size: $font-size-lg;\n font-weight: bold;\n color: $color-primary;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.j-admin-layout__top-menu {\n flex: 1;\n height: var(--j-admin-layout-header-height);\n border-bottom: none;\n min-width: 0;\n}\n\n.j-admin-layout__top-menu-icon {\n margin-right: $spacing-xs;\n}\n\n.j-admin-layout__header-right {\n display: flex;\n align-items: center;\n gap: $spacing-md;\n padding-right: $spacing-md;\n flex-shrink: 0;\n}\n\n.j-admin-layout__user {\n cursor: pointer;\n display: flex;\n align-items: center;\n color: $color-text-regular;\n}\n\n.j-admin-layout__user:hover {\n color: $color-primary;\n}\n\n.j-admin-layout__content-container {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n background-color: var(--j-admin-layout-content-bg);\n}\n\n.j-admin-layout__content {\n padding: var(--j-admin-layout-content-padding);\n flex: 1;\n overflow: auto;\n}\n\n.j-admin-layout__content--scrollbar-hidden {\n scrollbar-width: none;\n -ms-overflow-style: none;\n\n &::-webkit-scrollbar {\n display: none;\n }\n}\n</style>\n","/**\r\n * 递归转换值(处理嵌套对象和数组)\r\n */\r\nfunction deepTransformValue(value: any, transformer: (obj: Record<string, any>) => Record<string, any>): any {\r\n if (Array.isArray(value)) {\r\n return value.map((item) => deepTransformValue(item, transformer))\r\n }\r\n if (value !== null && typeof value === 'object' && !(value instanceof Date)) {\r\n return transformer(value)\r\n }\r\n return value\r\n}\r\n\r\n/**\r\n * 将对象的 key 从小驼峰转为下划线格式(支持深度嵌套)\r\n * @param obj 需要转换的对象\r\n * @param excludeKeys 不需要转换的 key 数组(可选)\r\n */\r\nexport function toSnakeCase<T extends Record<string, any>>(\r\n obj: T,\r\n excludeKeys: string[] = []\r\n): Record<string, any> {\r\n return Object.fromEntries(\r\n Object.entries(obj).map(([key, value]) => {\r\n const newValue = deepTransformValue(value, (v) => toSnakeCase(v, excludeKeys))\r\n if (excludeKeys.includes(key)) {\r\n return [key, newValue]\r\n }\r\n const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase()\r\n return [snakeKey, newValue]\r\n })\r\n )\r\n}\r\n\r\n/**\r\n * 将对象的 key 从下划线格式转为小驼峰(支持深度嵌套)\r\n * @param obj 需要转换的对象\r\n * @param excludeKeys 不需要转换的 key 数组(可选)\r\n */\r\nexport function toCamelCase<T extends Record<string, any>>(\r\n obj: T,\r\n excludeKeys: string[] = []\r\n): Record<string, any> {\r\n return Object.fromEntries(\r\n Object.entries(obj).map(([key, value]) => {\r\n const newValue = deepTransformValue(value, (v) => toCamelCase(v, excludeKeys))\r\n if (excludeKeys.includes(key)) {\r\n return [key, newValue]\r\n }\r\n const camelKey = key.replace(/_([a-z])/g, (_, char) => char.toUpperCase())\r\n return [camelKey, newValue]\r\n })\r\n )\r\n}\r\n\r\n/**\r\n * 从对象中提取指定的 key\r\n * @param obj 源对象\r\n * @param keys 要提取的 key 数组\r\n */\r\nexport function pick<T extends Record<string, any>, K extends keyof T>(\r\n obj: T,\r\n keys: K[]\r\n): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 从对象中排除指定的 key\r\n * @param obj 源对象\r\n * @param keys 要排除的 key 数组\r\n */\r\nexport function omit<T extends Record<string, any>, K extends keyof T>(\r\n obj: T,\r\n keys: K[]\r\n): Omit<T, K> {\r\n const result = { ...obj }\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * 深拷贝对象\r\n * @param obj 需要拷贝的对象\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== 'object') return obj\r\n if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T\r\n if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags) as unknown as T\r\n if (Array.isArray(obj)) return obj.map((item) => deepClone(item)) as unknown as T\r\n const cloned = {} as Record<string, any>\r\n for (const key of Object.keys(obj)) {\r\n cloned[key] = deepClone((obj as Record<string, any>)[key])\r\n }\r\n return cloned as T\r\n}\r\n\r\n/**\r\n * 过滤对象中的空值(null、undefined、空字符串)\r\n * @param obj 需要过滤的对象\r\n * @param deep 是否递归过滤嵌套对象,默认 false\r\n */\r\nexport function filterEmpty<T extends Record<string, any>>(\r\n obj: T,\r\n deep = false\r\n): Partial<T> {\r\n const result = {} as Record<string, any>\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (value === null || value === undefined || value === '') continue\r\n if (deep && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\r\n const filtered = filterEmpty(value, true)\r\n if (Object.keys(filtered).length > 0) {\r\n result[key] = filtered\r\n }\r\n } else {\r\n result[key] = value\r\n }\r\n }\r\n return result as Partial<T>\r\n}\r\n\r\n/**\r\n * 将嵌套对象扁平化为单层对象\r\n * @param obj 需要扁平化的对象\r\n * @param prefix key 前缀,默认为空\r\n * @param separator 分隔符,默认为 '.'\r\n * @example flatten({ a: { b: 1, c: { d: 2 } } }) => { 'a.b': 1, 'a.c.d': 2 }\r\n */\r\nexport function flatten(\r\n obj: Record<string, any>,\r\n prefix = '',\r\n separator = '.'\r\n): Record<string, any> {\r\n const result: Record<string, any> = {}\r\n for (const [key, value] of Object.entries(obj)) {\r\n const newKey = prefix ? `${prefix}${separator}${key}` : key\r\n if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\r\n Object.assign(result, flatten(value, newKey, separator))\r\n } else {\r\n result[newKey] = value\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 将扁平化的对象还原为嵌套对象\r\n * @param obj 扁平化的对象\r\n * @param separator 分隔符,默认为 '.'\r\n * @example unflatten({ 'a.b': 1, 'a.c.d': 2 }) => { a: { b: 1, c: { d: 2 } } }\r\n */\r\nexport function unflatten(\r\n obj: Record<string, any>,\r\n separator = '.'\r\n): Record<string, any> {\r\n const result: Record<string, any> = {}\r\n for (const [key, value] of Object.entries(obj)) {\r\n const parts = key.split(separator)\r\n let current = result\r\n for (let i = 0; i < parts.length - 1; i++) {\r\n const k = parts[i] as string\r\n if (!(k in current)) {\r\n current[k] = {}\r\n }\r\n current = current[k]\r\n }\r\n current[parts[parts.length - 1] as string] = value\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 将 { key: label } 对象转换为 el-table-column 所需的表头数组\r\n * @param fieldMap 字段映射对象\r\n * @example toTableColumns({ id: '主键', name: '名称' }) => [{ id: 'id', label: '主键', prop: 'id' }, ...]\r\n */\r\nexport function toTableColumns(fieldMap: Record<string, string>) {\r\n return Object.entries(fieldMap).map(([key, label]) => ({\r\n id: key,\r\n label,\r\n prop: key,\r\n }))\r\n}\r\n","import type { RouteRecordRaw } from 'vue-router'\r\nimport type { BackendRoute } from './types'\r\n\r\ntype ViewModules = Record<string, () => Promise<unknown>>\r\n\r\ninterface RouteTreeNode extends BackendRoute {\r\n children?: RouteTreeNode[]\r\n}\r\n\r\nexport function getComponentImport(componentPath: string, viewModules: ViewModules): (() => Promise<unknown>) | null {\r\n if (!componentPath) return null\r\n\r\n let normalizedPath = componentPath.replace(/^@\\//, '')\r\n if (!normalizedPath.startsWith('views/')) normalizedPath = `views/${normalizedPath}`\r\n if (!normalizedPath.endsWith('.vue')) normalizedPath = `${normalizedPath}.vue`\r\n\r\n const fullPath = `/src/${normalizedPath}`\r\n\r\n return (viewModules[fullPath] ?? viewModules['/src/views/common/NotFound.vue'] ?? null) as (() => Promise<unknown>) | null\r\n}\r\n\r\nexport function buildRouteTree(routes: BackendRoute[]): RouteTreeNode[] {\r\n const routeMap = new Map<string, RouteTreeNode>()\r\n const rootRoutes: RouteTreeNode[] = []\r\n\r\n routes.forEach(route => routeMap.set(route.name, { ...route, children: [] }))\r\n\r\n routes.forEach(route => {\r\n const currentRoute = routeMap.get(route.name)!\r\n if (!route.parent_name) {\r\n rootRoutes.push(currentRoute)\r\n } else {\r\n const parentRoute = routeMap.get(route.parent_name)\r\n if (parentRoute) {\r\n parentRoute.children ??= []\r\n parentRoute.children.push(currentRoute)\r\n } else {\r\n rootRoutes.push(currentRoute)\r\n }\r\n }\r\n })\r\n return rootRoutes\r\n}\r\n\r\nexport function transformBackendRoutes(\r\n backendRoutes: RouteTreeNode[],\r\n viewModules: ViewModules,\r\n projectName?: string\r\n): RouteRecordRaw[] {\r\n return backendRoutes\r\n .filter(route => !projectName || !route.project || route.project === projectName)\r\n .map(route => {\r\n const routeConfig: Partial<RouteRecordRaw> = {\r\n path: route.path,\r\n name: route.name,\r\n meta: {\r\n requiresAuth: route.requiresAuth === 1,\r\n title: route.title,\r\n permissions: route.permissions\r\n ? route.permissions.split(',').map(p => p.trim()).filter(Boolean)\r\n : [],\r\n params: route.params\r\n ? route.params.split('&').map(p => p.trim()).filter(Boolean)\r\n : [],\r\n },\r\n }\r\n\r\n const component = getComponentImport(route.component, viewModules)\r\n if (component) routeConfig.component = component as RouteRecordRaw['component']\r\n\r\n if (route.redirect) routeConfig.redirect = route.redirect\r\n\r\n if (route.children?.length) {\r\n routeConfig.children = transformBackendRoutes(route.children, viewModules, projectName)\r\n }\r\n\r\n return routeConfig as RouteRecordRaw\r\n })\r\n}\r\n\r\nexport function findFirstAllowedRoute(\r\n backendRoutes: BackendRoute[],\r\n routePermissions: string[],\r\n layoutRouteName: string,\r\n projectName?: string\r\n): BackendRoute | undefined {\r\n const routeMap = new Map<string, BackendRoute>()\r\n backendRoutes.forEach(route => routeMap.set(route.name, route))\r\n\r\n const isDescendantOfLayout = (route: BackendRoute): boolean => {\r\n let parentName = route.parent_name\r\n const visited = new Set<string>()\r\n\r\n while (parentName) {\r\n if (parentName === layoutRouteName) return true\r\n if (visited.has(parentName)) return false\r\n\r\n visited.add(parentName)\r\n const parentRoute = routeMap.get(parentName)\r\n if (!parentRoute) return false\r\n parentName = parentRoute.parent_name\r\n }\r\n\r\n return false\r\n }\r\n\r\n return backendRoutes\r\n .filter(route =>\r\n route.name !== layoutRouteName &&\r\n route.is_show === 1 &&\r\n route.component &&\r\n routePermissions.includes(route.code) &&\r\n isDescendantOfLayout(route) &&\r\n (!projectName || !route.project || route.project === projectName)\r\n )\r\n .sort((a, b) => a.sorts - b.sorts)[0]\r\n}\r\n","import type { NavigationGuardNext, Router } from 'vue-router'\r\nimport NProgress from 'nprogress'\r\nimport 'nprogress/nprogress.css'\r\nimport { ElMessage } from 'element-plus'\r\nimport type { RouterGuardOptions } from './types'\r\nimport { buildRouteTree, transformBackendRoutes } from './helpers'\r\n\r\nNProgress.configure({ showSpinner: false })\r\n\r\nconst isDev = import.meta.env.DEV\r\nconst log = (...args: unknown[]) => { if (isDev) console.log('[Router]', ...args) }\r\nconst warn = (...args: unknown[]) => { if (isDev) console.warn('[Router]', ...args) }\r\nconst logError = (...args: unknown[]) => { console.error('[Router]', ...args) }\r\n\r\nexport function createRouterGuard(router: Router, options: RouterGuardOptions) {\r\n const {\r\n getRouteStore,\r\n getPermissionStore,\r\n getUserStore,\r\n isAuthenticated,\r\n viewModules,\r\n homeComponent,\r\n notFoundComponent,\r\n projectName,\r\n layoutRouteName = 'Layout',\r\n publicPaths = ['/login', '/register'],\r\n loginRouteName = 'login',\r\n forbiddenRouteName = 'Forbidden',\r\n homeRouteName = 'Home',\r\n homeRoutePath = 'home',\r\n homeTitle = '\\u9996\\u9875',\r\n noPermissionMessage = '\\u6682\\u65e0\\u6743\\u9650',\r\n } = options\r\n\r\n let hasAddedRoutes = false\r\n\r\n function addDynamicRoutes(backendRoutes: ReturnType<typeof getRouteStore>['backendRoutes']) {\r\n const treeRoutes = buildRouteTree(backendRoutes)\r\n const layoutRoute = treeRoutes.find(route => route.name === layoutRouteName)\r\n const childRoutes = layoutRoute?.children\r\n ? transformBackendRoutes(layoutRoute.children, viewModules, projectName)\r\n : []\r\n\r\n childRoutes.forEach(route => {\r\n if (route.name && router.hasRoute(route.name)) return\r\n router.addRoute(layoutRouteName, route)\r\n log(`Add route: ${String(route.name)} -> ${route.path}`)\r\n })\r\n\r\n if (!router.hasRoute(homeRouteName)) {\r\n router.addRoute(layoutRouteName, {\r\n path: homeRoutePath,\r\n name: homeRouteName,\r\n component: homeComponent as never,\r\n meta: { title: homeTitle },\r\n })\r\n }\r\n\r\n if (!router.hasRoute('NotFound')) {\r\n router.addRoute({\r\n path: '/:pathMatch(.*)*',\r\n name: 'NotFound',\r\n component: notFoundComponent as never,\r\n })\r\n }\r\n\r\n log(`Dynamic routes added: ${childRoutes.length}`)\r\n }\r\n\r\n function redirectToHomeOrContinue(\r\n toName: ReturnType<Router['resolve']>['name'],\r\n next: NavigationGuardNext\r\n ) {\r\n if (toName === homeRouteName) {\r\n next()\r\n return\r\n }\r\n\r\n if (router.hasRoute(homeRouteName)) {\r\n next({ name: homeRouteName, replace: true })\r\n } else {\r\n next()\r\n }\r\n }\r\n\r\n router.beforeEach(async (to, _from, next) => {\r\n NProgress.start()\r\n\r\n if (isAuthenticated() && !hasAddedRoutes) {\r\n try {\r\n const routeStore = getRouteStore()\r\n const permissionStore = getPermissionStore()\r\n\r\n await routeStore.initRoutes()\r\n await permissionStore.loadUserPermissions()\r\n\r\n addDynamicRoutes(routeStore.backendRoutes)\r\n hasAddedRoutes = true\r\n\r\n if (to.path === '/' || to.path === '') {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n if (to.name === layoutRouteName) {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n const currentRoute = routeStore.backendRoutes.find(route => route.name === to.name)\r\n if (currentRoute && !permissionStore.routePermissions.includes(currentRoute.code)) {\r\n warn('No route permission:', to.path)\r\n next({ name: forbiddenRouteName, replace: true })\r\n return\r\n }\r\n\r\n next({\r\n path: to.path,\r\n query: to.query,\r\n hash: to.hash,\r\n replace: true,\r\n })\r\n return\r\n } catch (err) {\r\n logError('Failed to load route permissions:', err)\r\n hasAddedRoutes = false\r\n await getUserStore().logout()\r\n next({ name: loginRouteName, replace: true })\r\n return\r\n }\r\n }\r\n\r\n if (publicPaths.includes(to.path)) {\r\n if (isAuthenticated()) {\r\n next({ path: '/', replace: true })\r\n } else {\r\n next()\r\n }\r\n return\r\n }\r\n\r\n if (!isAuthenticated()) {\r\n next({ name: loginRouteName, replace: true })\r\n return\r\n }\r\n\r\n const permissionStore = getPermissionStore()\r\n const routeStore = getRouteStore()\r\n\r\n if (to.name === homeRouteName) {\r\n next()\r\n return\r\n }\r\n\r\n if (permissionStore.routePermissions.length === 0) {\r\n if (to.path !== '/') {\r\n ElMessage.warning(noPermissionMessage)\r\n next({ path: '/', replace: true })\r\n } else {\r\n redirectToHomeOrContinue(to.name, next)\r\n }\r\n return\r\n }\r\n\r\n if (to.path === '/') {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n if (to.name === layoutRouteName) {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n const currentRoute = routeStore.backendRoutes.find(route => route.name === to.name)\r\n if (currentRoute && !permissionStore.routePermissions.includes(currentRoute.code)) {\r\n warn('No route permission:', to.path)\r\n next({ name: forbiddenRouteName, replace: true })\r\n return\r\n }\r\n\r\n next()\r\n })\r\n\r\n router.afterEach(() => NProgress.done())\r\n\r\n return {\r\n resetRouterState: () => { hasAddedRoutes = false },\r\n }\r\n}\r\n","import type { App } from 'vue'\r\nimport { JButton } from './components/JButton'\r\nimport { JUploadImg } from './components/JUploadImg'\r\nimport { JIconRender } from './components/JIconRender'\r\nimport { JSearchHeader } from './components/JSearchHeader'\r\nimport { JImportExcel } from './components/JImportExcel'\r\nimport { JSidebar, JSideMenuItem } from './components/JSidebar'\r\nimport { JAdminLayout } from './components/JAdminLayout'\r\n\r\n// 组件列表,新增组件后在此处注册\r\nconst components = [JButton, JUploadImg, JIconRender, JSearchHeader, JImportExcel, JSidebar, JSideMenuItem, JAdminLayout]\r\n\r\n// 全量安装插件(app.use(JgyComponents))\r\nconst install = (app: App) => {\r\n components.forEach((component) => {\r\n app.component(component.name ?? component.__name ?? '', component)\r\n })\r\n}\r\n\r\n// 默认导出插件对象\r\nexport default { install }\r\n\r\n// 按需导出各组件\r\nexport { JButton, JUploadImg, JIconRender, JSearchHeader, JImportExcel, JSidebar, JSideMenuItem, JAdminLayout }\r\n\r\n// 导出工具方法\r\nexport { toSnakeCase, toCamelCase, pick, omit, deepClone, filterEmpty, flatten, unflatten, toTableColumns } from './utils'\r\n\r\n// 导出路由工具\r\nexport { createRouterGuard, buildRouteTree, transformBackendRoutes, findFirstAllowedRoute, getComponentImport } from './router'\r\nexport type { BackendRoute, RouteStoreAdapter, PermissionStoreAdapter, UserStoreAdapter, RouterGuardOptions } from './router'\r\n\r\n// 导出类型\r\nexport type { ButtonType, ButtonSize } from './components/JButton'\r\nexport type { JUploadImgProps, JUploadImgEmits, ImageItem } from './components/JUploadImg'\r\nexport type { JIconRenderProps } from './components/JIconRender'\r\nexport type { JSearchHeaderProps } from './components/JSearchHeader'\r\nexport type { JImportExcelProps, ApiFn } from './components/JImportExcel'\r\nexport type { SidebarMenuItem, JSidebarProps, JSideMenuItemProps } from './components/JSidebar'\r\nexport type { AdminLayoutMenuItem, JAdminLayoutProps } from './components/JAdminLayout'\r\n"],"names":["props","__props","emit","__emit","handleClick","event","_createElementBlock","_openBlock","_hoisted_2","$slots","_hoisted_3","_renderSlot","_ctx","imageUrl","ref","showPreview","showTipText","handlePreviewSingle","handleRemoveSingle","ElMessage","imageList","uploading","initImageList","urls","url","index","watch","val","handleDragEnd","emitMultipleUpdate","handleRemove","handleFileChange","uploadFile","file","error","item","_hoisted_1","_createVNode","_unref","draggable","$event","_withCtx","element","_createElementVNode","ElImage","img","_withModifiers","ElIcon","Delete","_createBlock","ElUpload","Loading","Plus","_Fragment","_hoisted_5","_hoisted_6","ZoomIn","ElImageViewer","_hoisted_7","_hoisted_8","_toDisplayString","_mergeProps","$attrs","formItemsRef","expanded","isAnimated","itemCount","collapsedHeight","shouldCollapse","computed","measureItems","items","lastVisibleItem","wrapperRect","lastVisibleRect","toggleExpand","el","onEnd","observer","onMounted","onBeforeUnmount","ElCard","ElForm","_normalizeClass","ElButton","Search","_cache","Refresh","_createTextVNode","ArrowDown","visible","_useModel","submitting","fieldMap","renderData","stats","statusMap","dataColumns","key","label","handleOpen","res","raw","reader","e","workbook","XLSX","wsName","ws","dataRows","row","cell","list","col","handleDel","idx","handleConfirm","data","_status","_error","rest","r","handleDownloadTemplate","wb","headers","tr","h","handleClose","ElDialog","ElDivider","ElLink","ElRow","ElCol","_hoisted_4","ElTable","_renderList","ElTableColumn","$index","ElSubMenu","JIconRender","child","_component_JSideMenuItem","ElMenuItem","innerCollapsed","toggleCollapse","_normalizeStyle","_a","ElMenu","route","JSideMenuItem","value","layoutStyle","handleTopMenuSelect","path","handleSideMenuClick","JSidebar","sidebarCollapsed","toggle","menu","ElDropdown","ElDropdownMenu","ElDropdownItem","deepTransformValue","transformer","toSnakeCase","obj","excludeKeys","newValue","v","toCamelCase","_","char","pick","keys","result","omit","deepClone","cloned","filterEmpty","deep","filtered","flatten","prefix","separator","newKey","unflatten","parts","current","i","k","toTableColumns","getComponentImport","componentPath","viewModules","normalizedPath","fullPath","buildRouteTree","routes","routeMap","rootRoutes","currentRoute","parentRoute","transformBackendRoutes","backendRoutes","projectName","routeConfig","p","component","findFirstAllowedRoute","routePermissions","layoutRouteName","isDescendantOfLayout","parentName","visited","a","b","NProgress","log","args","warn","logError","createRouterGuard","router","options","getRouteStore","getPermissionStore","getUserStore","isAuthenticated","homeComponent","notFoundComponent","publicPaths","loginRouteName","forbiddenRouteName","homeRouteName","homeRoutePath","homeTitle","noPermissionMessage","hasAddedRoutes","addDynamicRoutes","layoutRoute","childRoutes","redirectToHomeOrContinue","toName","next","to","_from","routeStore","permissionStore","err","components","JButton","JUploadImg","JSearchHeader","JImportExcel","JAdminLayout","app"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.cjs","sources":["../src/components/JButton/JButton.vue","../src/components/JUploadImg/JUploadImg.vue","../src/components/JIconRender/JIconRender.vue","../src/components/JSearchHeader/JSearchHeader.vue","../src/components/JImportExcel/JImportExcel.vue","../src/components/JSidebar/JSideMenuItem.vue","../src/components/JSidebar/JSidebar.vue","../src/components/JAdminLayout/JAdminLayout.vue","../src/components/JProductDetail/JProductDetailDialog.vue","../src/components/JProductDetail/JSkuLink.vue","../src/components/JProductDetail/useProductDetailDialog.ts","../src/components/JSearchInputDialog/JSearchInputDialog.vue","../src/utils/transform.ts","../src/router/helpers.ts","../src/router/guards.ts","../src/index.ts"],"sourcesContent":["<template>\r\n <button\r\n class=\"j-button\"\r\n :class=\"[\r\n `j-button--${type}`,\r\n `j-button--${size}`,\r\n {\r\n 'j-button--plain': plain,\r\n 'j-button--round': round,\r\n 'j-button--disabled': disabled,\r\n 'j-button--loading': loading,\r\n },\r\n ]\"\r\n :disabled=\"disabled || loading\"\r\n @click=\"handleClick\"\r\n >\r\n <span v-if=\"loading\" class=\"j-button__loading-icon\" />\r\n <span v-if=\"$slots.default\" class=\"j-button__text\">\r\n <slot />\r\n </span>\r\n </button>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport type { ButtonType, ButtonSize } from './types'\r\n\r\ninterface Props {\r\n type?: ButtonType\r\n size?: ButtonSize\r\n plain?: boolean\r\n round?: boolean\r\n disabled?: boolean\r\n loading?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n type: 'default',\r\n size: 'medium',\r\n plain: false,\r\n round: false,\r\n disabled: false,\r\n loading: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n click: [event: MouseEvent]\r\n}>()\r\n\r\nfunction handleClick(event: MouseEvent) {\r\n if (!props.disabled && !props.loading) {\r\n emit('click', event)\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.j-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: $spacing-xs;\r\n padding: 8px 16px;\r\n font-size: $font-size-base;\r\n font-weight: 400;\r\n line-height: 1;\r\n white-space: nowrap;\r\n cursor: pointer;\r\n border: 1px solid $color-border;\r\n border-radius: $border-radius-base;\r\n background-color: $color-white;\r\n color: $color-text-regular;\r\n transition: $transition-fast;\r\n outline: none;\r\n user-select: none;\r\n\r\n &:hover {\r\n color: $color-primary;\r\n border-color: $color-primary;\r\n background-color: color.adjust($color-primary, $lightness: 40%);\r\n }\r\n\r\n // 尺寸\r\n &--small {\r\n padding: 5px 12px;\r\n font-size: $font-size-xs;\r\n }\r\n\r\n &--medium {\r\n padding: 8px 16px;\r\n font-size: $font-size-base;\r\n }\r\n\r\n &--large {\r\n padding: 12px 20px;\r\n font-size: $font-size-md;\r\n }\r\n\r\n // 类型\r\n &--primary {\r\n background-color: $color-primary;\r\n border-color: $color-primary;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-primary, $lightness: 10%);\r\n border-color: color.adjust($color-primary, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--success {\r\n background-color: $color-success;\r\n border-color: $color-success;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-success, $lightness: 10%);\r\n border-color: color.adjust($color-success, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--danger {\r\n background-color: $color-danger;\r\n border-color: $color-danger;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-danger, $lightness: 10%);\r\n border-color: color.adjust($color-danger, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n &--warning {\r\n background-color: $color-warning;\r\n border-color: $color-warning;\r\n color: $color-white;\r\n &:hover {\r\n background-color: color.adjust($color-warning, $lightness: 10%);\r\n border-color: color.adjust($color-warning, $lightness: 10%);\r\n color: $color-white;\r\n }\r\n }\r\n\r\n // 朴素按钮\r\n &--plain {\r\n &.j-button--primary {\r\n background-color: color.adjust($color-primary, $lightness: 40%);\r\n color: $color-primary;\r\n &:hover {\r\n background-color: $color-primary;\r\n color: $color-white;\r\n }\r\n }\r\n }\r\n\r\n // 圆角\r\n &--round {\r\n border-radius: $border-radius-round;\r\n }\r\n\r\n // 禁用\r\n &--disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n }\r\n\r\n // 加载\r\n &--loading {\r\n opacity: 0.7;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n }\r\n\r\n &__loading-icon {\r\n display: inline-block;\r\n width: 14px;\r\n height: 14px;\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: j-spin 0.6s linear infinite;\r\n }\r\n\r\n @keyframes j-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"j-upload-img-container\">\r\n <!-- 多图模式 -->\r\n <template v-if=\"multiple\">\r\n <div class=\"images-wrapper\">\r\n <draggable\r\n v-model=\"imageList\"\r\n class=\"images-list\"\r\n item-key=\"uid\"\r\n :animation=\"200\"\r\n :disabled=\"disabled\"\r\n @end=\"handleDragEnd\"\r\n >\r\n <template #item=\"{ element, index }\">\r\n <div class=\"image-item\">\r\n <el-image\r\n :src=\"element.url\"\r\n :preview-src-list=\"imageList.map(img => img.url)\"\r\n :initial-index=\"index\"\r\n fit=\"cover\"\r\n class=\"image-preview\"\r\n :preview-teleported=\"true\"\r\n :hide-on-click-modal=\"true\"\r\n />\r\n <div v-if=\"!disabled\" class=\"delete-btn\" @click.stop=\"handleRemove(index)\">\r\n <el-icon class=\"icon-delete\">\r\n <Delete />\r\n </el-icon>\r\n </div>\r\n </div>\r\n </template>\r\n </draggable>\r\n\r\n <!-- 多图上传按钮 -->\r\n <el-upload\r\n v-if=\"!disabled && (!limit || imageList.length < limit)\"\r\n class=\"image-uploader\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n :disabled=\"uploading\"\r\n list-type=\"picture-card\"\r\n :accept=\"accept\"\r\n >\r\n <el-icon v-if=\"!uploading\" class=\"uploader-icon\">\r\n <Plus />\r\n </el-icon>\r\n <el-icon v-else class=\"uploader-icon is-loading\">\r\n <Loading />\r\n </el-icon>\r\n </el-upload>\r\n </div>\r\n </template>\r\n\r\n <!-- 单图模式 -->\r\n <template v-else>\r\n <!-- 已有图片:独立展示,hover 显示操作遮罩 -->\r\n <div v-if=\"imageUrl\" class=\"image-item single-image-item\">\r\n <el-image\r\n :src=\"imageUrl\"\r\n fit=\"cover\"\r\n class=\"image-preview\"\r\n />\r\n <div class=\"image-actions\">\r\n <el-icon class=\"action-icon\" @click.stop=\"handlePreviewSingle\">\r\n <ZoomIn />\r\n </el-icon>\r\n <el-icon v-if=\"!disabled\" class=\"action-icon\" @click.stop=\"handleRemoveSingle\">\r\n <Delete />\r\n </el-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- 无图片:显示上传按钮 -->\r\n <el-upload\r\n v-else\r\n class=\"image-uploader\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n :disabled=\"disabled || uploading\"\r\n :accept=\"accept\"\r\n list-type=\"picture-card\"\r\n >\r\n <el-icon class=\"uploader-icon\">\r\n <Plus v-if=\"!uploading\" />\r\n <Loading v-else class=\"is-loading\" />\r\n </el-icon>\r\n </el-upload>\r\n\r\n <!-- 大图预览 -->\r\n <el-image-viewer\r\n v-if=\"showPreview\"\r\n :url-list=\"[imageUrl]\"\r\n :teleported=\"true\"\r\n @close=\"showPreview = false\"\r\n />\r\n </template>\r\n\r\n <div v-if=\"showTipText\" class=\"upload-tip\">\r\n <span>{{ tip }}</span>\r\n <span v-if=\"multiple && limit\"> (最多 {{ limit }} 张)</span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch } from 'vue'\r\nimport { ElMessage, ElImage, ElIcon, ElUpload, ElImageViewer } from 'element-plus'\r\nimport type { UploadFile } from 'element-plus'\r\nimport { Plus, Loading, Delete, ZoomIn } from '@element-plus/icons-vue'\r\nimport draggable from 'vuedraggable'\r\nimport type { ImageItem } from './types'\r\n\r\ndefineOptions({\r\n name: 'JUploadImg'\r\n})\r\n\r\nconst props = withDefaults(defineProps<{\r\n modelValue?: string | string[]\r\n disabled?: boolean\r\n multiple?: boolean\r\n limit?: number\r\n maxSize?: number\r\n accept?: string\r\n tip?: string\r\n showTip?: boolean\r\n /** 自定义上传函数,接收 File 返回图片 URL */\r\n uploadFn?: (file: File) => Promise<string>\r\n}>(), {\r\n modelValue: '',\r\n disabled: false,\r\n multiple: false,\r\n limit: 9,\r\n maxSize: 2,\r\n accept: 'image/jpeg,image/png,image/jpg,image/gif',\r\n tip: '只能上传jpg/png/gif格式的图片,且不超过2MB',\r\n showTip: true,\r\n uploadFn: undefined\r\n})\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: string | string[]): void\r\n (e: 'success', url: string): void\r\n (e: 'error', error: any): void\r\n}>()\r\n\r\n// 单图模式\r\nconst imageUrl = ref<string>('')\r\nconst showPreview = ref(false)\r\nconst showTipText = props.showTip\r\n\r\nconst handlePreviewSingle = () => {\r\n showPreview.value = true\r\n}\r\n\r\nconst handleRemoveSingle = () => {\r\n imageUrl.value = ''\r\n emit('update:modelValue', '')\r\n ElMessage.success('删除成功')\r\n}\r\n\r\n// 多图模式\r\nconst imageList = ref<ImageItem[]>([])\r\nconst uploading = ref(false)\r\n\r\n// 初始化图片列表(多图模式)\r\nconst initImageList = (urls: string[]) => {\r\n imageList.value = urls.map((url, index) => ({\r\n uid: Date.now() + index,\r\n url\r\n }))\r\n}\r\n\r\n// 监听外部值变化\r\nwatch(() => props.modelValue, (val) => {\r\n if (props.multiple) {\r\n if (Array.isArray(val) && val.length > 0) {\r\n initImageList(val)\r\n } else {\r\n imageList.value = []\r\n }\r\n } else {\r\n if (typeof val === 'string') {\r\n imageUrl.value = val\r\n } else {\r\n imageUrl.value = ''\r\n }\r\n }\r\n}, { immediate: true })\r\n\r\n// 拖拽结束(多图模式)\r\nconst handleDragEnd = () => {\r\n emitMultipleUpdate()\r\n}\r\n\r\n// 删除图片(多图模式)\r\nconst handleRemove = (index: number) => {\r\n imageList.value.splice(index, 1)\r\n emitMultipleUpdate()\r\n ElMessage.success('删除成功')\r\n}\r\n\r\n// 文件改变时触发\r\nconst handleFileChange = async (uploadFile: UploadFile) => {\r\n const file = uploadFile.raw as File\r\n\r\n if (!file) {\r\n ElMessage.error('文件不存在,请重试')\r\n return\r\n }\r\n\r\n if (file.size > props.maxSize * 1024 * 1024) {\r\n ElMessage.error(`图片大小不能超过 ${props.maxSize}MB`)\r\n return\r\n }\r\n\r\n if (!props.uploadFn) {\r\n ElMessage.error('未配置上传函数 (uploadFn)')\r\n return\r\n }\r\n\r\n try {\r\n uploading.value = true\r\n const url = await props.uploadFn(file)\r\n\r\n if (props.multiple) {\r\n imageList.value.push({ uid: Date.now(), url })\r\n emitMultipleUpdate()\r\n } else {\r\n imageUrl.value = url\r\n emit('update:modelValue', url)\r\n }\r\n\r\n emit('success', url)\r\n ElMessage.success('上传成功')\r\n } catch (error) {\r\n console.error('上传出错:', error)\r\n ElMessage.error('上传失败,请重试')\r\n emit('error', error)\r\n } finally {\r\n uploading.value = false\r\n }\r\n}\r\n\r\n// 触发多图更新\r\nconst emitMultipleUpdate = () => {\r\n const urls = imageList.value.map(item => item.url)\r\n emit('update:modelValue', urls)\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-upload-img-container {\r\n display: inline-block;\r\n}\r\n\r\n/* 多图模式样式 */\r\n.images-wrapper {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n align-items: flex-start;\r\n}\r\n\r\n.images-list {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n}\r\n\r\n.image-item {\r\n position: relative;\r\n width: 74px;\r\n height: 74px;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 6px;\r\n overflow: hidden;\r\n cursor: move;\r\n}\r\n\r\n.image-preview {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.delete-btn {\r\n position: absolute;\r\n top: 2px;\r\n right: 2px;\r\n width: 20px;\r\n height: 20px;\r\n background-color: rgba(0, 0, 0, 0.6);\r\n border-radius: 50%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n opacity: 0;\r\n transition: opacity 0.3s;\r\n cursor: pointer;\r\n z-index: 1;\r\n}\r\n\r\n.image-item:hover .delete-btn {\r\n opacity: 1;\r\n}\r\n\r\n.delete-btn:hover {\r\n background-color: rgba(0, 0, 0, 0.8);\r\n}\r\n\r\n.icon-delete {\r\n font-size: 12px;\r\n color: #fff;\r\n}\r\n\r\n/* 单图和多图共用样式 */\r\n.image-uploader {\r\n display: inline-block;\r\n vertical-align: top;\r\n}\r\n\r\n.image-uploader :deep(.el-upload) {\r\n border: 1px dashed var(--el-border-color);\r\n border-radius: 6px;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n transition: var(--el-transition-duration-fast);\r\n width: 74px !important;\r\n height: 74px !important;\r\n}\r\n\r\n.image-uploader :deep(.el-upload:hover) {\r\n border-color: var(--el-color-primary);\r\n}\r\n\r\n.uploader-icon {\r\n font-size: 20px;\r\n color: #8c939d;\r\n width: 74px;\r\n height: 74px;\r\n text-align: center;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.single-image-item {\r\n cursor: default;\r\n}\r\n\r\n.image-actions {\r\n position: absolute;\r\n inset: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 12px;\r\n opacity: 0;\r\n transition: opacity 0.3s;\r\n}\r\n\r\n.single-image-item:hover .image-actions,\r\n.image-item:hover .image-actions {\r\n opacity: 1;\r\n}\r\n\r\n.action-icon {\r\n font-size: 18px;\r\n color: #fff;\r\n cursor: pointer;\r\n transition: transform 0.2s;\r\n}\r\n\r\n.action-icon:hover {\r\n transform: scale(1.2);\r\n}\r\n\r\n.upload-tip {\r\n margin-top: 8px;\r\n font-size: 12px;\r\n color: #909399;\r\n line-height: 1.5;\r\n}\r\n</style>\r\n","<template>\r\n <Icon v-if=\"icon\" :icon=\"icon\" :width=\"size\" :height=\"size\" v-bind=\"$attrs\" />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { Icon } from '@iconify/vue'\r\n\r\ndefineOptions({\r\n name: 'JIconRender'\r\n})\r\n\r\nwithDefaults(defineProps<{\r\n icon: string\r\n size?: string | number\r\n}>(), {\r\n size: 24,\r\n})\r\n</script>\r\n","<template>\r\n <el-card shadow=\"never\" class=\"j-search-header-card\">\r\n <el-form inline class=\"search-form\">\r\n <div\r\n ref=\"formItemsRef\"\r\n class=\"form-items-wrapper\"\r\n :class=\"{ 'is-animated': isAnimated }\"\r\n >\r\n <slot />\r\n </div>\r\n </el-form>\r\n\r\n <div class=\"action-bar\" :style=\"{ marginTop: expanded ? '0px' : '10px' }\">\r\n <div class=\"action-left\">\r\n <el-button v-if=\"showAdd\" type=\"primary\" :icon=\"Plus\" @click=\"emit('add')\">\r\n {{ addText }}\r\n </el-button>\r\n <el-button\r\n v-if=\"showBatchDelete\"\r\n type=\"danger\"\r\n :icon=\"Delete\"\r\n :disabled=\"selectedCount === 0\"\r\n @click=\"emit('batchDelete')\"\r\n >\r\n 批量删除{{ selectedCount ? `(${selectedCount})` : '' }}\r\n </el-button>\r\n <el-button v-if=\"showSearch\" type=\"primary\" :icon=\"Search\" @click=\"emit('search')\">搜索</el-button>\r\n <el-button v-if=\"showReset\" :icon=\"Refresh\" @click=\"emit('reset')\">重置</el-button>\r\n <slot name=\"actions\" />\r\n </div>\r\n <el-button\r\n v-if=\"shouldCollapse\"\r\n link\r\n type=\"primary\"\r\n @click=\"toggleExpand\"\r\n >\r\n {{ expanded ? '收起' : '展开' }}\r\n <el-icon class=\"toggle-icon\" :class=\"{ 'is-expanded': expanded }\">\r\n <ArrowDown />\r\n </el-icon>\r\n </el-button>\r\n </div>\r\n </el-card>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted, onBeforeUnmount } from 'vue'\r\nimport { ElCard, ElForm, ElButton, ElIcon } from 'element-plus'\r\nimport { Search, Refresh, Plus, Delete, ArrowDown } from '@element-plus/icons-vue'\r\n\r\ndefineOptions({\r\n name: 'JSearchHeader'\r\n})\r\n\r\nconst props = withDefaults(defineProps<{\r\n selectedCount?: number\r\n addText?: string\r\n defaultVisible?: number\r\n showAdd?: boolean\r\n showBatchDelete?: boolean\r\n showSearch?: boolean\r\n showReset?: boolean\r\n}>(), {\r\n selectedCount: 0,\r\n addText: '新增',\r\n defaultVisible: 5,\r\n showAdd: true,\r\n showBatchDelete: true,\r\n showSearch: true,\r\n showReset: true\r\n})\r\n\r\nconst emit = defineEmits<{\r\n search: []\r\n reset: []\r\n add: []\r\n batchDelete: []\r\n}>()\r\n\r\nconst formItemsRef = ref<HTMLElement>()\r\nconst expanded = ref(false)\r\nconst isAnimated = ref(false)\r\nconst itemCount = ref(0)\r\nconst collapsedHeight = ref(0)\r\n\r\nconst shouldCollapse = computed(() => itemCount.value > props.defaultVisible)\r\n\r\nconst measureItems = () => {\r\n if (!formItemsRef.value) return\r\n const items = Array.from(formItemsRef.value.children) as HTMLElement[]\r\n itemCount.value = items.length\r\n\r\n const lastVisibleItem = items[props.defaultVisible - 1]\r\n if (lastVisibleItem && formItemsRef.value) {\r\n const wrapperRect = formItemsRef.value.getBoundingClientRect()\r\n const lastVisibleRect = lastVisibleItem.getBoundingClientRect()\r\n collapsedHeight.value = lastVisibleRect.bottom - wrapperRect.top\r\n }\r\n}\r\n\r\nconst toggleExpand = () => {\r\n const el = formItemsRef.value\r\n if (!el) return\r\n\r\n if (!expanded.value) {\r\n expanded.value = true\r\n el.style.maxHeight = el.scrollHeight + 'px'\r\n const onEnd = () => {\r\n el.style.maxHeight = 'none'\r\n el.removeEventListener('transitionend', onEnd)\r\n }\r\n el.addEventListener('transitionend', onEnd)\r\n } else {\r\n measureItems()\r\n expanded.value = false\r\n el.style.maxHeight = el.scrollHeight + 'px'\r\n el.offsetHeight\r\n el.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n}\r\n\r\nlet observer: MutationObserver | null = null\r\n\r\nonMounted(() => {\r\n measureItems()\r\n if (shouldCollapse.value && formItemsRef.value) {\r\n formItemsRef.value.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n isAnimated.value = true\r\n })\r\n })\r\n if (formItemsRef.value) {\r\n observer = new MutationObserver(() => {\r\n measureItems()\r\n if (shouldCollapse.value && !expanded.value && formItemsRef.value) {\r\n formItemsRef.value.style.maxHeight = collapsedHeight.value + 'px'\r\n }\r\n })\r\n observer.observe(formItemsRef.value, { childList: true })\r\n }\r\n})\r\n\r\nonBeforeUnmount(() => {\r\n observer?.disconnect()\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.j-search-header-card :deep(.el-card__body) {\r\n padding: 16px 20px 12px;\r\n}\r\n\r\n.search-form {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: 0;\r\n}\r\n\r\n.form-items-wrapper {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n overflow: hidden;\r\n}\r\n\r\n.form-items-wrapper.is-animated {\r\n transition: max-height 0.3s ease-in-out;\r\n}\r\n\r\n.form-items-wrapper :deep(.el-form-item) {\r\n margin-bottom: 10px;\r\n margin-right: 16px;\r\n}\r\n\r\n.action-bar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding-top: 10px;\r\n border-top: 1px solid #ebeef5;\r\n}\r\n\r\n.action-left {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.toggle-icon {\r\n margin-left: 2px;\r\n transition: transform 0.25s;\r\n}\r\n\r\n.toggle-icon.is-expanded {\r\n transform: rotate(180deg);\r\n}\r\n</style>\r\n","<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n :title=\"props.title\"\r\n width=\"900px\"\r\n :close-on-click-modal=\"false\"\r\n @open=\"handleOpen\"\r\n @close=\"handleClose\"\r\n >\r\n <!-- 上传区域 -->\r\n <el-card shadow=\"never\" class=\"j-import-upload-card\">\r\n <div class=\"j-import-upload-card-title\">导入 EXCEL</div>\r\n <el-divider style=\"margin: 10px 0\" />\r\n <div class=\"j-import-upload-row\">\r\n <el-upload\r\n accept=\".xlsx,.xls\"\r\n :auto-upload=\"false\"\r\n :show-file-list=\"false\"\r\n :on-change=\"handleFileChange\"\r\n >\r\n <el-button size=\"small\">点击上传</el-button>\r\n </el-upload>\r\n <el-link\r\n v-if=\"dataColumns.length\"\r\n type=\"primary\"\r\n class=\"j-import-no-wrap\"\r\n @click=\"handleDownloadTemplate\"\r\n >\r\n 下载导入模板.xlsx\r\n </el-link>\r\n </div>\r\n </el-card>\r\n\r\n <!-- 统计信息 + 确认导入 -->\r\n <el-row class=\"j-import-stats-row\" :gutter=\"20\" align=\"middle\">\r\n <el-col :span=\"18\">\r\n <el-row class=\"j-import-stats-cols\">\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.total }}</div>\r\n <div class=\"j-import-stat-label\">导入数量</div>\r\n </el-col>\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.fail }}</div>\r\n <div class=\"j-import-stat-label\">失败数量</div>\r\n </el-col>\r\n <el-col :span=\"4\" class=\"j-import-stat-item\">\r\n <div class=\"j-import-stat-num\">{{ stats.success }}</div>\r\n <div class=\"j-import-stat-label\">成功数量</div>\r\n </el-col>\r\n </el-row>\r\n </el-col>\r\n <el-col :span=\"6\" class=\"j-import-confirm-col\">\r\n <el-button\r\n type=\"primary\"\r\n size=\"small\"\r\n :loading=\"submitting\"\r\n :disabled=\"!renderData.length\"\r\n @click=\"handleConfirm\"\r\n >\r\n 确认导入\r\n </el-button>\r\n </el-col>\r\n </el-row>\r\n\r\n <!-- 数据表格 -->\r\n <el-table :data=\"renderData\" border size=\"small\" max-height=\"360\" class=\"j-import-data-table\">\r\n <el-table-column\r\n v-for=\"col in dataColumns\"\r\n :key=\"col.prop\"\r\n :prop=\"col.prop\"\r\n :label=\"col.label\"\r\n :min-width=\"120\"\r\n show-overflow-tooltip\r\n />\r\n <el-table-column label=\"状态\" width=\"110\" align=\"center\" fixed=\"right\">\r\n <template #default=\"{ row }\">\r\n <span v-if=\"row._status === -1\" class=\"j-import-status-fail\">\r\n {{ row._error || '创建失败' }}\r\n </span>\r\n <span v-else>{{ statusMap[row._status] }}</span>\r\n </template>\r\n </el-table-column>\r\n <el-table-column label=\"操作\" width=\"80\" align=\"center\" fixed=\"right\">\r\n <template #default=\"{ $index, row }\">\r\n <el-button\r\n v-if=\"row._status === 0\"\r\n size=\"small\"\r\n @click=\"handleDel($index)\"\r\n >\r\n 删除\r\n </el-button>\r\n </template>\r\n </el-table-column>\r\n </el-table>\r\n\r\n <template #footer>\r\n <el-button @click=\"handleClose\">关闭</el-button>\r\n </template>\r\n </el-dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from 'vue'\r\nimport { ElMessage, ElDialog, ElCard, ElDivider, ElUpload, ElButton, ElLink, ElRow, ElCol, ElTable, ElTableColumn } from 'element-plus'\r\nimport type { UploadFile } from 'element-plus'\r\nimport * as XLSX from 'xlsx'\r\nimport type { JImportExcelProps } from './types'\r\n\r\ndefineOptions({ name: 'JImportExcel' })\r\n\r\nconst props = withDefaults(defineProps<JImportExcelProps>(), {\r\n excludeFields: () => ['id', 'ctime', 'mtime'],\r\n title: 'Excel 批量导入',\r\n})\r\n\r\nconst emit = defineEmits<{\r\n success: []\r\n}>()\r\n\r\nconst visible = defineModel<boolean>({ default: false })\r\nconst submitting = ref(false)\r\nconst fieldMap = ref<Record<string, string>>({})\r\nconst renderData = ref<Record<string, any>[]>([])\r\nconst stats = ref({ total: 0, success: 0, fail: 0 })\r\n\r\nconst statusMap: Record<number, string> = {\r\n 0: '待创建',\r\n 1: '创建成功',\r\n 2: '创建中',\r\n [-1]: '创建失败',\r\n}\r\n\r\n/** 过滤后的表头列 */\r\nconst dataColumns = computed(() => {\r\n return Object.entries(fieldMap.value)\r\n .filter(([key]) => !props.excludeFields.includes(key))\r\n .map(([key, label]) => ({ id: key, label, prop: key }))\r\n})\r\n\r\n/** 弹窗打开时获取字段列表 */\r\nconst handleOpen = async () => {\r\n try {\r\n const res = await props.getFieldListApi()\r\n fieldMap.value = res.data.tableFieldsInfo ?? {}\r\n } catch {\r\n ElMessage.error('获取字段列表失败')\r\n }\r\n}\r\n\r\n/** 文件上传解析 */\r\nconst handleFileChange = (uploadFile: UploadFile) => {\r\n const raw = uploadFile.raw\r\n if (!raw) return\r\n\r\n const validTypes = [\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n 'application/vnd.ms-excel',\r\n ]\r\n if (!validTypes.includes(raw.type) && !raw.name.match(/\\.xlsx?$/i)) {\r\n ElMessage.warning('请上传 .xlsx 或 .xls 格式文件')\r\n return\r\n }\r\n\r\n const reader = new FileReader()\r\n reader.onload = (e) => {\r\n try {\r\n const workbook = XLSX.read(e.target!.result, { type: 'binary' })\r\n const wsName = workbook.SheetNames[0] as string\r\n const ws = workbook.Sheets[wsName]!\r\n const rows = XLSX.utils.sheet_to_json(ws, {\r\n header: 1,\r\n defval: '',\r\n }) as any[][]\r\n\r\n const dataRows = rows.slice(1).filter((row) => row.some((cell) => cell !== ''))\r\n\r\n if (!dataRows.length) {\r\n ElMessage.warning('文件内容为空')\r\n return\r\n }\r\n\r\n // 按后端字段顺序一一映射,空单元格由 defval 补 '',避免后续列顶上来\r\n const list: Record<string, any>[] = dataRows.map((row) => {\r\n const item: Record<string, any> = { _status: 0, _error: '' }\r\n dataColumns.value.forEach((col, index) => {\r\n item[col.prop] = row[index] !== undefined ? row[index] : ''\r\n })\r\n return item\r\n })\r\n\r\n renderData.value = list\r\n stats.value = { total: list.length, success: 0, fail: 0 }\r\n } catch {\r\n ElMessage.error('解析文件失败,请检查文件格式')\r\n }\r\n }\r\n reader.readAsBinaryString(raw)\r\n}\r\n\r\n/** 删除行 */\r\nconst handleDel = (idx: number) => {\r\n renderData.value.splice(idx, 1)\r\n stats.value.total = renderData.value.length\r\n}\r\n\r\n/** 确认导入 */\r\nconst handleConfirm = async () => {\r\n const data = renderData.value\r\n .filter((row) => row._status === 0)\r\n .map(({ _status, _error, ...rest }) => rest)\r\n\r\n if (!data.length) {\r\n ElMessage.warning('没有可导入的数据')\r\n return\r\n }\r\n\r\n submitting.value = true\r\n try {\r\n const res = await props.importApi(data)\r\n if (res.code === 1) {\r\n // 全部成功\r\n renderData.value.forEach((row) => {\r\n if (row._status === 0) row._status = 1\r\n })\r\n stats.value.success = renderData.value.filter((r) => r._status === 1).length\r\n ElMessage.success('导入成功')\r\n emit('success')\r\n } else {\r\n ElMessage.error(res.msg || '导入失败')\r\n }\r\n } catch {\r\n ElMessage.error('导入失败,请重试')\r\n } finally {\r\n submitting.value = false\r\n }\r\n}\r\n\r\n/** 下载导入模板 */\r\nconst handleDownloadTemplate = () => {\r\n try {\r\n const wb = XLSX.utils.book_new()\r\n const headers = dataColumns.value.map((col) => col.label)\r\n const tr: Record<string, string> = {}\r\n headers.forEach((h) => (tr[h] = ''))\r\n const ws = XLSX.utils.json_to_sheet([tr])\r\n XLSX.utils.book_append_sheet(wb, ws, '模板')\r\n XLSX.writeFile(wb, '导入模板.xlsx')\r\n } catch {\r\n ElMessage.error('模板下载失败')\r\n }\r\n}\r\n\r\nconst handleClose = () => {\r\n if (!submitting.value) {\r\n visible.value = false\r\n renderData.value = []\r\n stats.value = { total: 0, success: 0, fail: 0 }\r\n }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-import-upload-card {\r\n margin-bottom: 16px;\r\n}\r\n.j-import-upload-card-title {\r\n font-size: 14px;\r\n color: #606266;\r\n}\r\n.j-import-upload-row {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n.j-import-no-wrap {\r\n white-space: nowrap;\r\n}\r\n.j-import-stats-row {\r\n margin: 12px 0;\r\n}\r\n.j-import-stats-cols {\r\n text-align: center;\r\n line-height: 1.5;\r\n}\r\n.j-import-stat-item {\r\n padding: 0 8px;\r\n}\r\n.j-import-stat-num {\r\n font-size: 20px;\r\n}\r\n.j-import-stat-label {\r\n font-size: 12px;\r\n color: #909399;\r\n}\r\n.j-import-confirm-col {\r\n text-align: right;\r\n padding-top: 10px;\r\n}\r\n.j-import-data-table {\r\n margin-top: 10px;\r\n}\r\n.j-import-status-fail {\r\n color: #f56c6c;\r\n font-size: 12px;\r\n}\r\n</style>\r\n","<template>\r\n <!-- 有子菜单:渲染 el-sub-menu -->\r\n <el-sub-menu\r\n v-if=\"menuItem.children && menuItem.children.length > 0\"\r\n :index=\"menuItem.path\"\r\n :class=\"[`j-sidebar__depth-${depth}`]\"\r\n >\r\n <template #title>\r\n <JIconRender v-if=\"menuItem.icon && depth === 0\" :icon=\"menuItem.icon\" />\r\n <span class=\"j-sidebar__menu-item-title\">{{ menuItem.title || menuItem.name }}</span>\r\n </template>\r\n <!-- 递归渲染子菜单 -->\r\n <JSideMenuItem\r\n v-for=\"child in menuItem.children\"\r\n :key=\"child.path\"\r\n :menu-item=\"child\"\r\n :is-collapse=\"isCollapse\"\r\n :depth=\"depth + 1\"\r\n @menu-click=\"(item) => emit('menu-click', item)\"\r\n />\r\n </el-sub-menu>\r\n\r\n <!-- 无子菜单:渲染 el-menu-item -->\r\n <el-menu-item\r\n v-else\r\n :index=\"menuItem.path\"\r\n :class=\"[`j-sidebar__depth-${depth}`]\"\r\n @click=\"handleClick\"\r\n >\r\n <JIconRender v-if=\"menuItem.icon && depth === 0\" :icon=\"menuItem.icon\" />\r\n <template #title>\r\n <span>{{ menuItem.title || menuItem.name }}</span>\r\n </template>\r\n </el-menu-item>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport type { SidebarMenuItem } from './types'\r\nimport { ElSubMenu, ElMenuItem } from 'element-plus'\r\nimport { JIconRender } from '../JIconRender'\r\n\r\ndefineOptions({\r\n name: 'JSideMenuItem'\r\n})\r\n\r\ninterface Props {\r\n menuItem: SidebarMenuItem\r\n isCollapse?: boolean\r\n depth?: number\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), { depth: 0 })\r\n\r\nconst emit = defineEmits<{\r\n 'menu-click': [item: SidebarMenuItem]\r\n}>()\r\n\r\nconst handleClick = () => {\r\n emit('menu-click', props.menuItem)\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.j-sidebar__menu-item-title {\r\n padding: 0 10px;\r\n}\r\n\r\n/* 二级菜单:灰色标题,作为分类标签 */\r\n.j-sidebar__depth-1 > :deep(.el-sub-menu__title) {\r\n color: #909399;\r\n font-size: 13px;\r\n}\r\n\r\n/* 二级叶子菜单(无子项)也用灰色 */\r\n:deep(.j-sidebar__depth-1.el-menu-item) {\r\n color: #909399;\r\n font-size: 13px;\r\n}\r\n\r\n/* 三级菜单:文字稍大 */\r\n:deep(.j-sidebar__depth-2.el-menu-item) {\r\n font-size: 15px;\r\n}\r\n</style>\r\n","<template>\r\n <div\r\n :class=\"['j-sidebar', innerCollapsed ? 'j-sidebar--collapsed' : 'j-sidebar--expanded']\"\r\n :style=\"{ width: innerCollapsed ? `${collapsedWidth}px` : `${expandedWidth}px` }\"\r\n >\r\n <!-- Logo 区域 -->\r\n <div class=\"j-sidebar__logo\">\r\n <slot name=\"logo\" :collapsed=\"innerCollapsed\">\r\n <h2 class=\"j-sidebar__title\">\r\n {{ innerCollapsed ? (collapsedTitle || title?.charAt(0) || '') : title }}\r\n </h2>\r\n </slot>\r\n </div>\r\n\r\n <!-- 菜单区域 -->\r\n <div class=\"j-sidebar__menu-wrapper\">\r\n <el-menu\r\n :default-active=\"activeMenu\"\r\n class=\"j-sidebar__menu\"\r\n :router=\"router\"\r\n :collapse=\"innerCollapsed\"\r\n :collapse-transition=\"false\"\r\n >\r\n <JSideMenuItem\r\n v-for=\"route in menus\"\r\n :key=\"route.path\"\r\n :menu-item=\"route\"\r\n :is-collapse=\"innerCollapsed\"\r\n @menu-click=\"(item) => emit('menu-click', item)\"\r\n />\r\n </el-menu>\r\n </div>\r\n\r\n <!-- 底部折叠按钮 -->\r\n <div class=\"j-sidebar__footer\">\r\n <slot name=\"footer\" :collapsed=\"innerCollapsed\" :toggle=\"toggleCollapse\">\r\n <button\r\n class=\"j-sidebar__collapse-btn\"\r\n @click=\"toggleCollapse\"\r\n >\r\n <JIconRender :icon=\"innerCollapsed ? 'mdi:chevron-right' : 'mdi:chevron-left'\" />\r\n </button>\r\n </slot>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch } from 'vue'\r\nimport { ElMenu } from 'element-plus'\r\nimport type { SidebarMenuItem } from './types'\r\nimport JSideMenuItem from './JSideMenuItem.vue'\r\nimport { JIconRender } from '../JIconRender'\r\n\r\ndefineOptions({\r\n name: 'JSidebar'\r\n})\r\n\r\ninterface Props {\r\n menus: SidebarMenuItem[]\r\n activeMenu?: string\r\n title?: string\r\n collapsedTitle?: string\r\n collapsed?: boolean\r\n collapsedWidth?: number\r\n expandedWidth?: number\r\n router?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n activeMenu: '',\r\n title: '',\r\n collapsedTitle: '',\r\n collapsed: false,\r\n collapsedWidth: 80,\r\n expandedWidth: 200,\r\n router: true,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:collapsed': [value: boolean]\r\n 'menu-click': [item: SidebarMenuItem]\r\n}>()\r\n\r\nconst innerCollapsed = ref(props.collapsed)\r\n\r\nwatch(() => props.collapsed, (val) => {\r\n innerCollapsed.value = val\r\n})\r\n\r\nconst toggleCollapse = () => {\r\n innerCollapsed.value = !innerCollapsed.value\r\n emit('update:collapsed', innerCollapsed.value)\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.j-sidebar {\r\n position: relative;\r\n background-color: $color-white;\r\n box-shadow: 2px 0 6px rgba(0, 21, 41, 0.08);\r\n overflow-x: hidden;\r\n transition: width 0.3s ease-in-out;\r\n flex-shrink: 0;\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n}\r\n\r\n.j-sidebar__logo {\r\n padding: 0 $spacing-md;\r\n display: flex;\r\n align-items: center;\r\n height: 50px;\r\n flex-shrink: 0;\r\n}\r\n\r\n\r\n.j-sidebar__title {\r\n margin: 0;\r\n font-size: $font-size-lg;\r\n font-weight: bold;\r\n color: $color-primary;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n}\r\n\r\n.j-sidebar__menu-wrapper {\r\n flex: 1;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n}\r\n\r\n.j-sidebar__menu {\r\n border: none;\r\n width: 100%;\r\n}\r\n\r\n.j-sidebar__footer {\r\n flex-shrink: 0;\r\n padding: $spacing-sm;\r\n display: flex;\r\n}\r\n\r\n// 折叠状态:覆盖 el-menu 样式,图标+文字上下排列\r\n.j-sidebar--collapsed {\r\n :deep(.el-menu--collapse) {\r\n width: 100%;\r\n\r\n .el-menu-item,\r\n .el-sub-menu__title {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n height: auto;\r\n line-height: normal;\r\n padding: $spacing-sm 0 !important;\r\n\r\n .el-icon,\r\n .iconify {\r\n margin: 0;\r\n }\r\n\r\n span {\r\n display: block !important;\r\n visibility: visible !important;\r\n overflow: visible !important;\r\n width: auto !important;\r\n height: auto !important;\r\n font-size: $font-size-xs;\r\n margin-top: $spacing-xs;\r\n }\r\n }\r\n\r\n // 隐藏子菜单展开箭头\r\n .el-sub-menu__icon-arrow {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n.j-sidebar__collapse-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: $spacing-sm;\r\n border: none;\r\n border-radius: $border-radius-base;\r\n background-color: transparent;\r\n color: $color-text-secondary;\r\n cursor: pointer;\r\n transition: $transition-fast;\r\n\r\n &:hover {\r\n background-color: $color-bg-base;\r\n color: $color-primary;\r\n }\r\n\r\n}\r\n</style>\r\n","<template>\n <div class=\"j-admin-layout\" :style=\"layoutStyle\">\n <JSidebar\n v-if=\"sideMenus.length > 0\"\n v-model:collapsed=\"innerCollapsed\"\n :menus=\"sideMenus\"\n :active-menu=\"activeMenu\"\n :title=\"title\"\n :collapsed-title=\"collapsedTitle\"\n :collapsed-width=\"sidebarCollapsedWidth\"\n :expanded-width=\"sidebarExpandedWidth\"\n @menu-click=\"handleSideMenuClick\"\n >\n <template v-if=\"$slots.sidebarFooter\" #footer=\"{ collapsed: sidebarCollapsed, toggle }\">\n <slot name=\"sidebarFooter\" :collapsed=\"sidebarCollapsed\" :toggle=\"toggle\" />\n </template>\n </JSidebar>\n\n <div class=\"j-admin-layout__right-panel\">\n <div class=\"j-admin-layout__header\">\n <div class=\"j-admin-layout__header-left\">\n <div v-if=\"sideMenus.length === 0\" class=\"j-admin-layout__logo\">\n <slot name=\"logo\">\n <h2>{{ logoTitle || title }}</h2>\n </slot>\n </div>\n\n <el-menu\n mode=\"horizontal\"\n :default-active=\"activeTopMenu\"\n class=\"j-admin-layout__top-menu\"\n @select=\"handleTopMenuSelect\"\n >\n <el-menu-item\n v-for=\"menu in topMenus\"\n :key=\"menu.path\"\n :index=\"menu.path\"\n >\n <JIconRender v-if=\"menu.icon\" :icon=\"menu.icon\" class=\"j-admin-layout__top-menu-icon\" />\n <span>{{ menu.title || menu.name }}</span>\n </el-menu-item>\n </el-menu>\n </div>\n\n <div class=\"j-admin-layout__header-right\">\n <slot name=\"headerRight\" :username=\"username\">\n <el-dropdown v-if=\"showProfile || showLogout\">\n <span class=\"j-admin-layout__user\">\n {{ username }}\n <el-icon>\n <ArrowDown />\n </el-icon>\n </span>\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item v-if=\"showProfile\" @click=\"emit('profile')\">\n {{ profileText }}\n </el-dropdown-item>\n <el-dropdown-item v-if=\"showLogout\" @click=\"emit('logout')\">\n {{ logoutText }}\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </slot>\n </div>\n </div>\n\n <div class=\"j-admin-layout__content-container\">\n <slot name=\"tabs\" />\n <div\n :class=\"[\n 'j-admin-layout__content',\n { 'j-admin-layout__content--scrollbar-hidden': hideContentScrollbar }\n ]\"\n >\n <slot />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ElMenu, ElMenuItem, ElDropdown, ElDropdownMenu, ElDropdownItem, ElIcon } from 'element-plus'\nimport { ArrowDown } from '@element-plus/icons-vue'\nimport { JSidebar, type SidebarMenuItem } from '../JSidebar'\nimport { JIconRender } from '../JIconRender'\nimport type { AdminLayoutMenuItem } from './types'\n\ndefineOptions({\n name: 'JAdminLayout'\n})\n\ninterface Props {\n topMenus: AdminLayoutMenuItem[]\n sideMenus: AdminLayoutMenuItem[]\n activeTopMenu?: string\n activeMenu?: string\n title?: string\n logoTitle?: string\n collapsedTitle?: string\n collapsed?: boolean\n username?: string\n profileText?: string\n logoutText?: string\n sidebarCollapsedWidth?: number\n sidebarExpandedWidth?: number\n headerHeight?: string\n contentPadding?: string\n contentBackground?: string\n headerBackground?: string\n showProfile?: boolean\n showLogout?: boolean\n hideContentScrollbar?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n activeTopMenu: '',\n activeMenu: '',\n title: '',\n logoTitle: '',\n collapsedTitle: '',\n collapsed: false,\n username: '',\n profileText: '个人资料',\n logoutText: '退出登录',\n sidebarCollapsedWidth: 80,\n sidebarExpandedWidth: 200,\n headerHeight: '50px',\n contentPadding: '10px',\n contentBackground: '#f0f2f5',\n headerBackground: '#ffffff',\n showProfile: true,\n showLogout: true,\n hideContentScrollbar: false,\n})\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean]\n 'top-menu-select': [path: string]\n 'side-menu-click': [item: SidebarMenuItem]\n profile: []\n logout: []\n}>()\n\nconst innerCollapsed = computed({\n get: () => props.collapsed,\n set: value => emit('update:collapsed', value),\n})\n\nconst layoutStyle = computed(() => ({\n '--j-admin-layout-header-height': props.headerHeight,\n '--j-admin-layout-content-padding': props.contentPadding,\n '--j-admin-layout-content-bg': props.contentBackground,\n '--j-admin-layout-header-bg': props.headerBackground,\n}))\n\nconst handleTopMenuSelect = (path: string) => {\n emit('top-menu-select', path)\n}\n\nconst handleSideMenuClick = (item: SidebarMenuItem) => {\n emit('side-menu-click', item)\n}\n</script>\n\n<style scoped lang=\"scss\">\n.j-admin-layout {\n width: 100vw;\n height: 100vh;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n}\n\n.j-admin-layout__right-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--j-admin-layout-content-bg);\n}\n\n.j-admin-layout__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: var(--j-admin-layout-header-bg);\n box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);\n height: var(--j-admin-layout-header-height);\n flex-shrink: 0;\n z-index: 100;\n}\n\n.j-admin-layout__header-left {\n display: flex;\n align-items: center;\n flex: 1;\n height: 100%;\n min-width: 0;\n}\n\n.j-admin-layout__logo {\n padding: 0 $spacing-md;\n display: flex;\n align-items: center;\n height: var(--j-admin-layout-header-height);\n flex-shrink: 0;\n}\n\n.j-admin-layout__logo h2 {\n margin: 0;\n font-size: $font-size-lg;\n font-weight: bold;\n color: $color-primary;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.j-admin-layout__top-menu {\n flex: 1;\n height: var(--j-admin-layout-header-height);\n border-bottom: none;\n min-width: 0;\n}\n\n.j-admin-layout__top-menu-icon {\n margin-right: $spacing-xs;\n}\n\n.j-admin-layout__header-right {\n display: flex;\n align-items: center;\n gap: $spacing-md;\n padding-right: $spacing-md;\n flex-shrink: 0;\n}\n\n.j-admin-layout__user {\n cursor: pointer;\n display: flex;\n align-items: center;\n color: $color-text-regular;\n}\n\n.j-admin-layout__user:hover {\n color: $color-primary;\n}\n\n.j-admin-layout__content-container {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n background-color: var(--j-admin-layout-content-bg);\n}\n\n.j-admin-layout__content {\n padding: var(--j-admin-layout-content-padding);\n flex: 1;\n overflow: auto;\n}\n\n.j-admin-layout__content--scrollbar-hidden {\n scrollbar-width: none;\n -ms-overflow-style: none;\n\n &::-webkit-scrollbar {\n display: none;\n }\n}\n</style>\n","<template>\n <el-dialog\n :model-value=\"visible\"\n title=\"查看产品\"\n width=\"1200px\"\n top=\"4vh\"\n :close-on-click-modal=\"false\"\n @update:model-value=\"(v: boolean) => emit('update:visible', v)\"\n >\n <div v-loading=\"loading\" class=\"pdd-body\">\n <template v-if=\"detail\">\n <!-- ===== 基本信息 ===== -->\n <div class=\"pdd-title\">基本信息</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item :label=\"isSpu ? '中文款式' : '中文品名'\">{{ fmt(nameCn) }}</el-descriptions-item>\n <el-descriptions-item :label=\"isSpu ? '英文款式' : '英文品名'\">{{ fmt(nameEn) }}</el-descriptions-item>\n <el-descriptions-item :label=\"isSpu ? 'SPU' : 'SKU'\">{{ fmt(mainCode) }}</el-descriptions-item>\n <el-descriptions-item label=\"产品类型\">{{ productTypeLabel }}</el-descriptions-item>\n <el-descriptions-item label=\"采购公司\">{{ fmt(peNames) }}</el-descriptions-item>\n <el-descriptions-item label=\"状态\">{{ fmt(statusName) }}</el-descriptions-item>\n <el-descriptions-item label=\"品类\">{{ fmt(basic.category_path_name || basic.category_name) }}</el-descriptions-item>\n <el-descriptions-item label=\"品牌\">{{ fmt(brandName) }}</el-descriptions-item>\n <el-descriptions-item label=\"单位\">{{ fmt(unitName) }}</el-descriptions-item>\n <el-descriptions-item label=\"产品标签\">\n <template v-if=\"tagList.length\">\n <el-tag\n v-for=\"t in tagList\"\n :key=\"t.code\"\n size=\"small\"\n class=\"pdd-tag\"\n :style=\"t.color ? { backgroundColor: t.color, borderColor: t.color, color: '#fff' } : {}\"\n >{{ t.name }}</el-tag>\n </template>\n <template v-else>—</template>\n </el-descriptions-item>\n <el-descriptions-item label=\"材质\">{{ fmt(basic.material) }}</el-descriptions-item>\n <el-descriptions-item label=\"型号\">{{ fmt(basic.product_model) }}</el-descriptions-item>\n <el-descriptions-item label=\"开发员\">{{ fmt(basic.develop_leader_name || basic.develop_user) }}</el-descriptions-item>\n <el-descriptions-item label=\"采购员\">{{ fmt(basic.purchase_leader_name || basic.purchase_user) }}</el-descriptions-item>\n <el-descriptions-item label=\"产品运营\">{{ fmt(basic.sales_leader_name || basic.sales_user) }}</el-descriptions-item>\n <el-descriptions-item v-if=\"!isSpu\" label=\"关联SPU\">{{ fmt(basic.spu_code) }}</el-descriptions-item>\n <el-descriptions-item v-if=\"!isSpu\" label=\"产品属性\" :span=\"2\">{{ fmt(skuAttrText) }}</el-descriptions-item>\n <el-descriptions-item label=\"附件\" :span=\"3\">\n <template v-if=\"basicAttachments.length\">\n <a\n v-for=\"(f, i) in basicAttachments\"\n :key=\"i\"\n :href=\"f.url\"\n target=\"_blank\"\n class=\"pdd-file\"\n >{{ f.name }}</a>\n </template>\n <template v-else>—</template>\n </el-descriptions-item>\n <el-descriptions-item label=\"详细描述\" :span=\"3\">\n <div v-if=\"hasDesc\" class=\"pdd-rich\" v-html=\"basic.product_desc\"></div>\n <template v-else>—</template>\n </el-descriptions-item>\n </el-descriptions>\n\n <!-- ===== 产品组成(组合产品 20) ===== -->\n <template v-if=\"productType === '20'\">\n <div class=\"pdd-title\">产品组成</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item label=\"单位加工费\">\n {{ bindSku.unit_process_cost != null && bindSku.unit_process_cost !== '' ? `${bindSku.unit_process_cost} ${bindSku.unit_process_currency_code || ''}` : '—' }}\n </el-descriptions-item>\n <el-descriptions-item label=\"加工备注\" :span=\"2\">{{ fmt(bindSku.unit_process_remark) }}</el-descriptions-item>\n </el-descriptions>\n <el-table :data=\"bindSkuList\" border size=\"small\" class=\"pdd-table\">\n <el-table-column label=\"图片\" width=\"70\" align=\"center\">\n <template #default=\"{ row }\">\n <el-image\n v-if=\"row.image || row.product_image\"\n :src=\"row.image || row.product_image\"\n :preview-src-list=\"[row.image || row.product_image]\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-thumb\"\n />\n <span v-else>—</span>\n </template>\n </el-table-column>\n <el-table-column label=\"品名\" prop=\"product_name\" min-width=\"140\" show-overflow-tooltip />\n <el-table-column label=\"SKU\" prop=\"sku_code\" min-width=\"120\" show-overflow-tooltip />\n <el-table-column label=\"单位\" min-width=\"70\">\n <template #default=\"{ row }\">{{ fmt(row.unit || row.unit_name) }}</template>\n </el-table-column>\n <el-table-column label=\"数量\" min-width=\"70\">\n <template #default=\"{ row }\">{{ fmt(row.quantity ?? row.sku_quantity) }}</template>\n </el-table-column>\n <el-table-column label=\"品类\" prop=\"category_path_name\" min-width=\"120\" show-overflow-tooltip />\n <el-table-column label=\"型号\" min-width=\"90\">\n <template #default=\"{ row }\">{{ fmt(row.model_no || row.product_model) }}</template>\n </el-table-column>\n <el-table-column label=\"材质\" prop=\"material\" min-width=\"90\" show-overflow-tooltip />\n <el-table-column label=\"单品尺寸\" min-width=\"140\">\n <template #default=\"{ row }\">{{ dimText(row.spec_info?.length, row.spec_info?.width, row.spec_info?.height, row.spec_info?.height_unit || 'cm') }}</template>\n </el-table-column>\n <el-table-column label=\"净重\" min-width=\"80\">\n <template #default=\"{ row }\">{{ weightText(row.spec_info?.net_weight ?? row.net_weight, row.spec_info?.product_unit) }}</template>\n </el-table-column>\n <el-table-column label=\"毛重\" min-width=\"80\">\n <template #default=\"{ row }\">{{ weightText(row.spec_info?.gross_weight ?? row.gross_weight, row.spec_info?.product_unit) }}</template>\n </el-table-column>\n </el-table>\n </template>\n\n <!-- ===== 款式属性(多属性产品 30) ===== -->\n <template v-if=\"isSpu\">\n <div class=\"pdd-title\">款式属性</div>\n <el-table :data=\"styleAttrs\" border size=\"small\" class=\"pdd-table\">\n <el-table-column label=\"属性\" prop=\"attr_name\" width=\"160\" />\n <el-table-column label=\"属性值\">\n <template #default=\"{ row }\">\n <el-tag v-for=\"c in row.childs || []\" :key=\"c.attr_value_code\" size=\"small\" class=\"pdd-tag\">\n {{ c.attr_value_name }}\n </el-tag>\n </template>\n </el-table-column>\n </el-table>\n <div class=\"pdd-subtitle\">关联产品信息</div>\n <el-table :data=\"skuVariants\" border size=\"small\" class=\"pdd-table\">\n <el-table-column label=\"图片\" width=\"70\" align=\"center\">\n <template #default=\"{ row }\">\n <el-image\n v-if=\"row.main_image\"\n :src=\"row.main_image\"\n :preview-src-list=\"[row.main_image]\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-thumb\"\n />\n <span v-else>—</span>\n </template>\n </el-table-column>\n <el-table-column label=\"SKU\" prop=\"sku_code\" min-width=\"130\" show-overflow-tooltip />\n <el-table-column label=\"中文品名\" prop=\"product_name\" min-width=\"150\" show-overflow-tooltip />\n <el-table-column label=\"英文品名\" min-width=\"150\" show-overflow-tooltip>\n <template #default=\"{ row }\">{{ fmt(row.product_name_en || row.product_en_name) }}</template>\n </el-table-column>\n <el-table-column\n v-for=\"attr in styleAttrs\"\n :key=\"attr.attr_code\"\n :label=\"attr.attr_name\"\n min-width=\"100\"\n >\n <template #default=\"{ row }\">{{ variantAttrText(row, attr) }}</template>\n </el-table-column>\n </el-table>\n </template>\n\n <!-- ===== 规格信息 ===== -->\n <div class=\"pdd-title\">规格信息</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item label=\"单品毛重\">{{ weightText(spec.gross_weight, spec.gross_weight_unit) }}</el-descriptions-item>\n <el-descriptions-item label=\"单品净重\">{{ weightText(spec.net_weight, spec.net_weight_unit) }}</el-descriptions-item>\n <el-descriptions-item label=\"包装重\">{{ weightText(spec.tare_weight, spec.tare_weight_unit) }}</el-descriptions-item>\n <el-descriptions-item label=\"单品尺寸\">{{ dimText(spec.length, spec.width, spec.height) }}</el-descriptions-item>\n <el-descriptions-item label=\"包装尺寸\" :span=\"2\">{{ dimText(spec.tare_length, spec.tare_width, spec.tare_height) }}</el-descriptions-item>\n </el-descriptions>\n <template v-if=\"specBoxList.length\">\n <div class=\"pdd-subtitle\">装箱规格</div>\n <el-table :data=\"specBoxList\" border size=\"small\" class=\"pdd-table\">\n <el-table-column type=\"index\" label=\"序号\" width=\"60\" align=\"center\" />\n <el-table-column label=\"箱规名称\" prop=\"box_name\" min-width=\"130\" show-overflow-tooltip />\n <el-table-column label=\"单箱数量\" min-width=\"90\">\n <template #default=\"{ row }\">{{ row.box_quantity != null ? `${row.box_quantity} pcs` : '—' }}</template>\n </el-table-column>\n <el-table-column label=\"单箱重量\" min-width=\"100\">\n <template #default=\"{ row }\">{{ weightText(row.one_box_weight, row.one_box_unit) }}</template>\n </el-table-column>\n <el-table-column label=\"箱子重量\" min-width=\"100\">\n <template #default=\"{ row }\">{{ weightText(row.box_weight, row.box_unit) }}</template>\n </el-table-column>\n <el-table-column label=\"外箱尺寸\" min-width=\"150\">\n <template #default=\"{ row }\">{{ dimText(row.box_length, row.box_width, row.box_height) }}</template>\n </el-table-column>\n <el-table-column label=\"首选\" width=\"70\" align=\"center\">\n <template #default=\"{ row }\">\n <el-tag v-if=\"Number(row.is_preferred) === 1\" size=\"small\" type=\"success\">首选</el-tag>\n <span v-else>—</span>\n </template>\n </el-table-column>\n </el-table>\n </template>\n\n <!-- ===== 采购信息(单品/组合产品) ===== -->\n <template v-if=\"!isSpu\">\n <div class=\"pdd-title\">采购信息</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item label=\"采购成本\">{{ fmt(purchase.purchase_cost) }}</el-descriptions-item>\n <el-descriptions-item label=\"采购交期\">{{ purchase.delivery_day != null && purchase.delivery_day !== '' ? `${purchase.delivery_day} 天` : '—' }}</el-descriptions-item>\n <el-descriptions-item label=\"采购税率\">{{ purchase.tax_rate != null && purchase.tax_rate !== '' ? `${purchase.tax_rate} %` : '—' }}</el-descriptions-item>\n <el-descriptions-item label=\"采购备注\" :span=\"3\">{{ fmt(purchase.purchase_remark) }}</el-descriptions-item>\n </el-descriptions>\n <template v-if=\"supplierList.length\">\n <div class=\"pdd-subtitle\">报价信息</div>\n <div v-for=\"(sup, si) in supplierList\" :key=\"si\" class=\"pdd-supplier\">\n <div class=\"pdd-supplier-head\">\n <span class=\"pdd-supplier-name\">{{ sup.supplier_name || sup.supplier_code || '—' }}</span>\n <el-tag v-if=\"Number(sup.is_preferred) === 1\" size=\"small\" type=\"success\">首选</el-tag>\n <span class=\"pdd-supplier-meta\">预计交期:{{ sup.delivery_day != null && sup.delivery_day !== '' ? `${sup.delivery_day} 天` : '—' }}</span>\n <span class=\"pdd-supplier-meta\">报价备注:{{ fmt(sup.purchase_remark ?? sup.remark) }}</span>\n </div>\n <el-table :data=\"supplierQuoteRows(sup)\" border size=\"small\">\n <el-table-column label=\"币种\" prop=\"currency\" width=\"80\" />\n <el-table-column label=\"含税\" width=\"70\" align=\"center\">\n <template #default=\"{ row }\">{{ Number(row.is_tax) === 1 ? '是' : '否' }}</template>\n </el-table-column>\n <el-table-column label=\"税率\" width=\"80\">\n <template #default=\"{ row }\">{{ row.tax_rate != null && row.tax_rate !== '' ? `${row.tax_rate} %` : '—' }}</template>\n </el-table-column>\n <el-table-column label=\"采购数量 ≥\" min-width=\"100\">\n <template #default=\"{ row }\">{{ fmt(row.purchase_quantity) }}</template>\n </el-table-column>\n <el-table-column label=\"单价\" min-width=\"100\">\n <template #default=\"{ row }\">{{ fmt(row.purchase_price) }}</template>\n </el-table-column>\n <el-table-column label=\"含税单价\" min-width=\"100\">\n <template #default=\"{ row }\">{{ fmt(row.purchase_price_tax) }}</template>\n </el-table-column>\n </el-table>\n </div>\n </template>\n </template>\n\n <!-- ===== 产品图片(单品/组合产品) ===== -->\n <template v-if=\"!isSpu\">\n <div class=\"pdd-title\">产品图片</div>\n <el-descriptions :column=\"1\" border size=\"small\">\n <el-descriptions-item label=\"主图\">\n <el-image\n v-if=\"mainImage\"\n :src=\"mainImage\"\n :preview-src-list=\"[mainImage]\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-img\"\n />\n <span v-else>—</span>\n </el-descriptions-item>\n <el-descriptions-item label=\"尺寸图\">\n <template v-if=\"sizeImages.length\">\n <el-image\n v-for=\"(img, i) in sizeImages\"\n :key=\"i\"\n :src=\"img\"\n :preview-src-list=\"sizeImages\"\n :initial-index=\"i\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-img\"\n />\n </template>\n <span v-else>—</span>\n </el-descriptions-item>\n <el-descriptions-item label=\"卖点图\">\n <template v-if=\"sellingPointImages.length\">\n <el-image\n v-for=\"(img, i) in sellingPointImages\"\n :key=\"i\"\n :src=\"img\"\n :preview-src-list=\"sellingPointImages\"\n :initial-index=\"i\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-img\"\n />\n </template>\n <span v-else>—</span>\n </el-descriptions-item>\n </el-descriptions>\n </template>\n\n <!-- ===== 申报信息 ===== -->\n <div class=\"pdd-title\">申报信息</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item label=\"中文申报名\">{{ fmt(declaration.declaration_name) }}</el-descriptions-item>\n <el-descriptions-item label=\"英文申报名\">{{ fmt(declaration.declaration_name_en) }}</el-descriptions-item>\n <el-descriptions-item label=\"中文材质\">{{ fmt(declaration.material) }}</el-descriptions-item>\n <el-descriptions-item label=\"英文材质\">{{ fmt(declaration.material_en) }}</el-descriptions-item>\n <el-descriptions-item label=\"中文用途\">{{ fmt(declaration.use) }}</el-descriptions-item>\n <el-descriptions-item label=\"英文用途\">{{ fmt(declaration.use_en) }}</el-descriptions-item>\n <el-descriptions-item label=\"中文功能\">{{ fmt(declaration.usage) }}</el-descriptions-item>\n <el-descriptions-item label=\"英文功能\">{{ fmt(declaration.usage_en) }}</el-descriptions-item>\n <el-descriptions-item label=\"申报价值\">\n {{ declaration.declaration_value != null && declaration.declaration_value !== '' ? `${declaration.declaration_value} ${declaration.declaration_currency_code || ''}` : '—' }}\n </el-descriptions-item>\n <el-descriptions-item label=\"海关编码\">{{ fmt(declaration.hs_code) }}</el-descriptions-item>\n <el-descriptions-item label=\"报关型号\">{{ fmt(declaration.declaration_model) }}</el-descriptions-item>\n <el-descriptions-item label=\"原产地\">{{ fmt(declaration.country_of_origin) }}</el-descriptions-item>\n <el-descriptions-item label=\"境内货源地\">{{ fmt(declaration.domestic_source_location) }}</el-descriptions-item>\n <el-descriptions-item label=\"申报单位\" :span=\"2\">{{ fmt(declarationUnitName) }}</el-descriptions-item>\n </el-descriptions>\n\n <!-- ===== 质检项 ===== -->\n <div class=\"pdd-title\">质检项</div>\n <el-descriptions :column=\"3\" border size=\"small\">\n <el-descriptions-item label=\"质检方式\">{{ qcMethodLabel }}</el-descriptions-item>\n <el-descriptions-item label=\"模板\" :span=\"2\">{{ fmt(qc.template_name || qc.template_id || qc.qc_temp_id) }}</el-descriptions-item>\n <el-descriptions-item label=\"图片\" :span=\"3\">\n <template v-if=\"qcImages.length\">\n <el-image\n v-for=\"(img, i) in qcImages\"\n :key=\"i\"\n :src=\"img\"\n :preview-src-list=\"qcImages\"\n :initial-index=\"i\"\n preview-teleported\n fit=\"cover\"\n class=\"pdd-img\"\n />\n </template>\n <span v-else>—</span>\n </el-descriptions-item>\n <el-descriptions-item label=\"附件\" :span=\"3\">\n <template v-if=\"qcAttachments.length\">\n <a\n v-for=\"(f, i) in qcAttachments\"\n :key=\"i\"\n :href=\"f.url\"\n target=\"_blank\"\n class=\"pdd-file\"\n >{{ f.name }}</a>\n </template>\n <span v-else>—</span>\n </el-descriptions-item>\n </el-descriptions>\n <template v-if=\"qcCustomList.length\">\n <div class=\"pdd-subtitle\">自定义质检项</div>\n <el-table :data=\"qcCustomList\" border size=\"small\" class=\"pdd-table\">\n <el-table-column type=\"index\" label=\"序号\" width=\"60\" align=\"center\" />\n <el-table-column label=\"质检项\" prop=\"qc_item\" min-width=\"150\" show-overflow-tooltip />\n <el-table-column label=\"质检内容\" prop=\"qc_content\" min-width=\"250\" show-overflow-tooltip />\n </el-table>\n </template>\n\n <!-- ===== 自定义属性 ===== -->\n <template v-if=\"customAttrList.length\">\n <div class=\"pdd-title\">自定义属性</div>\n <el-table :data=\"customAttrList\" border size=\"small\" class=\"pdd-table\">\n <el-table-column label=\"属性名称\" prop=\"attr_name\" width=\"200\" show-overflow-tooltip />\n <el-table-column label=\"属性值\">\n <template #default=\"{ row }\">{{ customAttrValueText(row) }}</template>\n </el-table-column>\n </el-table>\n </template>\n </template>\n <el-empty v-else-if=\"!loading\" description=\"暂无数据\" />\n </div>\n <template #footer>\n <el-button @click=\"emit('update:visible', false)\">关闭</el-button>\n </template>\n </el-dialog>\n</template>\n\n<script lang=\"ts\">\n/**\n * JProductDetailDialog —— 产品详情弹窗(只读)\n *\n * 与项目解耦:request 由宿主通过 prop 注入(传入各 *_front 项目 `@/api` 的默认导出),\n * token / operator / baseURL 均由宿主的 request 拦截器处理。接口路径内置。\n *\n * 前置条件(宿主项目):\n * 1. 已安装 element-plus(peerDependency)\n * 2. vite proxy 已配置 `/bis-app` 转发到后端\n * 3. 后端提供同一套 bis 产品详情接口\n *\n * 用法:\n * import request from '@/api'\n * <JProductDetailDialog v-model:visible=\"visible\" :code=\"row.sku_code\" :request=\"request\" />\n * <JProductDetailDialog v-model:visible=\"visible\" type=\"spu\" :code=\"row.spu_code\" :request=\"request\" />\n * 可选::id=\"row.id\"\n */\nimport { ref } from 'vue'\nimport type {\n JProductRequestFn,\n JProductRequestConfig,\n JProductDetailDialogProps,\n} from './types'\n\n// ---- 字典(模块级缓存:整个应用只请求一次,多个实例共享)----\nconst brandDict = ref<any[]>([])\nconst unitDict = ref<any[]>([])\nconst saleDict = ref<any[]>([])\nconst companyDict = ref<any[]>([])\nconst tagDict = ref<any[]>([])\nconst customAttrDict = ref<any[]>([])\n\nlet dictsLoaded = false\nlet dictsPromise: Promise<void> | null = null\n\nconst loadDicts = (request: JProductRequestFn): Promise<void> => {\n const post = (url: string, data: any): Promise<any> =>\n request({ url, method: 'post', data } as JProductRequestConfig)\n if (dictsLoaded) return Promise.resolve()\n if (dictsPromise) return dictsPromise\n dictsPromise = Promise.all([\n post('/bis-app/comm/productAttrValue/getAll', { pageSize: 999 }).then((res) => {\n if (res.code === 1) {\n brandDict.value = res.data?.brand || []\n unitDict.value = res.data?.unit || []\n saleDict.value = res.data?.sale || []\n }\n }).catch(() => { /* 展示走 _name 字段兜底,字典失败不阻断 */ }),\n post('/bis-app/comm/company/list', { pageSize: 999, subject_type: 'purchase' }).then((res) => {\n if (res.code === 1) companyDict.value = res.data?.list || res.data || []\n }).catch(() => { /* ignore */ }),\n post('/bis-app/comm/tagCategoryValue/list', { tag_code: 'PRODUCT_TAG', pageIndex: 1, pageSize: 999 }).then((res) => {\n if (res.code === 1) tagDict.value = res.data?.list || res.data || []\n }).catch(() => { /* ignore */ }),\n post('/bis-app/comm/customAttr/list', { pageIndex: 1, pageSize: 999 }).then((res) => {\n if (res.code === 1) customAttrDict.value = res.data?.list || res.data || []\n }).catch(() => { /* ignore */ }),\n ]).then(() => { dictsLoaded = true }).finally(() => { dictsPromise = null })\n return dictsPromise\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, watch } from 'vue'\nimport {\n ElDialog,\n ElDescriptions,\n ElDescriptionsItem,\n ElTag,\n ElTable,\n ElTableColumn,\n ElImage,\n ElEmpty,\n ElButton,\n ElMessage,\n vLoading,\n} from 'element-plus'\n// 类型已在上方 <script> 中统一 import(双 script 同作用域,避免 Duplicate identifier)\n\ndefineOptions({\n name: 'JProductDetailDialog',\n directives: { loading: vLoading },\n})\n\nconst props = withDefaults(defineProps<JProductDetailDialogProps>(), {\n visible: false,\n code: '',\n type: 'sku',\n id: undefined,\n})\n\nconst emit = defineEmits<{ 'update:visible': [boolean] }>()\n\nconst post = (url: string, data: any): Promise<any> =>\n props.request({ url, method: 'post', data } as JProductRequestConfig)\n\nconst loading = ref(false)\nconst detail = ref<any>(null)\n\n// ---- 请求:弹窗打开时并行加载字典(缓存)+ 详情 ----\nconst fetchDetail = async () => {\n if (!props.code && props.id === undefined) return\n detail.value = null\n loadDicts(props.request)\n const url = props.type === 'spu' ? '/bis-app/comm/spu/doDetail' : '/bis-app/comm/sku/doDetail'\n const params = props.type === 'spu'\n ? { id: props.id, spu_code: props.code }\n : { id: props.id, sku_code: props.code }\n loading.value = true\n try {\n const res = await post(url, params)\n if (res.code === 1 && res.data) {\n detail.value = res.data\n } else {\n ElMessage.error(res.msg || '获取详情失败')\n }\n } catch {\n ElMessage.error('获取详情失败')\n } finally {\n loading.value = false\n }\n}\n\nwatch(() => props.visible, (val) => {\n if (val) fetchDetail()\n})\n\n// ---- 数据分区(兼容详情接口嵌套结构与列表接口扁平结构)----\nconst basic = computed(() => detail.value?.basic_info ?? detail.value ?? {})\nconst spec = computed(() => detail.value?.spec_info ?? {})\nconst images = computed(() => detail.value?.images_info ?? detail.value?.image_info ?? {})\nconst purchase = computed(() => detail.value?.purchase_info ?? {})\nconst declaration = computed(() => detail.value?.declaration_info ?? {})\nconst qc = computed(() => detail.value?.qc_info ?? {})\nconst bindSku = computed(() => detail.value?.bind_sku_info ?? {})\nconst spuBindSku = computed(() => detail.value?.spu_bind_sku ?? {})\n\n// 装箱规格与供应商报价:详情接口在顶层,兼容嵌套位置\nconst specBoxList = computed<any[]>(() => detail.value?.spec_box_info ?? spec.value.spec_box_info ?? [])\nconst supplierList = computed<any[]>(() => detail.value?.sku_supplier ?? purchase.value.supplier_list ?? [])\n\nconst productType = computed(() => String(basic.value.product_type ?? (props.type === 'spu' ? '30' : '10')))\nconst isSpu = computed(() => productType.value === '30')\nconst productTypeLabel = computed(() => ({ '10': '单品', '20': '组合产品', '30': '多属性产品' } as Record<string, string>)[productType.value] || productType.value)\n\nconst nameCn = computed(() => (isSpu.value ? (basic.value.spu_name || basic.value.product_name) : basic.value.product_name))\nconst nameEn = computed(() => (isSpu.value ? (basic.value.spu_name_en || basic.value.product_name_en) : basic.value.product_name_en))\nconst mainCode = computed(() => (isSpu.value ? basic.value.spu_code : basic.value.sku_code))\n\n// ---- 归一化工具 ----\nconst normalizeStringArray = (v: any): string[] => {\n if (v == null || v === '') return []\n if (Array.isArray(v)) return v.map(String).filter(Boolean)\n if (typeof v === 'string') {\n const s = v.trim()\n if (!s) return []\n if (s.startsWith('[')) {\n try {\n const arr = JSON.parse(s)\n return Array.isArray(arr) ? arr.map(String).filter(Boolean) : []\n } catch { /* fallthrough */ }\n }\n return s.split(',').map((x) => x.trim()).filter(Boolean)\n }\n return [String(v)]\n}\n\nconst normalizeAttachments = (v: any): { name: string; url: string }[] => {\n let list: any[] = []\n if (Array.isArray(v)) list = v\n else if (typeof v === 'string' && v.trim()) {\n try {\n const arr = JSON.parse(v)\n list = Array.isArray(arr) ? arr : [v]\n } catch { list = [v] }\n }\n return list\n .map((it) => {\n if (typeof it === 'string') return { name: it.split('/').pop() || it, url: it }\n const url = it?.url || it?.file_url || it?.path || ''\n return { name: it?.name || it?.file_name || url.split('/').pop() || '附件', url }\n })\n .filter((f) => f.url)\n}\n\nconst fmt = (v: any) => (v == null || v === '' ? '—' : v)\nconst weightText = (v: any, unit?: string) => (v == null || v === '' ? '—' : `${v} ${unit || ''}`.trim())\nconst dimText = (l: any, w: any, h: any, unit = 'cm') => {\n if ([l, w, h].every((x) => x == null || x === '')) return '—'\n const p = (x: any) => (x == null || x === '' ? '—' : x)\n return `${p(l)} × ${p(w)} × ${p(h)} ${unit}`\n}\n\n// ---- 字段展示(优先详情返回的 _name 字段,字典映射兜底)----\nconst dictName = (list: any[], id: any): string => {\n if (id == null || id === '') return ''\n const hit = list.find((x) => String(x.id) === String(id))\n return hit?.attr_value_name || ''\n}\n\nconst brandName = computed(() => basic.value.brand_name || dictName(brandDict.value, basic.value.brand_id))\nconst unitName = computed(() => basic.value.unit_name || dictName(unitDict.value, basic.value.unit_id))\nconst statusName = computed(() =>\n basic.value.sale_status_name || basic.value.status_name || dictName(saleDict.value, basic.value.status)\n)\nconst declarationUnitName = computed(() =>\n declaration.value.declaration_unit_name || dictName(unitDict.value, declaration.value.declaration_unit_id) || declaration.value.declaration_unit_id\n)\n\nconst peNames = computed(() => {\n if (basic.value.pe_code_name) return basic.value.pe_code_name\n const codes = normalizeStringArray(basic.value.pe_codes)\n if (!codes.length) return ''\n return codes\n .map((c) => companyDict.value.find((x) => String(x.company_code) === String(c))?.company_name || c)\n .join('、')\n})\n\nconst tagList = computed(() =>\n normalizeStringArray(basic.value.tags).map((code) => {\n const hit = tagDict.value.find((t) => String(t.tag_value_code) === String(code))\n return { code, name: hit?.tag_value_name || code, color: hit?.tag_color || '' }\n })\n)\n\nconst skuAttrText = computed(() => {\n const attr = basic.value.sku_attr\n if (!attr || typeof attr !== 'object' || Array.isArray(attr)) return ''\n return Object.entries(attr).map(([k, v]) => `${k}: ${v}`).join(';')\n})\n\nconst basicAttachments = computed(() => normalizeAttachments(basic.value.att_files))\nconst hasDesc = computed(() => {\n const html = basic.value.product_desc || ''\n return String(html).replace(/<[^>]*>/g, '').trim().length > 0 || /<img/i.test(String(html))\n})\n\n// 图片\nconst mainImage = computed(() => images.value.main_image || detail.value?.product_image || '')\nconst sizeImages = computed(() => normalizeStringArray(images.value.size_images ?? detail.value?.size_images))\nconst sellingPointImages = computed(() => normalizeStringArray(images.value.selling_point_images))\n\n// 质检\nconst qcMethodLabel = computed(() =>\n ({ spot: '抽检', full: '全检', exempt: '免检' } as Record<string, string>)[qc.value.qc_method] || fmt(qc.value.qc_method)\n)\nconst qcImages = computed(() => normalizeStringArray(qc.value.images))\nconst qcAttachments = computed(() => normalizeAttachments(qc.value.att_files))\nconst qcCustomList = computed<any[]>(() => (Array.isArray(qc.value.qc_content) ? qc.value.qc_content : []))\n\n// 自定义属性\n// 详情里每行只有 custom_attr_id + 值(id),属性名和选项名需按 custom_attr_id 去字典匹配。\n// 字典项字段名与表单 allCustomAttrs 保持一致的多路兜底。\nconst dictAttrId = (item: any): string =>\n String(item.custom_attr_id ?? item.id ?? item.attr_id ?? item.attr_code ?? '').trim()\n\n// 解析字典项的选项列表 → [{id, name}](对齐表单 parseCustomAttrOptions)\nconst parseAttrOptions = (raw: any): { id: string; name: string }[] => {\n const list = Array.isArray(raw) ? raw : (raw != null && raw !== '' ? [raw] : [])\n const out: { id: string; name: string }[] = []\n for (const item of list) {\n if (typeof item === 'string') {\n item.split(/[,,、\\n]/).map((s) => s.trim()).filter(Boolean).forEach((name) => out.push({ id: '', name }))\n } else if (item && typeof item === 'object') {\n const name = String(item.attr_value ?? item.value ?? item.label ?? item.attr_value_name ?? item.name ?? '').trim()\n const id = String(item.id ?? item.attr_value_id ?? item.value_id ?? '')\n if (name) out.push({ id, name })\n }\n }\n return out\n}\n\n// custom_attr_id → 字典项\nconst customAttrDictMap = computed(() => {\n const m = new Map<string, any>()\n for (const d of customAttrDict.value) {\n const id = dictAttrId(d)\n if (id) m.set(id, d)\n }\n return m\n})\n\nconst customAttrList = computed<any[]>(() => {\n const info = detail.value?.custom_attr_info\n const list = info?.list ?? info\n const rows = Array.isArray(list) ? list : []\n return rows.map((row) => {\n const id = dictAttrId(row)\n const def = customAttrDictMap.value.get(id)\n return {\n ...row,\n custom_attr_id: id,\n // 属性名:详情自带优先,否则取字典\n attr_name: row.attr_name || def?.attr_name || id,\n options: parseAttrOptions(def?.attr_value ?? def?.options ?? row.options ?? row.attr_value),\n }\n })\n})\n\nconst customAttrValueText = (row: any): string => {\n const values = normalizeStringArray(row.custom_attr_value_id ?? row.custom_attr_value)\n if (!values.length) return '—'\n const options: any[] = row.options || []\n return values\n .map((v) => options.find((o) => (o.id && String(o.id) === String(v)) || String(o.name) === String(v))?.name || v)\n .join('、')\n}\n\n// 组合产品\nconst bindSkuList = computed<any[]>(() => bindSku.value.bind_sku_list ?? [])\n\n// SPU 款式属性 / SKU 变体\nconst styleAttrs = computed<any[]>(() => spuBindSku.value.sku_attr ?? [])\nconst skuVariants = computed<any[]>(() => spuBindSku.value.sku_list ?? [])\nconst variantAttrText = (row: any, attr: any): string => {\n const code = row.sku_attr?.[attr.attr_code]\n if (code == null || code === '') return '—'\n const child = (attr.childs || []).find((c: any) => String(c.attr_value_code) === String(code))\n return child?.attr_value_name || String(code)\n}\n\n// 供应商报价:币种组 × 阶梯 摊平成行\nconst supplierQuoteRows = (sup: any): any[] => {\n const rows: any[] = []\n for (const q of sup.supplier_quote || []) {\n for (const item of q.quote_list || []) {\n rows.push({\n currency: q.quote_currency_code,\n is_tax: q.is_tax,\n tax_rate: q.tax_rate,\n ...item,\n })\n }\n }\n return rows\n}\n</script>\n\n<style scoped>\n.pdd-body {\n min-height: 200px;\n max-height: 72vh;\n overflow-y: auto;\n padding-right: 4px;\n}\n\n.pdd-title {\n font-size: 15px;\n font-weight: 600;\n color: #303133;\n margin: 18px 0 10px;\n padding-left: 8px;\n border-left: 3px solid #409eff;\n}\n\n.pdd-title:first-child {\n margin-top: 0;\n}\n\n.pdd-subtitle {\n font-size: 13px;\n font-weight: 600;\n color: #606266;\n margin: 12px 0 8px;\n}\n\n.pdd-table {\n margin-bottom: 4px;\n}\n\n.pdd-tag {\n margin-right: 6px;\n margin-bottom: 2px;\n}\n\n.pdd-file {\n display: inline-block;\n margin-right: 14px;\n color: #409eff;\n text-decoration: none;\n}\n\n.pdd-file:hover {\n text-decoration: underline;\n}\n\n.pdd-img {\n width: 80px;\n height: 80px;\n margin-right: 8px;\n border-radius: 4px;\n border: 1px solid #e4e7ed;\n vertical-align: top;\n}\n\n.pdd-thumb {\n width: 40px;\n height: 40px;\n border-radius: 4px;\n}\n\n.pdd-rich {\n max-height: 300px;\n overflow-y: auto;\n}\n\n.pdd-rich :deep(img) {\n max-width: 100%;\n}\n\n.pdd-supplier {\n margin-bottom: 12px;\n border: 1px solid #e4e7ed;\n border-radius: 4px;\n padding: 10px;\n}\n\n.pdd-supplier-head {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 8px;\n font-size: 13px;\n}\n\n.pdd-supplier-name {\n font-weight: 600;\n color: #303133;\n}\n\n.pdd-supplier-meta {\n color: #909399;\n}\n</style>\n","<template>\n <span\n v-if=\"hasCode\"\n class=\"j-sku-link\"\n @click.stop=\"handleClick\"\n >{{ displayText }}</span>\n <span v-else class=\"j-sku-link-empty\">{{ emptyText }}</span>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\ndefineOptions({ name: 'JSkuLink' })\n\nconst props = withDefaults(defineProps<{\n code?: string | null\n emptyText?: string\n}>(), {\n emptyText: '-',\n})\n\nconst emit = defineEmits<{\n open: [code: string]\n}>()\n\nconst displayText = computed(() => {\n const value = String(props.code ?? '').trim()\n return value || props.emptyText\n})\n\nconst hasCode = computed(() => {\n const value = String(props.code ?? '').trim()\n return value !== '' && value !== '-'\n})\n\nconst handleClick = () => {\n if (!hasCode.value) return\n emit('open', String(props.code).trim())\n}\n</script>\n\n<style scoped>\n.j-sku-link {\n color: #409eff;\n font-weight: 700;\n cursor: pointer;\n}\n\n.j-sku-link:hover {\n text-decoration: underline;\n}\n\n.j-sku-link-empty {\n color: inherit;\n font-weight: inherit;\n}\n</style>\n","import { ref } from 'vue'\n\n/**\n * 产品详情弹窗状态管理。\n *\n * 用法:\n * const { productDetailDialogVisible, productDetailDialogCode, openProductDetailDialog }\n * = useProductDetailDialog()\n * // <JSkuLink :code=\"row.sku_code\" @open=\"openProductDetailDialog\" />\n * // <JProductDetailDialog v-model:visible=\"productDetailDialogVisible\"\n * // :code=\"productDetailDialogCode\" :request=\"request\" />\n */\nexport function useProductDetailDialog() {\n const productDetailDialogVisible = ref(false)\n const productDetailDialogCode = ref('')\n\n const openProductDetailDialog = (code: string) => {\n const sku = String(code ?? '').trim()\n if (!sku || sku === '-') return\n productDetailDialogCode.value = sku\n productDetailDialogVisible.value = true\n }\n\n return {\n productDetailDialogVisible,\n productDetailDialogCode,\n openProductDetailDialog,\n }\n}\n","<!--\r\n JSearchInputDialog - 关键词搜索复合控件\r\n\r\n 结构:\r\n [ 类型下拉 ] + [ 关键词输入框 ] + [ 批量输入按钮 ]\r\n │\r\n └─ 点右侧按钮 → Dialog + textarea 批量编辑\r\n\r\n 主流程:\r\n 1. 父组件传入 options(如 SKU / 品名),v-model:type + v-model:keyword 双向绑定\r\n 2. 用户左侧选类型,中间手输关键词;或点右侧 icon 打开弹窗批量粘贴\r\n 3. 弹窗确定:textarea 文本规范化 → 写回 keyword → emit('confirm')\r\n 4. 输入框回车:emit('search')\r\n 5. 父组件用 { [type]: keyword } 拼请求(也可调用 expose 的 toParams)\r\n\r\n 示例请求结果:type='sku', keyword='sku1,sku2' → { sku: 'sku1,sku2' }\r\n-->\r\n<template>\r\n <div class=\"j-search-input-dialog\" :style=\"{ width: width }\">\r\n <!-- 主输入区:前置类型 + 关键词 + 右侧批量入口 -->\r\n <el-input\r\n v-model=\"keyword\"\r\n :placeholder=\"placeholder\"\r\n clearable\r\n class=\"j-search-input-dialog__input\"\r\n @keyup.enter=\"emit('search')\"\r\n >\r\n <!-- 左侧:搜索字段类型(SKU / 品名 / 自定义) -->\r\n <template #prepend>\r\n <el-select\r\n v-model=\"type\"\r\n :style=\"{ width: selectWidth }\"\r\n :disabled=\"!options.length\"\r\n >\r\n <el-option\r\n v-for=\"item in options\"\r\n :key=\"item.value\"\r\n :label=\"item.label\"\r\n :value=\"item.value\"\r\n />\r\n </el-select>\r\n </template>\r\n <!-- 右侧:打开批量输入弹窗 -->\r\n <template #append>\r\n <el-button :icon=\"Memo\" :title=\"dialogTitleText\" @click=\"openDialog\" />\r\n </template>\r\n </el-input>\r\n\r\n <!-- 批量输入弹窗:textarea 编辑多值,确定后合并回主输入框 -->\r\n <el-dialog\r\n v-model=\"dialogVisible\"\r\n :title=\"dialogTitleText\"\r\n :width=\"dialogWidth\"\r\n append-to-body\r\n destroy-on-close\r\n :close-on-click-modal=\"false\"\r\n @closed=\"handleDialogClosed\"\r\n >\r\n <el-input\r\n v-model=\"textareaValue\"\r\n type=\"textarea\"\r\n :rows=\"rows\"\r\n :placeholder=\"textareaPlaceholder\"\r\n resize=\"vertical\"\r\n />\r\n <template #footer>\r\n <el-button @click=\"dialogVisible = false\">取消</el-button>\r\n <el-button type=\"primary\" @click=\"handleConfirm\">确定</el-button>\r\n </template>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport { Memo } from '@element-plus/icons-vue'\r\nimport type { JSearchInputDialogProps, SearchInputModel, SearchInputOption } from './types'\r\n\r\ndefineOptions({\r\n name: 'JSearchInputDialog',\r\n})\r\n\r\nconst props = withDefaults(defineProps<JSearchInputDialogProps>(), {\r\n options: () => [],\r\n placeholder: '请输入关键词',\r\n width: '320px',\r\n selectWidth: '100px',\r\n separator: ',',\r\n dialogTitle: '',\r\n dialogWidth: '480px',\r\n rows: 8,\r\n textareaPlaceholder: '支持换行、逗号、空格分隔,确定后自动合并',\r\n clearOnTypeChange: false,\r\n})\r\n\r\n/**\r\n * 双向绑定:\r\n * - type:当前选中的搜索字段类型(对应 options[].value)\r\n * - keyword:最终要参与搜索的关键词字符串(可多值,如 sku1,sku2)\r\n *\r\n * 父组件:\r\n * v-model:type=\"filters.keywordType\"\r\n * v-model:keyword=\"filters.keyword\"\r\n */\r\nconst type = defineModel<string>('type', { default: '' })\r\nconst keyword = defineModel<string>('keyword', { default: '' })\r\n\r\nconst emit = defineEmits<{\r\n /** 弹窗点「确定」并写回 keyword 后触发;父级常用来立刻 handleSearch */\r\n confirm: [payload: SearchInputModel]\r\n /** 主输入框回车触发;父级常用来 handleSearch */\r\n search: []\r\n}>()\r\n\r\n/** 批量输入弹窗显隐 */\r\nconst dialogVisible = ref(false)\r\n/** 弹窗内 textarea 的临时编辑值(确定前不影响外部 keyword) */\r\nconst textareaValue = ref('')\r\n\r\n/** 当前 type 对应的 option(用于取 label 拼弹窗标题) */\r\nconst currentOption = computed(() =>\r\n (props.options as SearchInputOption[]).find((item) => item.value === type.value),\r\n)\r\n\r\n/** 弹窗标题:优先用 props.dialogTitle,否则「批量输入{label}」 */\r\nconst dialogTitleText = computed(() => {\r\n if (props.dialogTitle) return props.dialogTitle\r\n const label = currentOption.value?.label || '关键词'\r\n return `批量输入${label}`\r\n})\r\n\r\n/**\r\n * 规范化批量文本 → 统一分隔符拼接的字符串\r\n * 流程:拆分(换行/逗号/分号/空白)→ trim → 去空 → 去重(保序)→ join(separator)\r\n * 例:'sku1\\nsku2, sku2 sku3' + separator=',' → 'sku1,sku2,sku3'\r\n */\r\nconst normalizeKeywords = (raw: string): string => {\r\n if (!raw) return ''\r\n const parts = raw\r\n .split(/[\\n\\r,,;;\\s\\t]+/)\r\n .map((item) => item.trim())\r\n .filter(Boolean)\r\n\r\n const unique: string[] = []\r\n const seen = new Set<string>()\r\n for (const part of parts) {\r\n if (seen.has(part)) continue\r\n seen.add(part)\r\n unique.push(part)\r\n }\r\n\r\n return unique.join(props.separator)\r\n}\r\n\r\n/**\r\n * 主输入框 keyword → textarea 多行回显\r\n * 打开弹窗前调用,方便用户在已有值上继续编辑\r\n * 例:'sku1,sku2' → 'sku1\\nsku2'\r\n */\r\nconst keywordToTextarea = (value: string): string => {\r\n if (!value) return ''\r\n return value\r\n .split(/[\\n\\r,,;;\\s\\t.]+/)\r\n .map((item) => item.trim())\r\n .filter(Boolean)\r\n .join('\\n')\r\n}\r\n\r\n/**\r\n * 打开批量输入弹窗\r\n * 1. 把当前 keyword 拆成多行填入 textarea\r\n * 2. 显示 dialog\r\n */\r\nconst openDialog = () => {\r\n textareaValue.value = keywordToTextarea(keyword.value)\r\n dialogVisible.value = true\r\n}\r\n\r\n/**\r\n * 弹窗点「确定」\r\n * 1. 规范化 textarea → 写回 keyword(同步到父组件 v-model)\r\n * 2. 关闭弹窗\r\n * 3. emit confirm,父组件可据此触发搜索\r\n * 注意:组件本身不发请求,只负责回写数据\r\n */\r\nconst handleConfirm = () => {\r\n keyword.value = normalizeKeywords(textareaValue.value)\r\n dialogVisible.value = false\r\n emit('confirm', {\r\n type: type.value,\r\n keyword: keyword.value,\r\n })\r\n}\r\n\r\n/**\r\n * 弹窗完全关闭后清理临时 textarea\r\n * 取消 / 确定关闭都会走这里;取消时不会改外部 keyword\r\n */\r\nconst handleDialogClosed = () => {\r\n textareaValue.value = ''\r\n}\r\n\r\n// 初始化:父组件未传 type 时,默认选中 options 第一项\r\nif (!type.value && props.options?.length) {\r\n type.value = props.options[0]?.value || ''\r\n}\r\n\r\n/**\r\n * 监听类型切换\r\n * 仅当 clearOnTypeChange=true 时,切换左侧类型会清空 keyword\r\n */\r\nwatch(type, (next, prev) => {\r\n if (!props.clearOnTypeChange) return\r\n if (next === prev) return\r\n keyword.value = ''\r\n})\r\n\r\n/**\r\n * 重置(供父组件 ref 调用)\r\n * @param defaultType 指定重置后的类型;不传则用 options[0]\r\n * 会清空 keyword\r\n */\r\nconst reset = (defaultType?: string) => {\r\n type.value = defaultType || props.options?.[0]?.value || ''\r\n keyword.value = ''\r\n}\r\n\r\n/**\r\n * 拼请求参数(供父组件 ref 调用)\r\n * 有 keyword 时返回 { [type]: keyword },否则 {}\r\n * 例:{ sku: 'sku1,sku2' }\r\n */\r\nconst toParams = (): Record<string, string> => {\r\n if (!keyword.value || !type.value) return {}\r\n return { [type.value]: keyword.value }\r\n}\r\n\r\n/**\r\n * 对外暴露,父组件通过 ref 调用:\r\n * - reset() 重置类型和关键词\r\n * - toParams() 直接拿请求参数对象\r\n * - openDialog() 程序化打开批量弹窗\r\n */\r\ndefineExpose({\r\n reset,\r\n toParams,\r\n openDialog,\r\n})\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n/* 让前置 select 贴合 el-input 的 prepend 区域,去掉多余边框/阴影 */\r\n.j-search-input-dialog {\r\n display: inline-block;\r\n vertical-align: middle;\r\n\r\n :deep(.el-input-group__prepend) {\r\n background-color: var(--el-fill-color-blank);\r\n padding: 0;\r\n }\r\n\r\n :deep(.el-input-group__prepend .el-select) {\r\n margin: 0;\r\n }\r\n\r\n :deep(.el-input-group__prepend .el-select .el-select__wrapper) {\r\n box-shadow: none !important;\r\n border: none;\r\n background: transparent;\r\n }\r\n}\r\n</style>\r\n","/**\r\n * 递归转换值(处理嵌套对象和数组)\r\n */\r\nfunction deepTransformValue(value: any, transformer: (obj: Record<string, any>) => Record<string, any>): any {\r\n if (Array.isArray(value)) {\r\n return value.map((item) => deepTransformValue(item, transformer))\r\n }\r\n if (value !== null && typeof value === 'object' && !(value instanceof Date)) {\r\n return transformer(value)\r\n }\r\n return value\r\n}\r\n\r\n/**\r\n * 将对象的 key 从小驼峰转为下划线格式(支持深度嵌套)\r\n * @param obj 需要转换的对象\r\n * @param excludeKeys 不需要转换的 key 数组(可选)\r\n */\r\nexport function toSnakeCase<T extends Record<string, any>>(\r\n obj: T,\r\n excludeKeys: string[] = []\r\n): Record<string, any> {\r\n return Object.fromEntries(\r\n Object.entries(obj).map(([key, value]) => {\r\n const newValue = deepTransformValue(value, (v) => toSnakeCase(v, excludeKeys))\r\n if (excludeKeys.includes(key)) {\r\n return [key, newValue]\r\n }\r\n const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase()\r\n return [snakeKey, newValue]\r\n })\r\n )\r\n}\r\n\r\n/**\r\n * 将对象的 key 从下划线格式转为小驼峰(支持深度嵌套)\r\n * @param obj 需要转换的对象\r\n * @param excludeKeys 不需要转换的 key 数组(可选)\r\n */\r\nexport function toCamelCase<T extends Record<string, any>>(\r\n obj: T,\r\n excludeKeys: string[] = []\r\n): Record<string, any> {\r\n return Object.fromEntries(\r\n Object.entries(obj).map(([key, value]) => {\r\n const newValue = deepTransformValue(value, (v) => toCamelCase(v, excludeKeys))\r\n if (excludeKeys.includes(key)) {\r\n return [key, newValue]\r\n }\r\n const camelKey = key.replace(/_([a-z])/g, (_, char) => char.toUpperCase())\r\n return [camelKey, newValue]\r\n })\r\n )\r\n}\r\n\r\n/**\r\n * 从对象中提取指定的 key\r\n * @param obj 源对象\r\n * @param keys 要提取的 key 数组\r\n */\r\nexport function pick<T extends Record<string, any>, K extends keyof T>(\r\n obj: T,\r\n keys: K[]\r\n): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 从对象中排除指定的 key\r\n * @param obj 源对象\r\n * @param keys 要排除的 key 数组\r\n */\r\nexport function omit<T extends Record<string, any>, K extends keyof T>(\r\n obj: T,\r\n keys: K[]\r\n): Omit<T, K> {\r\n const result = { ...obj }\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * 深拷贝对象\r\n * @param obj 需要拷贝的对象\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== 'object') return obj\r\n if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T\r\n if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags) as unknown as T\r\n if (Array.isArray(obj)) return obj.map((item) => deepClone(item)) as unknown as T\r\n const cloned = {} as Record<string, any>\r\n for (const key of Object.keys(obj)) {\r\n cloned[key] = deepClone((obj as Record<string, any>)[key])\r\n }\r\n return cloned as T\r\n}\r\n\r\n/**\r\n * 过滤对象中的空值(null、undefined、空字符串)\r\n * @param obj 需要过滤的对象\r\n * @param deep 是否递归过滤嵌套对象,默认 false\r\n */\r\nexport function filterEmpty<T extends Record<string, any>>(\r\n obj: T,\r\n deep = false\r\n): Partial<T> {\r\n const result = {} as Record<string, any>\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (value === null || value === undefined || value === '') continue\r\n if (deep && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\r\n const filtered = filterEmpty(value, true)\r\n if (Object.keys(filtered).length > 0) {\r\n result[key] = filtered\r\n }\r\n } else {\r\n result[key] = value\r\n }\r\n }\r\n return result as Partial<T>\r\n}\r\n\r\n/**\r\n * 将嵌套对象扁平化为单层对象\r\n * @param obj 需要扁平化的对象\r\n * @param prefix key 前缀,默认为空\r\n * @param separator 分隔符,默认为 '.'\r\n * @example flatten({ a: { b: 1, c: { d: 2 } } }) => { 'a.b': 1, 'a.c.d': 2 }\r\n */\r\nexport function flatten(\r\n obj: Record<string, any>,\r\n prefix = '',\r\n separator = '.'\r\n): Record<string, any> {\r\n const result: Record<string, any> = {}\r\n for (const [key, value] of Object.entries(obj)) {\r\n const newKey = prefix ? `${prefix}${separator}${key}` : key\r\n if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\r\n Object.assign(result, flatten(value, newKey, separator))\r\n } else {\r\n result[newKey] = value\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 将扁平化的对象还原为嵌套对象\r\n * @param obj 扁平化的对象\r\n * @param separator 分隔符,默认为 '.'\r\n * @example unflatten({ 'a.b': 1, 'a.c.d': 2 }) => { a: { b: 1, c: { d: 2 } } }\r\n */\r\nexport function unflatten(\r\n obj: Record<string, any>,\r\n separator = '.'\r\n): Record<string, any> {\r\n const result: Record<string, any> = {}\r\n for (const [key, value] of Object.entries(obj)) {\r\n const parts = key.split(separator)\r\n let current = result\r\n for (let i = 0; i < parts.length - 1; i++) {\r\n const k = parts[i] as string\r\n if (!(k in current)) {\r\n current[k] = {}\r\n }\r\n current = current[k]\r\n }\r\n current[parts[parts.length - 1] as string] = value\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 将 { key: label } 对象转换为 el-table-column 所需的表头数组\r\n * @param fieldMap 字段映射对象\r\n * @example toTableColumns({ id: '主键', name: '名称' }) => [{ id: 'id', label: '主键', prop: 'id' }, ...]\r\n */\r\nexport function toTableColumns(fieldMap: Record<string, string>) {\r\n return Object.entries(fieldMap).map(([key, label]) => ({\r\n id: key,\r\n label,\r\n prop: key,\r\n }))\r\n}\r\n","import type { RouteRecordRaw } from 'vue-router'\r\nimport type { BackendRoute } from './types'\r\n\r\ntype ViewModules = Record<string, () => Promise<unknown>>\r\n\r\ninterface RouteTreeNode extends BackendRoute {\r\n children?: RouteTreeNode[]\r\n}\r\n\r\nexport function getComponentImport(componentPath: string, viewModules: ViewModules): (() => Promise<unknown>) | null {\r\n if (!componentPath) return null\r\n\r\n let normalizedPath = componentPath.replace(/^@\\//, '')\r\n if (!normalizedPath.startsWith('views/')) normalizedPath = `views/${normalizedPath}`\r\n if (!normalizedPath.endsWith('.vue')) normalizedPath = `${normalizedPath}.vue`\r\n\r\n const fullPath = `/src/${normalizedPath}`\r\n\r\n return (viewModules[fullPath] ?? viewModules['/src/views/common/NotFound.vue'] ?? null) as (() => Promise<unknown>) | null\r\n}\r\n\r\nexport function buildRouteTree(routes: BackendRoute[]): RouteTreeNode[] {\r\n const routeMap = new Map<string, RouteTreeNode>()\r\n const rootRoutes: RouteTreeNode[] = []\r\n\r\n routes.forEach(route => routeMap.set(route.name, { ...route, children: [] }))\r\n\r\n routes.forEach(route => {\r\n const currentRoute = routeMap.get(route.name)!\r\n if (!route.parent_name) {\r\n rootRoutes.push(currentRoute)\r\n } else {\r\n const parentRoute = routeMap.get(route.parent_name)\r\n if (parentRoute) {\r\n parentRoute.children ??= []\r\n parentRoute.children.push(currentRoute)\r\n } else {\r\n rootRoutes.push(currentRoute)\r\n }\r\n }\r\n })\r\n return rootRoutes\r\n}\r\n\r\nexport function transformBackendRoutes(\r\n backendRoutes: RouteTreeNode[],\r\n viewModules: ViewModules,\r\n projectName?: string\r\n): RouteRecordRaw[] {\r\n return backendRoutes\r\n .filter(route => !projectName || !route.project || route.project === projectName)\r\n .map(route => {\r\n const routeConfig: Partial<RouteRecordRaw> = {\r\n path: route.path,\r\n name: route.name,\r\n meta: {\r\n requiresAuth: route.requiresAuth === 1,\r\n title: route.title,\r\n permissions: route.permissions\r\n ? route.permissions.split(',').map(p => p.trim()).filter(Boolean)\r\n : [],\r\n params: route.params\r\n ? route.params.split('&').map(p => p.trim()).filter(Boolean)\r\n : [],\r\n },\r\n }\r\n\r\n const component = getComponentImport(route.component, viewModules)\r\n if (component) routeConfig.component = component as RouteRecordRaw['component']\r\n\r\n if (route.redirect) routeConfig.redirect = route.redirect\r\n\r\n if (route.children?.length) {\r\n routeConfig.children = transformBackendRoutes(route.children, viewModules, projectName)\r\n }\r\n\r\n return routeConfig as RouteRecordRaw\r\n })\r\n}\r\n\r\nexport function findFirstAllowedRoute(\r\n backendRoutes: BackendRoute[],\r\n routePermissions: string[],\r\n layoutRouteName: string,\r\n projectName?: string\r\n): BackendRoute | undefined {\r\n const routeMap = new Map<string, BackendRoute>()\r\n backendRoutes.forEach(route => routeMap.set(route.name, route))\r\n\r\n const isDescendantOfLayout = (route: BackendRoute): boolean => {\r\n let parentName = route.parent_name\r\n const visited = new Set<string>()\r\n\r\n while (parentName) {\r\n if (parentName === layoutRouteName) return true\r\n if (visited.has(parentName)) return false\r\n\r\n visited.add(parentName)\r\n const parentRoute = routeMap.get(parentName)\r\n if (!parentRoute) return false\r\n parentName = parentRoute.parent_name\r\n }\r\n\r\n return false\r\n }\r\n\r\n return backendRoutes\r\n .filter(route =>\r\n route.name !== layoutRouteName &&\r\n route.is_show === 1 &&\r\n route.component &&\r\n routePermissions.includes(route.code) &&\r\n isDescendantOfLayout(route) &&\r\n (!projectName || !route.project || route.project === projectName)\r\n )\r\n .sort((a, b) => a.sorts - b.sorts)[0]\r\n}\r\n","import type { NavigationGuardNext, Router } from 'vue-router'\r\nimport NProgress from 'nprogress'\r\nimport 'nprogress/nprogress.css'\r\nimport { ElMessage } from 'element-plus'\r\nimport type { RouterGuardOptions } from './types'\r\nimport { buildRouteTree, transformBackendRoutes } from './helpers'\r\n\r\nNProgress.configure({ showSpinner: false })\r\n\r\nconst isDev = import.meta.env.DEV\r\nconst log = (...args: unknown[]) => { if (isDev) console.log('[Router]', ...args) }\r\nconst warn = (...args: unknown[]) => { if (isDev) console.warn('[Router]', ...args) }\r\nconst logError = (...args: unknown[]) => { console.error('[Router]', ...args) }\r\n\r\nexport function createRouterGuard(router: Router, options: RouterGuardOptions) {\r\n const {\r\n getRouteStore,\r\n getPermissionStore,\r\n getUserStore,\r\n isAuthenticated,\r\n viewModules,\r\n homeComponent,\r\n notFoundComponent,\r\n projectName,\r\n layoutRouteName = 'Layout',\r\n publicPaths = ['/login', '/register'],\r\n loginRouteName = 'login',\r\n forbiddenRouteName = 'Forbidden',\r\n homeRouteName = 'Home',\r\n homeRoutePath = 'home',\r\n homeTitle = '\\u9996\\u9875',\r\n noPermissionMessage = '\\u6682\\u65e0\\u6743\\u9650',\r\n } = options\r\n\r\n let hasAddedRoutes = false\r\n\r\n function addDynamicRoutes(backendRoutes: ReturnType<typeof getRouteStore>['backendRoutes']) {\r\n const treeRoutes = buildRouteTree(backendRoutes)\r\n const layoutRoute = treeRoutes.find(route => route.name === layoutRouteName)\r\n const childRoutes = layoutRoute?.children\r\n ? transformBackendRoutes(layoutRoute.children, viewModules, projectName)\r\n : []\r\n\r\n childRoutes.forEach(route => {\r\n if (route.name && router.hasRoute(route.name)) return\r\n router.addRoute(layoutRouteName, route)\r\n log(`Add route: ${String(route.name)} -> ${route.path}`)\r\n })\r\n\r\n if (!router.hasRoute(homeRouteName)) {\r\n router.addRoute(layoutRouteName, {\r\n path: homeRoutePath,\r\n name: homeRouteName,\r\n component: homeComponent as never,\r\n meta: { title: homeTitle },\r\n })\r\n }\r\n\r\n if (!router.hasRoute('NotFound')) {\r\n router.addRoute({\r\n path: '/:pathMatch(.*)*',\r\n name: 'NotFound',\r\n component: notFoundComponent as never,\r\n })\r\n }\r\n\r\n log(`Dynamic routes added: ${childRoutes.length}`)\r\n }\r\n\r\n function redirectToHomeOrContinue(\r\n toName: ReturnType<Router['resolve']>['name'],\r\n next: NavigationGuardNext\r\n ) {\r\n if (toName === homeRouteName) {\r\n next()\r\n return\r\n }\r\n\r\n if (router.hasRoute(homeRouteName)) {\r\n next({ name: homeRouteName, replace: true })\r\n } else {\r\n next()\r\n }\r\n }\r\n\r\n router.beforeEach(async (to, _from, next) => {\r\n NProgress.start()\r\n\r\n if (isAuthenticated() && !hasAddedRoutes) {\r\n try {\r\n const routeStore = getRouteStore()\r\n const permissionStore = getPermissionStore()\r\n\r\n await routeStore.initRoutes()\r\n await permissionStore.loadUserPermissions()\r\n\r\n addDynamicRoutes(routeStore.backendRoutes)\r\n hasAddedRoutes = true\r\n\r\n if (to.path === '/' || to.path === '') {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n if (to.name === layoutRouteName) {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n const currentRoute = routeStore.backendRoutes.find(route => route.name === to.name)\r\n if (currentRoute && !permissionStore.routePermissions.includes(currentRoute.code)) {\r\n warn('No route permission:', to.path)\r\n next({ name: forbiddenRouteName, replace: true })\r\n return\r\n }\r\n\r\n next({\r\n path: to.path,\r\n query: to.query,\r\n hash: to.hash,\r\n replace: true,\r\n })\r\n return\r\n } catch (err) {\r\n logError('Failed to load route permissions:', err)\r\n hasAddedRoutes = false\r\n await getUserStore().logout()\r\n next({ name: loginRouteName, replace: true })\r\n return\r\n }\r\n }\r\n\r\n if (publicPaths.includes(to.path)) {\r\n if (isAuthenticated()) {\r\n next({ path: '/', replace: true })\r\n } else {\r\n next()\r\n }\r\n return\r\n }\r\n\r\n if (!isAuthenticated()) {\r\n next({ name: loginRouteName, replace: true })\r\n return\r\n }\r\n\r\n const permissionStore = getPermissionStore()\r\n const routeStore = getRouteStore()\r\n\r\n if (to.name === homeRouteName) {\r\n next()\r\n return\r\n }\r\n\r\n if (permissionStore.routePermissions.length === 0) {\r\n if (to.path !== '/') {\r\n ElMessage.warning(noPermissionMessage)\r\n next({ path: '/', replace: true })\r\n } else {\r\n redirectToHomeOrContinue(to.name, next)\r\n }\r\n return\r\n }\r\n\r\n if (to.path === '/') {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n if (to.name === layoutRouteName) {\r\n redirectToHomeOrContinue(to.name, next)\r\n return\r\n }\r\n\r\n const currentRoute = routeStore.backendRoutes.find(route => route.name === to.name)\r\n if (currentRoute && !permissionStore.routePermissions.includes(currentRoute.code)) {\r\n warn('No route permission:', to.path)\r\n next({ name: forbiddenRouteName, replace: true })\r\n return\r\n }\r\n\r\n next()\r\n })\r\n\r\n router.afterEach(() => NProgress.done())\r\n\r\n return {\r\n resetRouterState: () => { hasAddedRoutes = false },\r\n }\r\n}\r\n","import type { App } from 'vue'\r\nimport { JButton } from './components/JButton'\r\nimport { JUploadImg } from './components/JUploadImg'\r\nimport { JIconRender } from './components/JIconRender'\r\nimport { JSearchHeader } from './components/JSearchHeader'\r\nimport { JImportExcel } from './components/JImportExcel'\r\nimport { JSidebar, JSideMenuItem } from './components/JSidebar'\r\nimport { JAdminLayout } from './components/JAdminLayout'\r\nimport { JProductDetailDialog, JSkuLink } from './components/JProductDetail'\r\nimport { JSearchInputDialog } from './components/JSearchInputDialog'\r\n\r\n// 组件列表,新增组件后在此处注册\r\nconst components = [\r\n JButton,\r\n JUploadImg,\r\n JIconRender,\r\n JSearchHeader,\r\n JImportExcel,\r\n JSidebar,\r\n JSideMenuItem,\r\n JAdminLayout,\r\n JProductDetailDialog,\r\n JSkuLink,\r\n JSearchInputDialog,\r\n]\r\n\r\n// 全量安装插件(app.use(JgyComponents))\r\nconst install = (app: App) => {\r\n components.forEach((component) => {\r\n app.component(component.name ?? component.__name ?? '', component)\r\n })\r\n}\r\n\r\n// 默认导出插件对象\r\nexport default { install }\r\n\r\n// 按需导出各组件\r\nexport {\r\n JButton,\r\n JUploadImg,\r\n JIconRender,\r\n JSearchHeader,\r\n JImportExcel,\r\n JSidebar,\r\n JSideMenuItem,\r\n JAdminLayout,\r\n JProductDetailDialog,\r\n JSkuLink,\r\n JSearchInputDialog,\r\n}\r\n\r\n// 导出 composable\r\nexport { useProductDetailDialog } from './components/JProductDetail'\r\n\r\n// 导出工具方法\r\nexport { toSnakeCase, toCamelCase, pick, omit, deepClone, filterEmpty, flatten, unflatten, toTableColumns } from './utils'\r\n\r\n// 导出路由工具\r\nexport { createRouterGuard, buildRouteTree, transformBackendRoutes, findFirstAllowedRoute, getComponentImport } from './router'\r\nexport type { BackendRoute, RouteStoreAdapter, PermissionStoreAdapter, UserStoreAdapter, RouterGuardOptions } from './router'\r\n\r\n// 导出类型\r\nexport type { ButtonType, ButtonSize } from './components/JButton'\r\nexport type { JUploadImgProps, JUploadImgEmits, ImageItem } from './components/JUploadImg'\r\nexport type { JIconRenderProps } from './components/JIconRender'\r\nexport type { JSearchHeaderProps } from './components/JSearchHeader'\r\nexport type { JImportExcelProps, ApiFn } from './components/JImportExcel'\r\nexport type { SidebarMenuItem, JSidebarProps, JSideMenuItemProps } from './components/JSidebar'\r\nexport type { AdminLayoutMenuItem, JAdminLayoutProps } from './components/JAdminLayout'\r\nexport type { JProductDetailDialogProps, JSkuLinkProps, JProductRequestFn, JProductRequestConfig } from './components/JProductDetail'\r\nexport type {\r\n JSearchInputDialogProps,\r\n SearchInputOption,\r\n SearchInputModel,\r\n} from './components/JSearchInputDialog'\r\n"],"names":["props","__props","emit","__emit","handleClick","event","_createElementBlock","_openBlock","_hoisted_2","$slots","_hoisted_3","_renderSlot","_ctx","imageUrl","ref","showPreview","showTipText","handlePreviewSingle","handleRemoveSingle","ElMessage","imageList","uploading","initImageList","urls","url","index","watch","val","handleDragEnd","emitMultipleUpdate","handleRemove","handleFileChange","uploadFile","file","error","item","_hoisted_1","_createVNode","_unref","draggable","$event","_withCtx","element","_createElementVNode","ElImage","img","_withModifiers","ElIcon","Delete","_createBlock","ElUpload","Loading","Plus","_Fragment","_hoisted_5","_hoisted_6","ZoomIn","ElImageViewer","_hoisted_7","_hoisted_8","_toDisplayString","_mergeProps","$attrs","formItemsRef","expanded","isAnimated","itemCount","collapsedHeight","shouldCollapse","computed","measureItems","items","lastVisibleItem","wrapperRect","lastVisibleRect","toggleExpand","el","onEnd","observer","onMounted","onBeforeUnmount","ElCard","ElForm","_normalizeClass","ElButton","Search","_cache","Refresh","_createTextVNode","ArrowDown","visible","_useModel","submitting","fieldMap","renderData","stats","statusMap","dataColumns","key","label","handleOpen","res","raw","reader","e","workbook","XLSX","wsName","ws","dataRows","row","cell","list","col","handleDel","idx","handleConfirm","data","_status","_error","rest","r","handleDownloadTemplate","wb","headers","tr","h","handleClose","ElDialog","ElDivider","ElLink","ElRow","ElCol","_hoisted_4","ElTable","_renderList","ElTableColumn","$index","ElSubMenu","JIconRender","child","_component_JSideMenuItem","ElMenuItem","innerCollapsed","toggleCollapse","_normalizeStyle","_a","ElMenu","route","JSideMenuItem","value","layoutStyle","handleTopMenuSelect","path","handleSideMenuClick","JSidebar","sidebarCollapsed","toggle","menu","ElDropdown","ElDropdownMenu","ElDropdownItem","brandDict","unitDict","saleDict","companyDict","tagDict","customAttrDict","dictsLoaded","dictsPromise","loadDicts","request","post","_b","_c","loading","detail","fetchDetail","params","basic","spec","images","purchase","declaration","qc","bindSku","spuBindSku","specBoxList","supplierList","productType","isSpu","productTypeLabel","nameCn","nameEn","mainCode","normalizeStringArray","v","s","arr","x","normalizeAttachments","it","f","fmt","weightText","unit","dimText","l","w","p","dictName","id","hit","brandName","unitName","statusName","declarationUnitName","peNames","codes","tagList","code","t","skuAttrText","attr","k","basicAttachments","hasDesc","html","mainImage","sizeImages","sellingPointImages","qcMethodLabel","qcImages","qcAttachments","qcCustomList","dictAttrId","parseAttrOptions","out","name","customAttrDictMap","m","d","customAttrList","info","def","customAttrValueText","values","options","o","bindSkuList","styleAttrs","skuVariants","variantAttrText","c","supplierQuoteRows","sup","rows","q","_withDirectives","ElDescriptions","ElDescriptionsItem","ElTag","i","_d","si","_hoisted_9","_hoisted_10","_hoisted_15","ElEmpty","displayText","hasCode","useProductDetailDialog","productDetailDialogVisible","productDetailDialogCode","sku","type","keyword","dialogVisible","textareaValue","currentOption","dialogTitleText","normalizeKeywords","parts","unique","seen","part","keywordToTextarea","openDialog","handleDialogClosed","next","prev","__expose","defaultType","_component_el_input","_component_el_select","_component_el_option","_component_el_button","Memo","_component_el_dialog","deepTransformValue","transformer","toSnakeCase","obj","excludeKeys","newValue","toCamelCase","_","char","pick","keys","result","omit","deepClone","cloned","filterEmpty","deep","filtered","flatten","prefix","separator","newKey","unflatten","current","toTableColumns","getComponentImport","componentPath","viewModules","normalizedPath","fullPath","buildRouteTree","routes","routeMap","rootRoutes","currentRoute","parentRoute","transformBackendRoutes","backendRoutes","projectName","routeConfig","component","findFirstAllowedRoute","routePermissions","layoutRouteName","isDescendantOfLayout","parentName","visited","a","b","NProgress","log","args","warn","logError","createRouterGuard","router","getRouteStore","getPermissionStore","getUserStore","isAuthenticated","homeComponent","notFoundComponent","publicPaths","loginRouteName","forbiddenRouteName","homeRouteName","homeRoutePath","homeTitle","noPermissionMessage","hasAddedRoutes","addDynamicRoutes","layoutRoute","childRoutes","redirectToHomeOrContinue","toName","to","_from","routeStore","permissionStore","err","components","JButton","JUploadImg","JSearchHeader","JImportExcel","JAdminLayout","JProductDetailDialog","JSkuLink","JSearchInputDialog","app"],"mappings":"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"}