@robot-admin/naive-ui-components 0.3.1 → 0.3.3
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.
- package/dist/C_ActionBar-nnfbZCea.css.map +1 -0
- package/dist/C_ActionBar2.js +2 -2
- package/dist/C_ActionBar2.js.map +1 -1
- package/dist/C_AntV-DGjscTWa.css.map +1 -0
- package/dist/C_AntV2.js +6 -6
- package/dist/C_AntV2.js.map +1 -1
- package/dist/C_Barcode-DjTmDkbQ.css.map +1 -0
- package/dist/C_Barcode2.js +1 -1
- package/dist/C_Barcode2.js.map +1 -1
- package/dist/C_Captcha-Ccq3DMrR.css.map +1 -0
- package/dist/C_Captcha2.js +1 -1
- package/dist/C_Captcha2.js.map +1 -1
- package/dist/C_Cascade-IUUHIh7r.css.map +1 -0
- package/dist/C_Cascade2.js +2 -2
- package/dist/C_Cascade2.js.map +1 -1
- package/dist/C_City-Cv5BESaN.css.map +1 -0
- package/dist/C_City2.js +2 -2
- package/dist/C_City2.js.map +1 -1
- package/dist/C_Code-DPZlNSxL.css.map +1 -0
- package/dist/C_Code2.js +8 -7
- package/dist/C_Code2.js.map +1 -1
- package/dist/C_CollapsePanel-Fap-lv_5.css.map +1 -0
- package/dist/C_CollapsePanel2.js +1 -1
- package/dist/C_CollapsePanel2.js.map +1 -1
- package/dist/C_Cron-C0-8b5af.css.map +1 -0
- package/dist/C_Cron2.js +15 -14
- package/dist/C_Cron2.js.map +1 -1
- package/dist/C_Date2.js +1 -1
- package/dist/C_Date2.js.map +1 -1
- package/dist/C_Draggable-Bq6o0qXn.css.map +1 -0
- package/dist/C_Draggable2.js +1 -1
- package/dist/C_Draggable2.js.map +1 -1
- package/dist/C_Editor-OlxIF9-5.css.map +1 -0
- package/dist/C_Editor2.js +1 -1
- package/dist/C_Editor2.js.map +1 -1
- package/dist/C_FilePreview-B4XgTv-h.css.map +1 -0
- package/dist/C_FilePreview.cjs +1 -0
- package/dist/C_FilePreview.js +1 -0
- package/dist/C_FilePreview2.js +10 -9
- package/dist/C_FilePreview2.js.map +1 -1
- package/dist/C_Form-Cr9oX037.css.map +1 -0
- package/dist/C_Form.cjs +1 -0
- package/dist/C_Form.js +1 -0
- package/dist/C_Form2.js +69 -72
- package/dist/C_Form2.js.map +1 -1
- package/dist/C_FormSearch-DlIEoh7X.css.map +1 -0
- package/dist/C_FormSearch2.js +2 -2
- package/dist/C_FormSearch2.js.map +1 -1
- package/dist/C_FormulaEditor-Cm0CokN5.css.map +1 -0
- package/dist/C_FormulaEditor2.js +6 -6
- package/dist/C_FormulaEditor2.js.map +1 -1
- package/dist/C_FullCalendar-BULCIlVK.css.map +1 -0
- package/dist/C_FullCalendar2.js +2 -2
- package/dist/C_FullCalendar2.js.map +1 -1
- package/dist/C_Guide2.js +1 -1
- package/dist/C_Guide2.js.map +1 -1
- package/dist/C_Icon2.js.map +1 -1
- package/dist/C_ImageCropper-DrmUlaLi.css.map +1 -0
- package/dist/C_ImageCropper2.js +4 -4
- package/dist/C_ImageCropper2.js.map +1 -1
- package/dist/C_Language2.js +1 -1
- package/dist/C_Language2.js.map +1 -1
- package/dist/C_Map-WUMXSAfy.css.map +1 -0
- package/dist/C_Map2.js +2 -2
- package/dist/C_Map2.js.map +1 -1
- package/dist/C_Markdown-Dmv8yaM4.css.map +1 -0
- package/dist/C_Markdown2.js +4 -4
- package/dist/C_Markdown2.js.map +1 -1
- package/dist/C_NotificationCenter-DbgBiyqB.css.map +1 -0
- package/dist/C_NotificationCenter2.js +21 -20
- package/dist/C_NotificationCenter2.js.map +1 -1
- package/dist/C_Progress2.js +1 -1
- package/dist/C_Progress2.js.map +1 -1
- package/dist/C_QRCode-G7fiAkm4.css.map +1 -0
- package/dist/C_QRCode2.js +1 -1
- package/dist/C_QRCode2.js.map +1 -1
- package/dist/C_Signature-es-ZNPzr.css.map +1 -0
- package/dist/C_Signature2.js +2 -2
- package/dist/C_Signature2.js.map +1 -1
- package/dist/C_SplitPane-Br2eK8IG.css.map +1 -0
- package/dist/C_SplitPane2.js +1 -1
- package/dist/C_SplitPane2.js.map +1 -1
- package/dist/C_Steps-P9Qj9iDd.css.map +1 -0
- package/dist/C_Steps2.js +1 -1
- package/dist/C_Steps2.js.map +1 -1
- package/dist/C_Table-DAwAxr72.css.map +1 -0
- package/dist/C_Table.cjs +1 -0
- package/dist/C_Table.js +1 -0
- package/dist/C_Table2.js +3 -3
- package/dist/C_Table2.js.map +1 -1
- package/dist/C_Theme2.js +1 -1
- package/dist/C_Theme2.js.map +1 -1
- package/dist/C_Time-Bd_e1YDN.css.map +1 -0
- package/dist/C_Time2.js +2 -2
- package/dist/C_Time2.js.map +1 -1
- package/dist/C_Tree-DnGc_MPb.css.map +1 -0
- package/dist/C_Tree2.js +2 -2
- package/dist/C_Tree2.js.map +1 -1
- package/dist/C_Upload-i8LB_29U.css.map +1 -0
- package/dist/C_Upload2.js +5 -5
- package/dist/C_Upload2.js.map +1 -1
- package/dist/C_VideoPlayer-rm0MODUv.css.map +1 -0
- package/dist/C_VideoPlayer2.js +21 -20
- package/dist/C_VideoPlayer2.js.map +1 -1
- package/dist/C_VtableGantt-BpY-Rng3.css.map +1 -0
- package/dist/C_VtableGantt2.js +2 -2
- package/dist/C_VtableGantt2.js.map +1 -1
- package/dist/C_WaterFall-HWB-gPON.css.map +1 -0
- package/dist/C_WaterFall2.js +2 -2
- package/dist/C_WaterFall2.js.map +1 -1
- package/dist/C_WorkFlow-CSO86Cuc.css.map +1 -0
- package/dist/C_WorkFlow2.js +6 -6
- package/dist/C_WorkFlow2.js.map +1 -1
- package/dist/constants.d.ts +4 -4
- package/dist/constants2.d.ts +4 -4
- package/dist/constants3.d.ts +4 -4
- package/dist/constants4.d.ts +5 -5
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.vue.d.ts +1 -1
- package/dist/index10.vue.d.ts +7 -7
- package/dist/index11.vue.d.ts +2 -2
- package/dist/index12.vue.d.ts +5 -5
- package/dist/index12.vue.d.ts.map +1 -1
- package/dist/index13.vue.d.ts +1 -1
- package/dist/index14.vue.d.ts +1 -1
- package/dist/index16.vue.d.ts +1 -1
- package/dist/index2.vue.d.ts +6 -6
- package/dist/index3.vue.d.ts +2 -2
- package/dist/index4.vue.d.ts +2 -2
- package/dist/index5.vue.d.ts +2 -2
- package/dist/index6.vue.d.ts +1 -1
- package/dist/index8.vue.d.ts +3 -3
- package/dist/resolver.js.map +1 -1
- package/dist/style.css +1555 -1555
- package/dist/useCalendarEvents.d.ts +2 -2
- package/dist/useCollapsePanel.d.ts +2 -2
- package/dist/useCropperCore.d.ts +3 -3
- package/dist/useDraggableLayout.d.ts +8 -8
- package/dist/useDynamicFormState.d.ts +111 -111
- package/dist/useDynamicFormState.d.ts.map +1 -1
- package/dist/useEdgeInteraction.d.ts +2 -2
- package/dist/useInfiniteScroll.d.ts +1 -1
- package/dist/useModalEdit.d.ts +4 -4
- package/dist/useModalEdit.d.ts.map +1 -1
- package/dist/useQRCode.d.ts +4 -4
- package/dist/useQRCode.d.ts.map +1 -1
- package/dist/useSearchState.d.ts +2 -2
- package/dist/useSignatureHistory.d.ts +4 -4
- package/dist/useSplitResize.d.ts +6 -6
- package/dist/useSplitResize.d.ts.map +1 -1
- package/dist/useTimeSelection.d.ts +2 -2
- package/dist/useTreeOperations.d.ts +6 -6
- package/dist/useWorkflowValidation.d.ts +5 -5
- package/package.json +2 -1
- package/dist/C_ActionBar-DWN-woTc.css.map +0 -1
- package/dist/C_AntV-AFKyK6hH.css.map +0 -1
- package/dist/C_Barcode-P_EFj8dC.css.map +0 -1
- package/dist/C_Captcha-C-ef41xw.css.map +0 -1
- package/dist/C_Cascade-D9kNsjsV.css.map +0 -1
- package/dist/C_City-BCQ4ipiK.css.map +0 -1
- package/dist/C_Code-C9kvvEmO.css.map +0 -1
- package/dist/C_CollapsePanel-BUJHuYcU.css.map +0 -1
- package/dist/C_Cron-yx2Ob4Jl.css.map +0 -1
- package/dist/C_Draggable-C483syRC.css.map +0 -1
- package/dist/C_Editor-Bp0SyIEw.css.map +0 -1
- package/dist/C_FilePreview-CPqvhoCy.css.map +0 -1
- package/dist/C_Form-Jx7PY3sT.css.map +0 -1
- package/dist/C_FormSearch-DvRgxlRn.css.map +0 -1
- package/dist/C_FormulaEditor-DtGkt4T_.css.map +0 -1
- package/dist/C_FullCalendar-BF7H0YIx.css.map +0 -1
- package/dist/C_ImageCropper-BVJfUufl.css.map +0 -1
- package/dist/C_Map-DpzeuWdX.css.map +0 -1
- package/dist/C_Markdown-BEjxknqd.css.map +0 -1
- package/dist/C_NotificationCenter-0l3TY2Gn.css.map +0 -1
- package/dist/C_QRCode-DbdiAIPg.css.map +0 -1
- package/dist/C_Signature-zhHCbra9.css.map +0 -1
- package/dist/C_SplitPane-C6sBsfKY.css.map +0 -1
- package/dist/C_Steps-CODHN5Hs.css.map +0 -1
- package/dist/C_Table-DSNsntmT.css.map +0 -1
- package/dist/C_Time-BvZLYraL.css.map +0 -1
- package/dist/C_Tree-0GDv--jX.css.map +0 -1
- package/dist/C_Upload-BXd3YYLx.css.map +0 -1
- package/dist/C_VideoPlayer-DYG3RL0Q.css.map +0 -1
- package/dist/C_VtableGantt-fhItIiHE.css.map +0 -1
- package/dist/C_WaterFall-8sQDFXKg.css.map +0 -1
- package/dist/C_WorkFlow-J-dyIuh9.css.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_Barcode-DjTmDkbQ.css","names":[],"sources":["../src/components/C_Barcode/index.vue?vue&type=style&index=0&scoped=e44c361d&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-barcode[data-v-e44c361d] {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper[data-v-e44c361d] {\n display: inline-block;\n padding: 8px;\n background: #ffffff;\n border-radius: 4px;\n transition: all 0.3s ease;\n overflow: hidden;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper.with-border[data-v-e44c361d] {\n border: 1px dashed #e0e0e0;\n}\n.c-barcode .barcode-wrapper[data-v-e44c361d]:hover {\n border-color: var(--c-primary, #409eff);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.c-barcode .barcode-wrapper[data-v-e44c361d] svg {\n max-width: 100%;\n height: auto;\n display: block;\n overflow: visible;\n}\n.c-barcode .barcode-label[data-v-e44c361d] {\n font-size: 14px;\n color: #666;\n text-align: center;\n font-weight: 500;\n word-break: break-all;\n max-width: 100%;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Barcode2.js
CHANGED
|
@@ -61,7 +61,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
61
61
|
|
|
62
62
|
//#endregion
|
|
63
63
|
//#region src/components/C_Barcode/index.vue
|
|
64
|
-
var C_Barcode_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
64
|
+
var C_Barcode_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e44c361d"]]);
|
|
65
65
|
|
|
66
66
|
//#endregion
|
|
67
67
|
export { C_Barcode_default as t };
|
package/dist/C_Barcode2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Barcode2.js","names":["showBorder","showLabel","label"],"sources":["../src/components/C_Barcode/index.vue","../src/components/C_Barcode/index.vue","../src/components/C_Barcode/index.vue"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"C_Barcode2.js","names":["showBorder","showLabel","label"],"sources":["../src/components/C_Barcode/index.vue","../src/components/C_Barcode/index.vue","../src/components/C_Barcode/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-12-02\r\n * @Description: 条形码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-barcode\">\r\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\r\n\r\ndefineOptions({ name: \"C_Barcode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n format?:\r\n | \"CODE128\"\r\n | \"CODE39\"\r\n | \"EAN13\"\r\n | \"EAN8\"\r\n | \"UPC\"\r\n | \"ITF14\"\r\n | \"MSI\"\r\n | \"pharmacode\";\r\n width?: number;\r\n height?: number;\r\n showText?: boolean;\r\n fontSize?: number;\r\n textPosition?: \"bottom\" | \"top\";\r\n lineColor?: string;\r\n background?: string;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n format: \"CODE128\",\r\n width: 2,\r\n height: 80,\r\n showText: true,\r\n fontSize: 20,\r\n textPosition: \"bottom\",\r\n lineColor: \"#000000\",\r\n background: \"#FFFFFF\",\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst barcodeProps = computed(() => ({\r\n value: props.value,\r\n format: props.format,\r\n width: props.width,\r\n height: props.height,\r\n displayValue: props.showText,\r\n fontSize: props.fontSize,\r\n textPosition: props.textPosition,\r\n lineColor: props.lineColor,\r\n background: props.background,\r\n}));\r\n\r\nconst handleError = (error: Error) => {\r\n console.error(\"条形码生成失败:\", error);\r\n emit(\"error\", error);\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-12-02\r\n * @Description: 条形码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-barcode\">\r\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\r\n\r\ndefineOptions({ name: \"C_Barcode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n format?:\r\n | \"CODE128\"\r\n | \"CODE39\"\r\n | \"EAN13\"\r\n | \"EAN8\"\r\n | \"UPC\"\r\n | \"ITF14\"\r\n | \"MSI\"\r\n | \"pharmacode\";\r\n width?: number;\r\n height?: number;\r\n showText?: boolean;\r\n fontSize?: number;\r\n textPosition?: \"bottom\" | \"top\";\r\n lineColor?: string;\r\n background?: string;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n format: \"CODE128\",\r\n width: 2,\r\n height: 80,\r\n showText: true,\r\n fontSize: 20,\r\n textPosition: \"bottom\",\r\n lineColor: \"#000000\",\r\n background: \"#FFFFFF\",\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst barcodeProps = computed(() => ({\r\n value: props.value,\r\n format: props.format,\r\n width: props.width,\r\n height: props.height,\r\n displayValue: props.showText,\r\n fontSize: props.fontSize,\r\n textPosition: props.textPosition,\r\n lineColor: props.lineColor,\r\n background: props.background,\r\n}));\r\n\r\nconst handleError = (error: Error) => {\r\n console.error(\"条形码生成失败:\", error);\r\n emit(\"error\", error);\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-12-02\r\n * @Description: 条形码组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-barcode\">\r\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\r\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\r\n </div>\r\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\r\n {{ label }}\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\r\n\r\ndefineOptions({ name: \"C_Barcode\" });\r\n\r\ninterface Props {\r\n value: string;\r\n format?:\r\n | \"CODE128\"\r\n | \"CODE39\"\r\n | \"EAN13\"\r\n | \"EAN8\"\r\n | \"UPC\"\r\n | \"ITF14\"\r\n | \"MSI\"\r\n | \"pharmacode\";\r\n width?: number;\r\n height?: number;\r\n showText?: boolean;\r\n fontSize?: number;\r\n textPosition?: \"bottom\" | \"top\";\r\n lineColor?: string;\r\n background?: string;\r\n showBorder?: boolean;\r\n label?: string;\r\n showLabel?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n format: \"CODE128\",\r\n width: 2,\r\n height: 80,\r\n showText: true,\r\n fontSize: 20,\r\n textPosition: \"bottom\",\r\n lineColor: \"#000000\",\r\n background: \"#FFFFFF\",\r\n showBorder: true,\r\n label: \"\",\r\n showLabel: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n error: [error: Error];\r\n}>();\r\n\r\nconst barcodeProps = computed(() => ({\r\n value: props.value,\r\n format: props.format,\r\n width: props.width,\r\n height: props.height,\r\n displayValue: props.showText,\r\n fontSize: props.fontSize,\r\n textPosition: props.textPosition,\r\n lineColor: props.lineColor,\r\n background: props.background,\r\n}));\r\n\r\nconst handleError = (error: Error) => {\r\n console.error(\"条形码生成失败:\", error);\r\n emit(\"error\", error);\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC+CA,MAAM,QAAQ;EAcd,MAAM,OAAO;EAIb,MAAM,eAAe,gBAAgB;GACnC,OAAO,MAAM;GACb,QAAQ,MAAM;GACd,OAAO,MAAM;GACb,QAAQ,MAAM;GACd,cAAc,MAAM;GACpB,UAAU,MAAM;GAChB,cAAc,MAAM;GACpB,WAAW,MAAM;GACjB,YAAY,MAAM;GACnB,EAAE;EAEH,MAAM,eAAe,UAAiB;AACpC,WAAQ,MAAM,YAAY,MAAM;AAChC,QAAK,SAAS,MAAM;;;uBAvEpB,mBAOM,OAPN,YAOM,CANJ,mBAEM,OAAA,EAFD,OAAK,eAAA,CAAC,mBAAiB,EAAA,eAA0BA,KAAAA,YAAU,CAAA,CAAA,KAC9D,YAAyD,MAAA,WAAA,EAAzD,WAAoB,aAAqC,OAAzB,EAAG,SAAO,aAAW,CAAA,EAAA,MAAA,GAAA,OAE5CC,KAAAA,aAAaC,KAAAA,sBAAxB,mBAEM,OAFN,YAEM,gBADDA,KAAAA,MAAK,EAAA,EAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_Captcha-Ccq3DMrR.css","names":[],"sources":["../src/components/C_Captcha/index.vue?vue&type=style&index=0&scoped=74f1f0d1&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-captcha-modern[data-v-74f1f0d1] {\n width: 100%;\n font-family: inherit;\n}\n.captcha-trigger[data-v-74f1f0d1] {\n width: 100%;\n max-width: 280px;\n margin: 0 auto;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.captcha-trigger[data-v-74f1f0d1]:hover:not(.disabled) {\n transform: translateY(-1px);\n}\n.captcha-trigger.disabled[data-v-74f1f0d1] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.captcha-content[data-v-74f1f0d1] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex: 1;\n}\n.captcha-icon[data-v-74f1f0d1] {\n font-size: 18px;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.captcha-text[data-v-74f1f0d1] {\n color: rgba(255, 255, 255, 0.8);\n font-size: 14px;\n font-weight: 500;\n letter-spacing: 0.3px;\n text-align: center;\n white-space: nowrap;\n}\n.refresh-button[data-v-74f1f0d1] {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.3s ease;\n color: rgba(255, 255, 255, 0.6);\n font-size: 14px;\n flex-shrink: 0;\n}\n.refresh-button[data-v-74f1f0d1]:hover {\n color: rgba(255, 255, 255, 0.9);\n transform: translateY(-50%) rotate(180deg);\n}\n.success-icon[data-v-74f1f0d1],\n.success-text[data-v-74f1f0d1] {\n color: #43c23a;\n}\n.error-icon[data-v-74f1f0d1],\n.error-text[data-v-74f1f0d1] {\n color: #f56c6c;\n}\n@keyframes shake-74f1f0d1 {\n0%, 100% {\n transform: translateX(0);\n}\n25% {\n transform: translateX(-4px);\n}\n75% {\n transform: translateX(4px);\n}\n}\n@media (max-width: 768px) {\n.captcha-trigger[data-v-74f1f0d1] {\n max-width: 240px;\n padding: 10px 14px;\n}\n.captcha-icon[data-v-74f1f0d1] {\n font-size: 16px;\n width: 18px;\n height: 18px;\n}\n.captcha-text[data-v-74f1f0d1] {\n font-size: 13px;\n}\n.refresh-button[data-v-74f1f0d1] {\n width: 24px;\n height: 24px;\n font-size: 12px;\n right: 10px;\n}\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Captcha2.js
CHANGED
|
@@ -148,7 +148,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
148
148
|
|
|
149
149
|
//#endregion
|
|
150
150
|
//#region src/components/C_Captcha/index.vue
|
|
151
|
-
var C_Captcha_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
151
|
+
var C_Captcha_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-74f1f0d1"]]);
|
|
152
152
|
|
|
153
153
|
//#endregion
|
|
154
154
|
export { C_Captcha_default as t };
|
package/dist/C_Captcha2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Captcha2.js","names":["disabled","triggerText"],"sources":["../src/components/C_Captcha/index.vue","../src/components/C_Captcha/index.vue","../src/components/C_Captcha/index.vue"],"sourcesContent":["<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECqEA,MAAM,QAAQ;EAOd,MAAM,OAAO;EAEb,MAAM,YAAY,IAAI,MAAM;EAC5B,MAAM,aAAa,IAAI,MAAM;EAC7B,MAAM,WAAW,IAAI,MAAM;EAC3B,MAAM,oBAAoB,IAAI,GAAG;EACjC,IAAI,aAAmD;EAEvD,MAAM,gBAAgB,eACpB,MAAM,OAAO,SAAS,IAAI,MAAM,SAAS,OAC1C;EAED,MAAM,oBAAoB;AACxB,OAAI,MAAM,YAAY,WAAW,MAAO;AACxC,YAAS,QAAQ;AACjB,aAAU,QAAQ;;EAGpB,MAAM,sBAAsB;AAC1B,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;GAClB,MAAM,YAAY,KAAK,KAAK;GAC5B,MAAM,QAAQ,UAAU,UAAU,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,UAAU,GAAG,EAAE;AAC/E,qBAAkB,QAAQ;AAC1B,QAAK,WAAW;IAAE;IAAO;IAAW,CAAC;AACrC,QAAK,UAAU,KAAK;;EAGtB,MAAM,mBAAmB;AACvB,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;AAClB,OAAI,WAAY,cAAa,WAAW;AACxC,gBAAa,iBAAiB;AAC5B,aAAS,QAAQ;AACjB,iBAAa;MACZ,IAAK;AACR,QAAK,QAAQ,SAAS;AACtB,QAAK,UAAU,MAAM;;EAGvB,MAAM,oBAAoB;AACxB,aAAU,QAAQ;;EAGpB,MAAM,qBAAqB;AACzB,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;AAClB,qBAAkB,QAAQ;AAC1B,OAAI,YAAY;AACd,iBAAa,WAAW;AACxB,iBAAa;;AAEf,QAAK,QAAQ;AACb,QAAK,UAAU,MAAM;;AAGvB,WAAa;GACX,gBAAgB,WAAW;GAC3B,gBAAgB,kBAAkB;GAClC,2BAA2B;AACzB,QAAI,CAAC,WAAW,MAAO,QAAO;AAC9B,WAAO;KACL,OAAO,kBAAkB;KACzB,WAAW,KAAK,KAAK;KACrB,MAAM;KACP;;GAEH,OAAO;GACP,MAAM;GACP,CAAC;AAEF,wBAAsB;AACpB,OAAI,WAAY,cAAa,WAAW;IACxC;;uBAhJA,mBAsCM,OAtCN,YAsCM,CArCJ,mBA6BM,OAAA;IA5BJ,OAAK,eAAA,CAAC,mBAAiB;eAEM,WAAA;YAA4B,SAAA;eAA6BA,KAAAA;;IADrF,SAAO;OAOR,mBAWM,OAXN,YAWM,CAVJ,mBAIM,OAJN,YAIM;KAHS,WAAA,SAAU,CAAK,SAAA,sBAA5B,mBAA+C,QAAA,YAAT,KAAE;IAC5B,WAAA,sBAAZ,mBAAqD,QAArD,YAA6C,IAAC;IAClC,SAAA,sBAAZ,mBAAkD,QAAlD,YAAyC,KAAE;OAE7C,mBAIM,OAJN,YAIM;KAHS,WAAA,SAAU,CAAK,SAAA,sBAA5B,mBAA8D,QAAA,YAAA,gBAArBC,KAAAA,YAAW,EAAA,EAAA;IACxC,WAAA,sBAAZ,mBAAwD,QAAxD,YAA6C,OAAI;IACrC,SAAA,sBAAZ,mBAAwD,QAAxD,aAAyC,WAAQ;SAI7C,WAAA,SAAc,SAAA,sBADtB,mBAOM,OAAA;;IALJ,OAAM;IACL,SAAK,cAAO,cAAY,CAAA,OAAA,CAAA;IACzB,OAAM;MACP,MAED,2CAEF,YAME,MAAA,YAAA,EAAA;IALC,MAAM,UAAA;IACN,MAAM,cAAA;IACN,WAAS;IACT,SAAO;IACP,QAAM"}
|
|
1
|
+
{"version":3,"file":"C_Captcha2.js","names":["disabled","triggerText"],"sources":["../src/components/C_Captcha/index.vue","../src/components/C_Captcha/index.vue","../src/components/C_Captcha/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-07-23\r\n * @Description: 基于 vue3-puzzle-vcode 封装的验证器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-captcha-modern\">\r\n <div\r\n class=\"captcha-trigger\"\r\n @click=\"showCaptcha\"\r\n :class=\"{\r\n verified: isVerified,\r\n error: hasError,\r\n disabled: disabled,\r\n }\"\r\n >\r\n <div class=\"captcha-content\">\r\n <div class=\"captcha-icon\">\r\n <span v-if=\"!isVerified && !hasError\">🧩</span>\r\n <span v-if=\"isVerified\" class=\"success-icon\">✓</span>\r\n <span v-if=\"hasError\" class=\"error-icon\">⚠️</span>\r\n </div>\r\n <div class=\"captcha-text\">\r\n <span v-if=\"!isVerified && !hasError\">{{ triggerText }}</span>\r\n <span v-if=\"isVerified\" class=\"success-text\">验证成功</span>\r\n <span v-if=\"hasError\" class=\"error-text\">验证失败,请重试</span>\r\n </div>\r\n </div>\r\n <div\r\n v-if=\"isVerified || hasError\"\r\n class=\"refresh-button\"\r\n @click.stop=\"resetCaptcha\"\r\n title=\"重新验证\"\r\n >\r\n ⟲\r\n </div>\r\n </div>\r\n <PuzzleVcode\r\n :show=\"showModal\"\r\n :imgs=\"captchaImages\"\r\n @success=\"handleSuccess\"\r\n @close=\"handleClose\"\r\n @fail=\"handleFail\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onBeforeUnmount } from \"vue\";\r\nimport PuzzleVcode from \"vue3-puzzle-vcode\";\r\n\r\ndefineOptions({ name: \"C_Captcha\" });\r\n\r\ninterface CaptchaProps {\r\n triggerText?: string;\r\n images?: string[];\r\n disabled?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\ninterface CaptchaEmits {\r\n (e: \"success\", data: { token: string; timestamp: number }): void;\r\n (e: \"fail\", error: string): void;\r\n (e: \"change\", valid: boolean): void;\r\n (e: \"reset\"): void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<CaptchaProps>(), {\r\n triggerText: \"点击进行人机验证\",\r\n images: () => [],\r\n disabled: false,\r\n theme: \"dark\",\r\n});\r\n\r\nconst emit = defineEmits<CaptchaEmits>();\r\n\r\nconst showModal = ref(false);\r\nconst isVerified = ref(false);\r\nconst hasError = ref(false);\r\nconst verificationToken = ref(\"\");\r\nlet errorTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\nconst captchaImages = computed(() =>\r\n props.images.length > 0 ? props.images : undefined,\r\n);\r\n\r\nconst showCaptcha = () => {\r\n if (props.disabled || isVerified.value) return;\r\n hasError.value = false;\r\n showModal.value = true;\r\n};\r\n\r\nconst handleSuccess = () => {\r\n isVerified.value = true;\r\n hasError.value = false;\r\n showModal.value = false;\r\n const timestamp = Date.now();\r\n const token = `puzzle_${timestamp}_${Math.random().toString(36).substring(2, 9)}`;\r\n verificationToken.value = token;\r\n emit(\"success\", { token, timestamp });\r\n emit(\"change\", true);\r\n};\r\n\r\nconst handleFail = () => {\r\n isVerified.value = false;\r\n hasError.value = true;\r\n showModal.value = false;\r\n if (errorTimer) clearTimeout(errorTimer);\r\n errorTimer = setTimeout(() => {\r\n hasError.value = false;\r\n errorTimer = null;\r\n }, 3000);\r\n emit(\"fail\", \"拼图验证失败\");\r\n emit(\"change\", false);\r\n};\r\n\r\nconst handleClose = () => {\r\n showModal.value = false;\r\n};\r\n\r\nconst resetCaptcha = () => {\r\n isVerified.value = false;\r\n hasError.value = false;\r\n showModal.value = false;\r\n verificationToken.value = \"\";\r\n if (errorTimer) {\r\n clearTimeout(errorTimer);\r\n errorTimer = null;\r\n }\r\n emit(\"reset\");\r\n emit(\"change\", false);\r\n};\r\n\r\ndefineExpose({\r\n validate: () => isVerified.value,\r\n getToken: () => verificationToken.value,\r\n getVerificationData: () => {\r\n if (!isVerified.value) return null;\r\n return {\r\n token: verificationToken.value,\r\n timestamp: Date.now(),\r\n type: \"puzzle-captcha\",\r\n };\r\n },\r\n reset: resetCaptcha,\r\n show: showCaptcha,\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n if (errorTimer) clearTimeout(errorTimer);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECqEA,MAAM,QAAQ;EAOd,MAAM,OAAO;EAEb,MAAM,YAAY,IAAI,MAAM;EAC5B,MAAM,aAAa,IAAI,MAAM;EAC7B,MAAM,WAAW,IAAI,MAAM;EAC3B,MAAM,oBAAoB,IAAI,GAAG;EACjC,IAAI,aAAmD;EAEvD,MAAM,gBAAgB,eACpB,MAAM,OAAO,SAAS,IAAI,MAAM,SAAS,OAC1C;EAED,MAAM,oBAAoB;AACxB,OAAI,MAAM,YAAY,WAAW,MAAO;AACxC,YAAS,QAAQ;AACjB,aAAU,QAAQ;;EAGpB,MAAM,sBAAsB;AAC1B,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;GAClB,MAAM,YAAY,KAAK,KAAK;GAC5B,MAAM,QAAQ,UAAU,UAAU,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,UAAU,GAAG,EAAE;AAC/E,qBAAkB,QAAQ;AAC1B,QAAK,WAAW;IAAE;IAAO;IAAW,CAAC;AACrC,QAAK,UAAU,KAAK;;EAGtB,MAAM,mBAAmB;AACvB,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;AAClB,OAAI,WAAY,cAAa,WAAW;AACxC,gBAAa,iBAAiB;AAC5B,aAAS,QAAQ;AACjB,iBAAa;MACZ,IAAK;AACR,QAAK,QAAQ,SAAS;AACtB,QAAK,UAAU,MAAM;;EAGvB,MAAM,oBAAoB;AACxB,aAAU,QAAQ;;EAGpB,MAAM,qBAAqB;AACzB,cAAW,QAAQ;AACnB,YAAS,QAAQ;AACjB,aAAU,QAAQ;AAClB,qBAAkB,QAAQ;AAC1B,OAAI,YAAY;AACd,iBAAa,WAAW;AACxB,iBAAa;;AAEf,QAAK,QAAQ;AACb,QAAK,UAAU,MAAM;;AAGvB,WAAa;GACX,gBAAgB,WAAW;GAC3B,gBAAgB,kBAAkB;GAClC,2BAA2B;AACzB,QAAI,CAAC,WAAW,MAAO,QAAO;AAC9B,WAAO;KACL,OAAO,kBAAkB;KACzB,WAAW,KAAK,KAAK;KACrB,MAAM;KACP;;GAEH,OAAO;GACP,MAAM;GACP,CAAC;AAEF,wBAAsB;AACpB,OAAI,WAAY,cAAa,WAAW;IACxC;;uBAhJA,mBAsCM,OAtCN,YAsCM,CArCJ,mBA6BM,OAAA;IA5BJ,OAAK,eAAA,CAAC,mBAAiB;eAEM,WAAA;YAA4B,SAAA;eAA6BA,KAAAA;;IADrF,SAAO;OAOR,mBAWM,OAXN,YAWM,CAVJ,mBAIM,OAJN,YAIM;KAHS,WAAA,SAAU,CAAK,SAAA,sBAA5B,mBAA+C,QAAA,YAAT,KAAE;IAC5B,WAAA,sBAAZ,mBAAqD,QAArD,YAA6C,IAAC;IAClC,SAAA,sBAAZ,mBAAkD,QAAlD,YAAyC,KAAE;OAE7C,mBAIM,OAJN,YAIM;KAHS,WAAA,SAAU,CAAK,SAAA,sBAA5B,mBAA8D,QAAA,YAAA,gBAArBC,KAAAA,YAAW,EAAA,EAAA;IACxC,WAAA,sBAAZ,mBAAwD,QAAxD,YAA6C,OAAI;IACrC,SAAA,sBAAZ,mBAAwD,QAAxD,aAAyC,WAAQ;SAI7C,WAAA,SAAc,SAAA,sBADtB,mBAOM,OAAA;;IALJ,OAAM;IACL,SAAK,cAAO,cAAY,CAAA,OAAA,CAAA;IACzB,OAAM;MACP,MAED,2CAEF,YAME,MAAA,YAAA,EAAA;IALC,MAAM,UAAA;IACN,MAAM,cAAA;IACN,WAAS;IACT,SAAO;IACP,QAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_Cascade-IUUHIh7r.css","names":[],"sources":["../src/components/C_Cascade/index.vue?vue&type=style&index=0&scoped=e3904f11&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.n-cascade-selector[data-v-e3904f11] {\n display: flex;\n gap: 12px;\n}\n.n-cascade-selector .n-select-item[data-v-e3904f11] {\n min-width: 140px;\n flex: 1;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Cascade2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as export_helper_default } from "./export-helper.js";
|
|
2
|
-
import { Fragment, computed, createElementBlock, createVNode, defineComponent, openBlock, ref, renderList, unref, watch } from "vue";
|
|
3
2
|
import { NSelect } from "naive-ui";
|
|
3
|
+
import { Fragment, computed, createElementBlock, createVNode, defineComponent, openBlock, ref, renderList, unref, watch } from "vue";
|
|
4
4
|
|
|
5
5
|
//#region src/components/C_Cascade/index.vue?vue&type=script&setup=true&lang.ts
|
|
6
6
|
const _hoisted_1 = { class: "n-cascade-selector" };
|
|
@@ -96,7 +96,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
96
96
|
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region src/components/C_Cascade/index.vue
|
|
99
|
-
var C_Cascade_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
99
|
+
var C_Cascade_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e3904f11"]]);
|
|
100
100
|
|
|
101
101
|
//#endregion
|
|
102
102
|
export { C_Cascade_default as t };
|
package/dist/C_Cascade2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Cascade2.js","names":["placeholders"],"sources":["../src/components/C_Cascade/index.vue","../src/components/C_Cascade/index.vue","../src/components/C_Cascade/index.vue"],"sourcesContent":["<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;ECyCA,MAAM,QAAQ;EAWd,MAAM,OAAO;EAKb,MAAM,SAAS;GAAC;GAAG;GAAG;GAAE;EACxB,MAAM,iBAAiB,IAAgC;GAAC;GAAM;GAAM;GAAK,CAAC;EAE1E,MAAM,gBAAgB,UAAiC;AACrD,OAAI,UAAU,EAAG,QAAO,MAAM;AAC9B,OAAI,CAAC,eAAe,MAAM,QAAQ,GAAI,QAAO,EAAE;AAE/C,UADmB,aAAa,QAAQ,EAAE,CAE7B,MAAM,MAAM,EAAE,UAAU,eAAe,MAAM,QAAQ,GAAG,EAC/D,YAAY,EAAE;;EAItB,MAAM,eAAe,eACnB,OAAO,KAAK,UACV,aAAa,MAAM,CAAC,KAAK,UAAU;GACjC,OAAO,KAAK;GACZ,OAAO,KAAK;GACb,EAAE,CACJ,CACF;EAED,MAAM,gBAAgB,UAAkB;AACtC,kBAAe,MAAM,OACnB,QAAQ,GACR,OAAO,SAAS,QAAQ,GACxB,GAAG,MAAM,OAAO,SAAS,QAAQ,EAAE,CAAC,KAAK,KAAK,CAC/C;AACD,cAAW;;EAGb,MAAM,mBAAmB,UAAkB;GACzC,MAAM,QAAQ,eAAe,MAAM;AACnC,OAAI,CAAC,MAAO,QAAO;GAEnB,MAAM,OADO,aAAa,MAAM,CACd,MAAM,MAAM,EAAE,UAAU,MAAM;AAChD,UAAO,OAAO;IAAE,OAAO,KAAK;IAAO,OAAO,KAAK;IAAO,GAAG;;EAG3D,MAAM,kBAAkB;GACtB,MAAM,SAAuB;IAC3B,SAAS,gBAAgB,EAAE;IAC3B,WAAW,gBAAgB,EAAE;IAC7B,UAAU,gBAAgB,EAAE;IAC7B;AACD,QAAK,qBAAqB,OAAO;AACjC,QAAK,UAAU,OAAO;;AAGxB,cACQ,MAAM,aACX,QAAQ;AACP,kBAAe,QAAQ;IACrB,KAAK,SAAS,SAAS;IACvB,KAAK,WAAW,SAAS;IACzB,KAAK,UAAU,SAAS;IACzB;KAEH;GAAE,WAAW;GAAM,MAAM;GAAM,CAChC;;uBA5GC,mBAYM,OAZN,YAYM,eAXJ,mBAUE,UAAA,MAAA,WATyB,SAAjB,OAAO,UAAK;WADtB,YAUE,MAAA,QAAA,EAAA;KARC,KAAK;KACE,OAAO,eAAA,MAAe;oCAAf,eAAA,MAAe,SAAK,SAAA,WAKpB,aAAa,MAAK,CAAA;KAJhC,SAAS,aAAA,MAAa;KACvB,WAAA;KACC,aAAaA,KAAAA,aAAa;KAC1B,UAAU,QAAK,KAAA,CAAS,eAAA,MAAe,QAAK;KAE7C,OAAM"}
|
|
1
|
+
{"version":3,"file":"C_Cascade2.js","names":["placeholders"],"sources":["../src/components/C_Cascade/index.vue","../src/components/C_Cascade/index.vue","../src/components/C_Cascade/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-28\r\n * @Description: 级联选择组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"n-cascade-selector\">\r\n <NSelect\r\n v-for=\"(level, index) in levels\"\r\n :key=\"index\"\r\n v-model:value=\"selectedValues[index]\"\r\n :options=\"levelOptions[index]\"\r\n clearable\r\n :placeholder=\"placeholders[index]\"\r\n :disabled=\"index > 0 && !selectedValues[index - 1]\"\r\n @update:value=\"handleChange(index)\"\r\n class=\"n-select-item\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref, computed, watch } from \"vue\";\r\nimport { NSelect } from \"naive-ui\";\r\n\r\ndefineOptions({ name: \"C_Cascade\" });\r\n\r\nexport interface CascadeItem {\r\n label: string;\r\n value: string | number;\r\n children?: CascadeItem[];\r\n}\r\n\r\ninterface CascadeValue {\r\n primary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n secondary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n tertiary?: Pick<CascadeItem, \"label\" | \"value\"> | null;\r\n}\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n data: CascadeItem[];\r\n placeholders?: string[];\r\n modelValue?: CascadeValue;\r\n }>(),\r\n {\r\n placeholders: () => [\"请选择\", \"请选择\", \"请选择\"],\r\n },\r\n);\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CascadeValue];\r\n change: [value: CascadeValue];\r\n}>();\r\n\r\nconst levels = [0, 1, 2];\r\nconst selectedValues = ref<(string | number | null)[]>([null, null, null]);\r\n\r\nconst getLevelData = (level: number): CascadeItem[] => {\r\n if (level === 0) return props.data;\r\n if (!selectedValues.value[level - 1]) return [];\r\n const parentData = getLevelData(level - 1);\r\n return (\r\n parentData.find((x) => x.value === selectedValues.value[level - 1])\r\n ?.children || []\r\n );\r\n};\r\n\r\nconst levelOptions = computed(() =>\r\n levels.map((level) =>\r\n getLevelData(level).map((item) => ({\r\n label: item.label,\r\n value: item.value,\r\n })),\r\n ),\r\n);\r\n\r\nconst handleChange = (index: number) => {\r\n selectedValues.value.splice(\r\n index + 1,\r\n levels.length - index - 1,\r\n ...Array(levels.length - index - 1).fill(null),\r\n );\r\n emitValue();\r\n};\r\n\r\nconst getSelectedItem = (index: number) => {\r\n const value = selectedValues.value[index];\r\n if (!value) return null;\r\n const data = getLevelData(index);\r\n const item = data.find((i) => i.value === value);\r\n return item ? { label: item.label, value: item.value } : null;\r\n};\r\n\r\nconst emitValue = () => {\r\n const result: CascadeValue = {\r\n primary: getSelectedItem(0),\r\n secondary: getSelectedItem(1),\r\n tertiary: getSelectedItem(2),\r\n };\r\n emit(\"update:modelValue\", result);\r\n emit(\"change\", result);\r\n};\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n selectedValues.value = [\r\n val?.primary?.value ?? null,\r\n val?.secondary?.value ?? null,\r\n val?.tertiary?.value ?? null,\r\n ];\r\n },\r\n { immediate: true, deep: true },\r\n);\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.n-cascade-selector {\r\n display: flex;\r\n gap: 12px;\r\n .n-select-item {\r\n min-width: 140px;\r\n flex: 1;\r\n }\r\n}\r\n</style>\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;ECyCA,MAAM,QAAQ;EAWd,MAAM,OAAO;EAKb,MAAM,SAAS;GAAC;GAAG;GAAG;GAAE;EACxB,MAAM,iBAAiB,IAAgC;GAAC;GAAM;GAAM;GAAK,CAAC;EAE1E,MAAM,gBAAgB,UAAiC;AACrD,OAAI,UAAU,EAAG,QAAO,MAAM;AAC9B,OAAI,CAAC,eAAe,MAAM,QAAQ,GAAI,QAAO,EAAE;AAE/C,UADmB,aAAa,QAAQ,EAAE,CAE7B,MAAM,MAAM,EAAE,UAAU,eAAe,MAAM,QAAQ,GAAG,EAC/D,YAAY,EAAE;;EAItB,MAAM,eAAe,eACnB,OAAO,KAAK,UACV,aAAa,MAAM,CAAC,KAAK,UAAU;GACjC,OAAO,KAAK;GACZ,OAAO,KAAK;GACb,EAAE,CACJ,CACF;EAED,MAAM,gBAAgB,UAAkB;AACtC,kBAAe,MAAM,OACnB,QAAQ,GACR,OAAO,SAAS,QAAQ,GACxB,GAAG,MAAM,OAAO,SAAS,QAAQ,EAAE,CAAC,KAAK,KAAK,CAC/C;AACD,cAAW;;EAGb,MAAM,mBAAmB,UAAkB;GACzC,MAAM,QAAQ,eAAe,MAAM;AACnC,OAAI,CAAC,MAAO,QAAO;GAEnB,MAAM,OADO,aAAa,MAAM,CACd,MAAM,MAAM,EAAE,UAAU,MAAM;AAChD,UAAO,OAAO;IAAE,OAAO,KAAK;IAAO,OAAO,KAAK;IAAO,GAAG;;EAG3D,MAAM,kBAAkB;GACtB,MAAM,SAAuB;IAC3B,SAAS,gBAAgB,EAAE;IAC3B,WAAW,gBAAgB,EAAE;IAC7B,UAAU,gBAAgB,EAAE;IAC7B;AACD,QAAK,qBAAqB,OAAO;AACjC,QAAK,UAAU,OAAO;;AAGxB,cACQ,MAAM,aACX,QAAQ;AACP,kBAAe,QAAQ;IACrB,KAAK,SAAS,SAAS;IACvB,KAAK,WAAW,SAAS;IACzB,KAAK,UAAU,SAAS;IACzB;KAEH;GAAE,WAAW;GAAM,MAAM;GAAM,CAChC;;uBA5GC,mBAYM,OAZN,YAYM,eAXJ,mBAUE,UAAA,MAAA,WATyB,SAAjB,OAAO,UAAK;WADtB,YAUE,MAAA,QAAA,EAAA;KARC,KAAK;KACE,OAAO,eAAA,MAAe;oCAAf,eAAA,MAAe,SAAK,SAAA,WAKpB,aAAa,MAAK,CAAA;KAJhC,SAAS,aAAA,MAAa;KACvB,WAAA;KACC,aAAaA,KAAAA,aAAa;KAC1B,UAAU,QAAK,KAAA,CAAS,eAAA,MAAe,QAAK;KAE7C,OAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_City-Cv5BESaN.css","names":[],"sources":["../src/components/C_City/index.vue?vue&type=style&index=0&scoped=06a335f4&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.city-selector-trigger[data-v-06a335f4] {\n display: inline-flex;\n align-items: center;\n justify-content: space-between;\n min-width: 200px;\n height: 34px;\n padding: 0 12px;\n border: 1px solid #e0e0e6;\n border-radius: 3px;\n cursor: pointer;\n transition: all 0.3s;\n}\n.city-selector-trigger[data-v-06a335f4]:hover {\n border-color: var(--c-primary, #1890ff);\n}\n.city-selector-trigger__text[data-v-06a335f4] {\n flex: 1;\n font-size: 14px;\n}\n.city-selector-trigger__icon[data-v-06a335f4] {\n margin-left: 8px;\n color: #999;\n font-size: 16px;\n transition: transform 0.3s;\n}\n.city-selector-trigger__icon.is-active[data-v-06a335f4] {\n transform: rotate(180deg);\n}\n.city-selector-content[data-v-06a335f4] {\n display: flex;\n flex-direction: column;\n height: 500px;\n padding: 0;\n}\n.city-selector-header[data-v-06a335f4] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n border-bottom: 1px solid rgba(247, 247, 247, 0.514);\n flex-shrink: 0;\n}\n.city-selector-header .city-selector-search[data-v-06a335f4] {\n flex: 1;\n}\n.city-selector-letters[data-v-06a335f4] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin: 0 12px 10px;\n padding: 8px;\n flex-shrink: 0;\n}\n.city-selector-letters .city-selector-letter[data-v-06a335f4] {\n padding: 2px 6px;\n cursor: pointer;\n color: var(--c-primary, #1890ff);\n font-size: 13px;\n font-weight: 500;\n transition: all 0.3s;\n min-width: 24px;\n text-align: center;\n}\n.city-selector-letters .city-selector-letter[data-v-06a335f4]:hover {\n background-color: var(--c-primary, #1890ff);\n color: #fff;\n border-radius: 2px;\n}\n.city-selector-body[data-v-06a335f4] {\n flex: 1;\n margin: 12px;\n margin-top: 8px;\n overflow: hidden;\n}\n.city-list[data-v-06a335f4],\n.province-list[data-v-06a335f4] {\n padding: 0 8px;\n}\n.city-group[data-v-06a335f4],\n.province-group[data-v-06a335f4] {\n display: flex;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid rgba(247, 247, 247, 0.514);\n}\n.city-group[data-v-06a335f4]:last-child,\n.province-group[data-v-06a335f4]:last-child {\n border-bottom: none;\n margin-bottom: 0;\n padding-bottom: 0;\n}\n.city-group__letter[data-v-06a335f4], .city-group__name[data-v-06a335f4],\n.province-group__letter[data-v-06a335f4],\n.province-group__name[data-v-06a335f4] {\n flex-shrink: 0;\n width: 70px;\n font-weight: 500;\n font-size: 14px;\n line-height: 28px;\n}\n.city-group__cities[data-v-06a335f4],\n.province-group__cities[data-v-06a335f4] {\n flex: 1;\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: flex-start;\n}\n.city-item[data-v-06a335f4] {\n padding: 3px 10px;\n cursor: pointer;\n font-size: 13px;\n border-radius: 2px;\n transition: all 0.3s;\n line-height: 20px;\n}\n.city-item[data-v-06a335f4]:hover {\n background-color: #f0f0f0;\n color: var(--c-primary, #1890ff);\n}\n.city-item.is-active[data-v-06a335f4] {\n background-color: var(--c-primary, #1890ff);\n color: #fff;\n}\n[data-v-06a335f4] .n-scrollbar .n-scrollbar-rail {\n right: 2px;\n}\n[data-v-06a335f4] .n-scrollbar .n-scrollbar-content {\n padding-right: 12px;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_City2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as export_helper_default } from "./export-helper.js";
|
|
2
|
-
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, withCtx } from "vue";
|
|
3
2
|
import { NPopover, NRadioButton, NRadioGroup, NScrollbar, NSelect } from "naive-ui";
|
|
3
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, withCtx } from "vue";
|
|
4
4
|
|
|
5
5
|
//#region src/components/C_City/province.json
|
|
6
6
|
var province_default = {
|
|
@@ -834,7 +834,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
834
834
|
|
|
835
835
|
//#endregion
|
|
836
836
|
//#region src/components/C_City/index.vue
|
|
837
|
-
var C_City_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
837
|
+
var C_City_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-06a335f4"]]);
|
|
838
838
|
|
|
839
839
|
//#endregion
|
|
840
840
|
export { C_City_default as t };
|
package/dist/C_City2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_City2.js","names":["modelValue","placeholder","showLetters"],"sources":["../src/components/C_City/province.json","../src/components/C_City/index.vue","../src/components/C_City/index.vue","../src/components/C_City/index.vue"],"sourcesContent":["","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_City2.js","names":["modelValue","placeholder","showLetters"],"sources":["../src/components/C_City/province.json","../src/components/C_City/index.vue","../src/components/C_City/index.vue","../src/components/C_City/index.vue"],"sourcesContent":["","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-05-30\r\n * @Description: 城市选择器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NPopover\r\n v-model:show=\"visible\"\r\n placement=\"bottom-start\"\r\n :width=\"430\"\r\n trigger=\"click\"\r\n :show-arrow=\"false\"\r\n >\r\n <template #trigger>\r\n <slot name=\"trigger\" :value=\"modelValue\" :visible=\"visible\">\r\n <div class=\"city-selector-trigger\">\r\n <span class=\"city-selector-trigger__text\">{{\r\n modelValue || placeholder\r\n }}</span>\r\n </div>\r\n </slot>\r\n </template>\r\n\r\n <div class=\"city-selector-content\">\r\n <div class=\"city-selector-header\">\r\n <NRadioGroup v-model:value=\"radioValue\" size=\"small\">\r\n <NRadioButton value=\"city\">按城市</NRadioButton>\r\n <NRadioButton value=\"province\">按省份</NRadioButton>\r\n </NRadioGroup>\r\n <NSelect\r\n v-model:value=\"searchValue\"\r\n class=\"city-selector-search\"\r\n :options=\"searchOptions\"\r\n filterable\r\n clearable\r\n placeholder=\"搜索城市\"\r\n @update:value=\"handleSearchSelect\"\r\n />\r\n </div>\r\n\r\n <div v-if=\"showLetters\" class=\"city-selector-letters\">\r\n <span\r\n v-for=\"letter in letters\"\r\n :key=\"letter\"\r\n class=\"city-selector-letter\"\r\n @click=\"scrollToLetter(letter)\"\r\n >\r\n {{ letter }}\r\n </span>\r\n </div>\r\n\r\n <NScrollbar class=\"city-selector-body\">\r\n <div v-if=\"radioValue === 'city'\" class=\"city-list\">\r\n <div\r\n v-for=\"(cities, letter) in cityDataByLetter\"\r\n :key=\"letter\"\r\n :id=\"`letter-${letter}`\"\r\n class=\"city-group\"\r\n >\r\n <div class=\"city-group__letter\">{{ letter }}:</div>\r\n <div class=\"city-group__cities\">\r\n <span\r\n v-for=\"(city, index) in cities\"\r\n :key=\"`${letter}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city.name }\"\r\n @click=\"handleCitySelect(city.name)\"\r\n >\r\n {{ city.name }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"province-list\">\r\n <div\r\n v-for=\"province in allProvinces\"\r\n :key=\"province.id\"\r\n :id=\"`letter-${province.id}`\"\r\n class=\"province-group\"\r\n >\r\n <div class=\"province-group__name\">{{ province.name }}:</div>\r\n <div class=\"province-group__cities\">\r\n <span\r\n v-for=\"(city, index) in province.data\"\r\n :key=\"`${province.id}-${index}`\"\r\n class=\"city-item\"\r\n :class=\"{ 'is-active': modelValue === city }\"\r\n @click=\"handleCitySelect(city)\"\r\n >\r\n {{ city }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </NScrollbar>\r\n </div>\r\n </NPopover>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted } from \"vue\";\r\nimport {\r\n NPopover,\r\n NRadioGroup,\r\n NRadioButton,\r\n NSelect,\r\n NScrollbar,\r\n} from \"naive-ui\";\r\nimport type { SelectOption } from \"naive-ui\";\r\nimport provinceData from \"./province.json\";\r\n\r\ndefineOptions({ name: \"C_City\" });\r\n\r\ninterface CityItem {\r\n id: number;\r\n spell: string;\r\n name: string;\r\n}\r\n\r\n// 城市数据懒加载(83KB JSON 仅在组件挂载时加载)\r\nconst cityData = ref<{ cities: Record<string, CityItem[]> } | null>(null);\r\n\r\nonMounted(async () => {\r\n const mod = await import(\"./city.json\");\r\n cityData.value = mod.default ?? mod;\r\n});\r\n\r\ninterface ProvinceItem {\r\n id?: string;\r\n name: string;\r\n data: string[];\r\n}\r\n\r\ninterface Props {\r\n modelValue?: string;\r\n placeholder?: string;\r\n showLetters?: boolean;\r\n}\r\n\r\ninterface Emits {\r\n (e: \"update:modelValue\", value: string): void;\r\n (e: \"change\", value: string): void;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n placeholder: \"请选择城市\",\r\n showLetters: true,\r\n});\r\n\r\nconst emit = defineEmits<Emits>();\r\n\r\nconst visible = ref(false);\r\nconst radioValue = ref<\"city\" | \"province\">(\"city\");\r\nconst searchValue = ref(\"\");\r\n\r\nconst allProvinces = computed(() => {\r\n const provinces: ProvinceItem[] = [];\r\n Object.values(provinceData).forEach((group) => {\r\n provinces.push(...(group as ProvinceItem[]));\r\n });\r\n return provinces;\r\n});\r\n\r\nconst cityDataByLetter = computed(() => {\r\n if (cityData.value?.cities) {\r\n return cityData.value.cities;\r\n }\r\n // 数据未加载时,从省份数据生成城市索引作为 fallback\r\n const cities: Record<string, CityItem[]> = {};\r\n let cityId = 1;\r\n const citySet = new Set<string>();\r\n allProvinces.value.forEach((province) => {\r\n province.data.forEach((cityName) => {\r\n citySet.add(cityName);\r\n });\r\n });\r\n Array.from(citySet).forEach((cityName) => {\r\n const letter = cityName[0].toUpperCase();\r\n if (!cities[letter]) cities[letter] = [];\r\n cities[letter].push({ id: cityId++, name: cityName, spell: \"\" });\r\n });\r\n const sortedCities: Record<string, CityItem[]> = {};\r\n Object.keys(cities)\r\n .sort()\r\n .forEach((letter) => {\r\n sortedCities[letter] = cities[letter].sort((a, b) =>\r\n a.name.localeCompare(b.name, \"zh-CN\"),\r\n );\r\n });\r\n return sortedCities;\r\n});\r\n\r\nconst letters = computed(() => {\r\n if (radioValue.value === \"city\") {\r\n return Object.keys(cityDataByLetter.value).sort();\r\n } else {\r\n const provinceLetters = new Set<string>();\r\n Object.keys(provinceData).forEach((key) => {\r\n if (key !== \"直辖市\" && key !== \"港澳\") {\r\n provinceLetters.add(key);\r\n }\r\n });\r\n const result = Array.from(provinceLetters).sort();\r\n result.push(\"直辖市\", \"港澳\");\r\n return result;\r\n }\r\n});\r\n\r\nconst searchOptions = computed((): SelectOption[] => {\r\n if (radioValue.value === \"city\") {\r\n const options: SelectOption[] = [];\r\n Object.values(cityDataByLetter.value).forEach((cities) => {\r\n (cities as CityItem[]).forEach((city) => {\r\n options.push({\r\n label: city.name,\r\n value: city.name,\r\n });\r\n });\r\n });\r\n return options;\r\n } else {\r\n return allProvinces.value.flatMap((province) =>\r\n province.data.map((city) => ({\r\n label: `${city} (${province.name})`,\r\n value: city,\r\n })),\r\n );\r\n }\r\n});\r\n\r\nconst handleCitySelect = (cityName: string): void => {\r\n emit(\"update:modelValue\", cityName);\r\n emit(\"change\", cityName);\r\n visible.value = false;\r\n};\r\n\r\nconst handleSearchSelect = (value: string): void => {\r\n if (value) {\r\n handleCitySelect(value);\r\n searchValue.value = \"\";\r\n }\r\n};\r\n\r\nconst scrollToLetter = (letter: string): void => {\r\n const element = document.getElementById(`letter-${letter}`);\r\n if (element) {\r\n element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n }\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"C_Code-DPZlNSxL.css","names":[],"sources":["../src/components/C_Code/index.vue?vue&type=style&index=0&scoped=2f676c83&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.mr-2[data-v-2f676c83] {\n margin-right: 0.5rem;\n}\n.ml-2[data-v-2f676c83] {\n margin-left: 0.5rem;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Code2.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as C_Icon_default } from "./C_Icon2.js";
|
|
2
2
|
import { t as export_helper_default } from "./export-helper.js";
|
|
3
|
-
import {
|
|
3
|
+
import { NButton, NCode, NModal, NSpin, NTooltip } from "naive-ui";
|
|
4
|
+
import { Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, nextTick, normalizeStyle, onMounted, onUnmounted, openBlock, ref, toDisplayString, watch, withCtx } from "vue";
|
|
4
5
|
|
|
5
6
|
//#region src/components/C_Code/index.vue?vue&type=script&setup=true&lang.ts
|
|
6
7
|
const _hoisted_1 = { class: "c-code-wrapper" };
|
|
@@ -193,11 +194,11 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
193
194
|
toggleFullscreen
|
|
194
195
|
});
|
|
195
196
|
return (_ctx, _cache) => {
|
|
196
|
-
const _component_NButton =
|
|
197
|
-
const _component_NTooltip =
|
|
198
|
-
const _component_NCode =
|
|
199
|
-
const _component_NSpin =
|
|
200
|
-
const _component_NModal =
|
|
197
|
+
const _component_NButton = NButton;
|
|
198
|
+
const _component_NTooltip = NTooltip;
|
|
199
|
+
const _component_NCode = NCode;
|
|
200
|
+
const _component_NSpin = NSpin;
|
|
201
|
+
const _component_NModal = NModal;
|
|
201
202
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
202
203
|
createCommentVNode(" 代码标题栏 "),
|
|
203
204
|
_ctx.showHeader ? (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("div", _hoisted_3, [languageIcon.value ? (openBlock(), createBlock(C_Icon_default, {
|
|
@@ -339,7 +340,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
339
340
|
|
|
340
341
|
//#endregion
|
|
341
342
|
//#region src/components/C_Code/index.vue
|
|
342
|
-
var C_Code_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
343
|
+
var C_Code_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2f676c83"]]);
|
|
343
344
|
|
|
344
345
|
//#endregion
|
|
345
346
|
export { C_Code_default as t };
|