@qxs-bns/components 0.0.29 → 0.0.30
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/es/package.json.mjs +1 -1
- package/es/src/data-chart/src/components/area.vue2.mjs +1 -1
- package/es/src/data-chart/src/components/area.vue2.mjs.map +1 -1
- package/es/src/data-chart/src/components/bar.vue.mjs +1 -1
- package/es/src/data-chart/src/components/bar.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/funnel.vue.mjs +1 -1
- package/es/src/data-chart/src/components/funnel.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/line.vue2.mjs +1 -1
- package/es/src/data-chart/src/components/line.vue2.mjs.map +1 -1
- package/es/src/data-chart/src/components/pie.vue.mjs +1 -1
- package/es/src/data-chart/src/components/pie.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/radar.vue.mjs +1 -1
- package/es/src/data-chart/src/components/radar.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/scatter-simple.vue.mjs +1 -1
- package/es/src/data-chart/src/components/scatter-simple.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/scatter.vue.mjs +1 -1
- package/es/src/data-chart/src/components/scatter.vue.mjs.map +1 -1
- package/es/src/data-chart/src/components/table.vue.mjs +1 -1
- package/es/src/data-chart/src/components/table.vue.mjs.map +1 -1
- package/es/src/data-chart/src/data-chart.vue.mjs +1 -1
- package/es/src/data-chart/src/data-chart.vue.mjs.map +1 -1
- package/es/src/data-chart/src/utils/useCharts.mjs +1 -1
- package/es/src/data-chart/src/utils/useCharts.mjs.map +1 -1
- package/es/src/file-upload/src/file-upload.vue.mjs +1 -1
- package/es/src/file-upload/src/file-upload.vue.mjs.map +1 -1
- package/es/src/fixed-action-bar/src/fixed-action-bar.vue.mjs +1 -1
- package/es/src/fixed-action-bar/src/fixed-action-bar.vue.mjs.map +1 -1
- package/es/src/image-upload/src/image-upload.vue.mjs +1 -1
- package/es/src/image-upload/src/image-upload.vue.mjs.map +1 -1
- package/es/src/photo-crop-tool/src/composables.mjs +1 -1
- package/es/src/photo-crop-tool/src/composables.mjs.map +1 -1
- package/es/src/photo-crop-tool/src/photo-crop-tool.vue.mjs +1 -1
- package/es/src/photo-crop-tool/src/photo-crop-tool.vue.mjs.map +1 -1
- package/es/src/subject-action/src/subject-action.vue.mjs +1 -1
- package/es/src/subject-action/src/subject-action.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/SubjectPageEnd.vue.mjs +1 -1
- package/es/src/subject-list/src/components/SubjectPageEnd.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/SubjectRichText.vue.mjs +1 -1
- package/es/src/subject-list/src/components/SubjectRichText.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/subject-blank-fill.vue.mjs +1 -1
- package/es/src/subject-list/src/components/subject-blank-fill.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/subject-scale.vue.mjs +1 -1
- package/es/src/subject-list/src/components/subject-scale.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/subject-single.vue.mjs +1 -1
- package/es/src/subject-list/src/components/subject-single.vue.mjs.map +1 -1
- package/es/src/subject-list/src/components/subject-text-fill.vue.mjs +1 -1
- package/es/src/subject-list/src/components/subject-text-fill.vue.mjs.map +1 -1
- package/es/src/subject-list/src/subject-list.vue.mjs +1 -1
- package/es/src/subject-list/src/subject-list.vue.mjs.map +1 -1
- package/es/src/subject-type/src/subject-type.vue.mjs +1 -1
- package/es/src/subject-type/src/subject-type.vue.mjs.map +1 -1
- package/es/src/tiny-mce-editor/src/tiny-mce-editor.vue.mjs +1 -1
- package/es/src/tiny-mce-editor/src/tiny-mce-editor.vue.mjs.map +1 -1
- package/lib/package.json.cjs +1 -1
- package/lib/src/data-chart/src/components/area.vue2.cjs +1 -1
- package/lib/src/data-chart/src/components/area.vue2.cjs.map +1 -1
- package/lib/src/data-chart/src/components/bar.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/bar.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/funnel.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/funnel.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/line.vue2.cjs +1 -1
- package/lib/src/data-chart/src/components/line.vue2.cjs.map +1 -1
- package/lib/src/data-chart/src/components/pie.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/pie.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/radar.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/radar.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/scatter-simple.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/scatter-simple.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/scatter.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/scatter.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/components/table.vue.cjs +1 -1
- package/lib/src/data-chart/src/components/table.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/data-chart.vue.cjs +1 -1
- package/lib/src/data-chart/src/data-chart.vue.cjs.map +1 -1
- package/lib/src/data-chart/src/utils/useCharts.cjs +1 -1
- package/lib/src/data-chart/src/utils/useCharts.cjs.map +1 -1
- package/lib/src/file-upload/src/file-upload.vue.cjs +1 -1
- package/lib/src/file-upload/src/file-upload.vue.cjs.map +1 -1
- package/lib/src/fixed-action-bar/src/fixed-action-bar.vue.cjs +1 -1
- package/lib/src/fixed-action-bar/src/fixed-action-bar.vue.cjs.map +1 -1
- package/lib/src/image-upload/src/image-upload.vue.cjs +1 -1
- package/lib/src/image-upload/src/image-upload.vue.cjs.map +1 -1
- package/lib/src/photo-crop-tool/src/composables.cjs +1 -1
- package/lib/src/photo-crop-tool/src/composables.cjs.map +1 -1
- package/lib/src/photo-crop-tool/src/photo-crop-tool.vue.cjs +1 -1
- package/lib/src/photo-crop-tool/src/photo-crop-tool.vue.cjs.map +1 -1
- package/lib/src/subject-action/src/subject-action.vue.cjs +1 -1
- package/lib/src/subject-action/src/subject-action.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/SubjectPageEnd.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/SubjectPageEnd.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/SubjectRichText.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/SubjectRichText.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/subject-blank-fill.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/subject-blank-fill.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/subject-scale.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/subject-scale.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/subject-single.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/subject-single.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/components/subject-text-fill.vue.cjs +1 -1
- package/lib/src/subject-list/src/components/subject-text-fill.vue.cjs.map +1 -1
- package/lib/src/subject-list/src/subject-list.vue.cjs +1 -1
- package/lib/src/subject-list/src/subject-list.vue.cjs.map +1 -1
- package/lib/src/subject-type/src/subject-type.vue.cjs +1 -1
- package/lib/src/subject-type/src/subject-type.vue.cjs.map +1 -1
- package/lib/src/tiny-mce-editor/src/tiny-mce-editor.vue.cjs +1 -1
- package/lib/src/tiny-mce-editor/src/tiny-mce-editor.vue.cjs.map +1 -1
- package/package.json +8 -6
- package/types/index.d.ts +0 -6
- package/types/index.d.ts.map +0 -1
- package/types/src/base/style/css.d.ts +0 -2
- package/types/src/base/style/css.d.ts.map +0 -1
- package/types/src/base/style/index.d.ts +0 -2
- package/types/src/base/style/index.d.ts.map +0 -1
- package/types/src/components.d.ts +0 -11
- package/types/src/components.d.ts.map +0 -1
- package/types/src/data-chart/index.d.ts +0 -4
- package/types/src/data-chart/index.d.ts.map +0 -1
- package/types/src/data-chart/src/analyze.d.ts +0 -23
- package/types/src/data-chart/src/analyze.d.ts.map +0 -1
- package/types/src/data-chart/src/utils/config.d.ts +0 -41
- package/types/src/data-chart/src/utils/config.d.ts.map +0 -1
- package/types/src/data-chart/src/utils/injectionKeys.d.ts +0 -3
- package/types/src/data-chart/src/utils/injectionKeys.d.ts.map +0 -1
- package/types/src/data-chart/src/utils/useCharts.d.ts +0 -16
- package/types/src/data-chart/src/utils/useCharts.d.ts.map +0 -1
- package/types/src/data-chart/style/index.d.ts +0 -3
- package/types/src/data-chart/style/index.d.ts.map +0 -1
- package/types/src/defaults.d.ts +0 -6
- package/types/src/defaults.d.ts.map +0 -1
- package/types/src/file-upload/index.d.ts +0 -4
- package/types/src/file-upload/index.d.ts.map +0 -1
- package/types/src/file-upload/style/index.d.ts +0 -3
- package/types/src/file-upload/style/index.d.ts.map +0 -1
- package/types/src/fixed-action-bar/index.d.ts +0 -4
- package/types/src/fixed-action-bar/index.d.ts.map +0 -1
- package/types/src/fixed-action-bar/style/index.d.ts +0 -3
- package/types/src/fixed-action-bar/style/index.d.ts.map +0 -1
- package/types/src/image-upload/index.d.ts +0 -4
- package/types/src/image-upload/index.d.ts.map +0 -1
- package/types/src/image-upload/style/index.d.ts +0 -3
- package/types/src/image-upload/style/index.d.ts.map +0 -1
- package/types/src/make-installer.d.ts +0 -9
- package/types/src/make-installer.d.ts.map +0 -1
- package/types/src/photo-crop-tool/index.d.ts +0 -4
- package/types/src/photo-crop-tool/index.d.ts.map +0 -1
- package/types/src/photo-crop-tool/src/composables.d.ts +0 -7
- package/types/src/photo-crop-tool/src/composables.d.ts.map +0 -1
- package/types/src/photo-crop-tool/style/index.d.ts +0 -3
- package/types/src/photo-crop-tool/style/index.d.ts.map +0 -1
- package/types/src/subject-action/index.d.ts +0 -4
- package/types/src/subject-action/index.d.ts.map +0 -1
- package/types/src/subject-action/style/index.d.ts +0 -3
- package/types/src/subject-action/style/index.d.ts.map +0 -1
- package/types/src/subject-layout/index.d.ts +0 -4
- package/types/src/subject-layout/index.d.ts.map +0 -1
- package/types/src/subject-layout/style/index.d.ts +0 -3
- package/types/src/subject-layout/style/index.d.ts.map +0 -1
- package/types/src/subject-list/index.d.ts +0 -4
- package/types/src/subject-list/index.d.ts.map +0 -1
- package/types/src/subject-list/style/index.d.ts +0 -3
- package/types/src/subject-list/style/index.d.ts.map +0 -1
- package/types/src/subject-type/index.d.ts +0 -4
- package/types/src/subject-type/index.d.ts.map +0 -1
- package/types/src/subject-type/style/index.d.ts +0 -3
- package/types/src/subject-type/style/index.d.ts.map +0 -1
- package/types/src/tiny-mce-editor/index.d.ts +0 -4
- package/types/src/tiny-mce-editor/index.d.ts.map +0 -1
- package/types/src/tiny-mce-editor/style/index.d.ts +0 -3
- package/types/src/tiny-mce-editor/style/index.d.ts.map +0 -1
- package/types/src/withInstall.d.ts +0 -4
- package/types/src/withInstall.d.ts.map +0 -1
- package/types/tsconfig.tsbuildinfo +0 -1
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("../utils/injectionKeys.cjs"),r=require("../utils/useCharts.cjs"),a=
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("../utils/injectionKeys.cjs"),r=require("../utils/useCharts.cjs"),a=e.defineComponent({name:"DataChartScatter",__name:"scatter",props:{chartData:{type:Object,required:!0,default:()=>({colDesc:[],xGroupByDesc:{colDesc:"",groupByDesc:"",groupByValues:[],xAxis:!1},groupByDesc:[],data:[],modelName:""})},chartOptions:{type:null,required:!0}},setup(a){const s=e.ref(),c=e.inject(t.InjectionChartMerge,(e=>e),!0),o=e.computed((()=>c({xAxis:{},yAxis:{},series:[{symbolSize:20,data:[[10,8.04],[8.07,6.95],[13,7.58],[9.05,8.81],[11,8.33],[14,7.66],[13.4,6.81],[10,6.33],[14,8.96],[12.5,6.82],[9.15,7.2],[11.5,7.2],[3.03,4.23],[12.2,7.83],[2.02,4.47],[1.05,3.33],[4.05,4.96],[6.03,7.24],[12,6.26],[12,8.84],[7.08,5.82],[5.02,5.68]],type:"scatter"}]},a.chartOptions)));return r.useCharts({chartDOM:s,chartOptions:o,chartData:e.computed((()=>a.chartData))}),(t,r)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"dataChartScatter",ref:s,class:"data-chart-scatter"},null,512))}});exports.default=a;
|
2
2
|
//# sourceMappingURL=scatter.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"scatter.vue.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/components/scatter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { EChartsOption, IFormatPublicData } from '../types'\nimport { InjectionChartMerge } from '../utils/injectionKeys'\nimport { useCharts } from '../utils/useCharts'\n\ndefineOptions({\n name: 'DataChartScatter',\n})\n\nconst {\n chartData = {\n colDesc: [],\n xGroupByDesc: {\n colDesc: '',\n groupByDesc: '',\n groupByValues: [],\n xAxis: false,\n },\n groupByDesc: [],\n data: [],\n modelName: '',\n },\n chartOptions,\n} = defineProps<{\n chartData: IFormatPublicData\n chartOptions: EChartsOption\n}>()\n\nconst dataChartScatter = ref()\nconst merge = inject(InjectionChartMerge, (v: any) => v, true)\n\nconst scatterChartOptions = computed<EChartsOption>(() => {\n const config = {\n xAxis: {},\n yAxis: {},\n series: [\n {\n symbolSize: 20,\n data: [\n [10.0, 8.04],\n [8.07, 6.95],\n [13.0, 7.58],\n [9.05, 8.81],\n [11.0, 8.33],\n [14.0, 7.66],\n [13.4, 6.81],\n [10.0, 6.33],\n [14.0, 8.96],\n [12.5, 6.82],\n [9.15, 7.2],\n [11.5, 7.2],\n [3.03, 4.23],\n [12.2, 7.83],\n [2.02, 4.47],\n [1.05, 3.33],\n [4.05, 4.96],\n [6.03, 7.24],\n [12.0, 6.26],\n [12.0, 8.84],\n [7.08, 5.82],\n [5.02, 5.68],\n ],\n type: 'scatter',\n },\n ],\n }\n\n return merge(config, chartOptions)\n})\nuseCharts({ chartDOM: dataChartScatter, chartOptions: scatterChartOptions, chartData: computed(() => chartData) })\n</script>\n\n<template>\n <div ref=\"dataChartScatter\" class=\"data-chart-scatter\" />\n</template>\n"],"names":["dataChartScatter","ref","merge","inject","InjectionChartMerge","v","scatterChartOptions","computed","xAxis","yAxis","series","symbolSize","data","type","__props","chartOptions","useCharts","chartDOM","chartData"],"mappings":"
|
1
|
+
{"version":3,"file":"scatter.vue.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/components/scatter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { EChartsOption, IFormatPublicData } from '../types'\nimport { InjectionChartMerge } from '../utils/injectionKeys'\nimport { useCharts } from '../utils/useCharts'\n\ndefineOptions({\n name: 'DataChartScatter',\n})\n\nconst {\n chartData = {\n colDesc: [],\n xGroupByDesc: {\n colDesc: '',\n groupByDesc: '',\n groupByValues: [],\n xAxis: false,\n },\n groupByDesc: [],\n data: [],\n modelName: '',\n },\n chartOptions,\n} = defineProps<{\n chartData: IFormatPublicData\n chartOptions: EChartsOption\n}>()\n\nconst dataChartScatter = ref()\nconst merge = inject(InjectionChartMerge, (v: any) => v, true)\n\nconst scatterChartOptions = computed<EChartsOption>(() => {\n const config = {\n xAxis: {},\n yAxis: {},\n series: [\n {\n symbolSize: 20,\n data: [\n [10.0, 8.04],\n [8.07, 6.95],\n [13.0, 7.58],\n [9.05, 8.81],\n [11.0, 8.33],\n [14.0, 7.66],\n [13.4, 6.81],\n [10.0, 6.33],\n [14.0, 8.96],\n [12.5, 6.82],\n [9.15, 7.2],\n [11.5, 7.2],\n [3.03, 4.23],\n [12.2, 7.83],\n [2.02, 4.47],\n [1.05, 3.33],\n [4.05, 4.96],\n [6.03, 7.24],\n [12.0, 6.26],\n [12.0, 8.84],\n [7.08, 5.82],\n [5.02, 5.68],\n ],\n type: 'scatter',\n },\n ],\n }\n\n return merge(config, chartOptions)\n})\nuseCharts({ chartDOM: dataChartScatter, chartOptions: scatterChartOptions, chartData: computed(() => chartData) })\n</script>\n\n<template>\n <div ref=\"dataChartScatter\" class=\"data-chart-scatter\" />\n</template>\n"],"names":["dataChartScatter","ref","merge","inject","InjectionChartMerge","v","scatterChartOptions","computed","xAxis","yAxis","series","symbolSize","data","type","__props","chartOptions","useCharts","chartDOM","chartData"],"mappings":"+bA4BA,MAAMA,EAAmBC,EAAAA,MACnBC,EAAQC,EAAAA,OAAOC,EAAAA,qBAAsBC,GAAWA,IAAG,GAEnDC,EAAsBC,EAAAA,UAAwB,IAoC3CL,EAnCQ,CACbM,MAAO,CAAC,EACRC,MAAO,CAAC,EACRC,OAAQ,CACN,CACEC,WAAY,GACZC,KAAM,CACJ,CAAC,GAAM,MACP,CAAC,KAAM,MACP,CAAC,GAAM,MACP,CAAC,KAAM,MACP,CAAC,GAAM,MACP,CAAC,GAAM,MACP,CAAC,KAAM,MACP,CAAC,GAAM,MACP,CAAC,GAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,KACP,CAAC,KAAM,KACP,CAAC,KAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,MACP,CAAC,GAAM,MACP,CAAC,GAAM,MACP,CAAC,KAAM,MACP,CAAC,KAAM,OAETC,KAAM,aAKSC,EAAYC,uBAEzBC,EAAAA,UAAA,CAAEC,SAAUjB,EAAkBe,aAAcT,EAAqBY,UAAWX,YAAS,IAAMO,EAAAI"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),a=require("./empty.vue.cjs"),o=require("@qxs-bns/hooks")
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),a=require("./empty.vue.cjs"),o=require("@qxs-bns/hooks");const r={key:0,class:"title"};var l=t.defineComponent({name:"DataChartTable",__name:"table",props:{chartData:{type:Object,default:()=>({colDesc:[],xGroupByDesc:[],data:[],modelName:""})}},setup(l){const c=l,n=o.useNamespace("data-chart"),s=t.computed((()=>c.chartData.groupByDesc.find((e=>!e.xAxis))));function i(e){if(!e)return 100;const t=14*e.length+20+30;return t<100?100:t}return(o,c)=>{const p=e.ElTableColumn,d=e.ElTable;return t.openBlock(),t.createElementBlock("div",{class:t.normalizeClass([t.unref(n).e("data-chart-table")])},[l.chartData.modelName?(t.openBlock(),t.createElementBlock("p",r,[t.createElementVNode("span",null,t.toDisplayString(l.chartData.modelName),1)])):t.createCommentVNode("v-if",!0),t.createVNode(d,{class:"customize-table data-chart-table-content",data:l.chartData.data,stripe:"",height:"100%"},{empty:t.withCtx((()=>[t.createVNode(a.default)])),default:t.withCtx((()=>[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(l.chartData.groupByDesc,((e,a)=>(t.openBlock(),t.createBlock(p,{key:`${e.colDesc}${e.groupByDesc}${a}`,align:"center","show-overflow-tooltip":"",sortable:"","min-width":`${i(e.colDesc)}px`,prop:e.colDesc||""},{header:t.withCtx((()=>[t.createTextVNode(t.toDisplayString(e.colDesc),1)])),default:t.withCtx((a=>[t.createTextVNode(t.toDisplayString((t.unref(s)&&(t.unref(s).colDesc,e.colDesc),a.row[e.colDesc||""]||"--")),1)])),_:2},1032,["min-width","prop"])))),128)),(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(l.chartData.colDesc,((e,a)=>(t.openBlock(),t.createBlock(p,{key:e+a,align:"center","min-width":`${i(e)}px`,label:e,"show-overflow-tooltip":"",sortable:"",prop:e},{header:t.withCtx((()=>[t.createTextVNode(t.toDisplayString(e),1)])),_:2},1032,["min-width","label","prop"])))),128))])),_:1},8,["data"])],2)}}});exports.default=l;
|
2
2
|
//# sourceMappingURL=table.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"table.vue.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/components/table.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { IFormatPublicData } from '../types'\nimport Empty from './empty.vue'\nimport { useNamespace } from '@qxs-bns/hooks'\n\ndefineOptions({\n name: 'DataChartTable',\n})\n\nconst props = defineProps({\n chartData: {\n type: Object as PropType<IFormatPublicData>,\n default: () => ({\n colDesc: [],\n xGroupByDesc: [],\n data: [],\n modelName: '',\n }),\n },\n})\n\nconst ns = useNamespace('data-chart')\n\nconst yGroupByDesc = computed(() => {\n const row = props.chartData.groupByDesc.find(item => !item.xAxis)\n return row\n})\n\nfunction baseWidth(str: string | null) {\n if (!str) {\n return 100\n }\n const strWidth = str.length * 14 + 20 + 30\n return strWidth < 100 ? 100 : strWidth\n}\n</script>\n\n<template>\n <div :class=\"[ns.e('data-chart-table')]\">\n <p v-if=\"chartData.modelName\" class=\"title\">\n <span>{{ chartData.modelName }}</span>\n </p>\n <el-table\n class=\"customize-table data-chart-table-content\"\n :data=\"chartData.data\"\n stripe\n height=\"100%\"\n >\n <el-table-column\n v-for=\"(item, index) in chartData.groupByDesc\"\n :key=\"`${item.colDesc}${item.groupByDesc}${index}`\"\n align=\"center\"\n show-overflow-tooltip\n sortable\n :min-width=\"`${baseWidth(item.colDesc)}px`\"\n :prop=\"item.colDesc || ''\"\n >\n <template #header>\n {{ item.colDesc }}\n </template>\n <template #default=\"scoped\">\n {{ (yGroupByDesc && yGroupByDesc.colDesc === item.colDesc ? scoped.row[item.colDesc || ''] : scoped.row[item.colDesc || '']) || '--' }}\n </template>\n </el-table-column>\n <el-table-column\n v-for=\"(item, index) in chartData.colDesc\"\n :key=\"item + index\"\n align=\"center\"\n :min-width=\"`${baseWidth(item)}px`\"\n :label=\"item\"\n show-overflow-tooltip\n sortable\n :prop=\"item\"\n >\n <template #header>\n {{ item }}\n </template>\n </el-table-column>\n <template #empty>\n <Empty />\n </template>\n </el-table>\n </div>\n</template>"],"names":["props","__props","ns","useNamespace","yGroupByDesc","computed","chartData","groupByDesc","find","item","xAxis","baseWidth","str","strWidth","length"],"mappings":"
|
1
|
+
{"version":3,"file":"table.vue.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/components/table.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { IFormatPublicData } from '../types'\nimport Empty from './empty.vue'\nimport { useNamespace } from '@qxs-bns/hooks'\n\ndefineOptions({\n name: 'DataChartTable',\n})\n\nconst props = defineProps({\n chartData: {\n type: Object as PropType<IFormatPublicData>,\n default: () => ({\n colDesc: [],\n xGroupByDesc: [],\n data: [],\n modelName: '',\n }),\n },\n})\n\nconst ns = useNamespace('data-chart')\n\nconst yGroupByDesc = computed(() => {\n const row = props.chartData.groupByDesc.find(item => !item.xAxis)\n return row\n})\n\nfunction baseWidth(str: string | null) {\n if (!str) {\n return 100\n }\n const strWidth = str.length * 14 + 20 + 30\n return strWidth < 100 ? 100 : strWidth\n}\n</script>\n\n<template>\n <div :class=\"[ns.e('data-chart-table')]\">\n <p v-if=\"chartData.modelName\" class=\"title\">\n <span>{{ chartData.modelName }}</span>\n </p>\n <el-table\n class=\"customize-table data-chart-table-content\"\n :data=\"chartData.data\"\n stripe\n height=\"100%\"\n >\n <el-table-column\n v-for=\"(item, index) in chartData.groupByDesc\"\n :key=\"`${item.colDesc}${item.groupByDesc}${index}`\"\n align=\"center\"\n show-overflow-tooltip\n sortable\n :min-width=\"`${baseWidth(item.colDesc)}px`\"\n :prop=\"item.colDesc || ''\"\n >\n <template #header>\n {{ item.colDesc }}\n </template>\n <template #default=\"scoped\">\n {{ (yGroupByDesc && yGroupByDesc.colDesc === item.colDesc ? scoped.row[item.colDesc || ''] : scoped.row[item.colDesc || '']) || '--' }}\n </template>\n </el-table-column>\n <el-table-column\n v-for=\"(item, index) in chartData.colDesc\"\n :key=\"item + index\"\n align=\"center\"\n :min-width=\"`${baseWidth(item)}px`\"\n :label=\"item\"\n show-overflow-tooltip\n sortable\n :prop=\"item\"\n >\n <template #header>\n {{ item }}\n </template>\n </el-table-column>\n <template #empty>\n <Empty />\n </template>\n </el-table>\n </div>\n</template>"],"names":["props","__props","ns","useNamespace","yGroupByDesc","computed","chartData","groupByDesc","find","item","xAxis","baseWidth","str","strWidth","length"],"mappings":"oXAUA,MAAMA,EAAQC,EAYRC,EAAKC,eAAa,cAElBC,EAAeC,EAAAA,UAAS,IAChBL,EAAMM,UAAUC,YAAYC,MAAaC,IAACA,EAAKC,UAI7D,SAASC,EAAUC,GACjB,IAAKA,EACI,OAAA,IAET,MAAMC,EAAwB,GAAbD,EAAIE,OAAc,GAAK,GACjC,OAAAD,EAAW,IAAM,IAAMA,CAAA"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/utils"),r=require("lodash-es"),s=require("./utils/config.cjs"),o=require("./utils/injectionKeys.cjs"),a=require("./utils/useCharts.cjs"),u=require("@qxs-bns/hooks"),n=require("./components/table.vue.cjs"),c=require("./components/bar.vue.cjs"),l=require("./components/line.vue.cjs"),i=require("./components/pie.vue.cjs"),p=require("./components/radar.vue.cjs"),d=require("./components/scatter.vue.cjs"),m=require("./components/funnel.vue.cjs"),f=require("./components/area.vue.cjs"),h=require("./components/card.vue.cjs"),
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/utils"),r=require("lodash-es"),s=require("./utils/config.cjs"),o=require("./utils/injectionKeys.cjs"),a=require("./utils/useCharts.cjs"),u=require("@qxs-bns/hooks"),n=require("./components/table.vue.cjs"),c=require("./components/bar.vue.cjs"),l=require("./components/line.vue.cjs"),i=require("./components/pie.vue.cjs"),p=require("./components/radar.vue.cjs"),d=require("./components/scatter.vue.cjs"),m=require("./components/funnel.vue.cjs"),f=require("./components/area.vue.cjs"),h=require("./components/card.vue.cjs"),y=require("./components/scatter-simple.vue.cjs"),q=e.defineComponent({name:"QxsDataChart",__name:"data-chart",props:{modelName:{type:String,required:!1,default:""},showTypeName:{type:String,required:!1,default:"table"},subShowType:{type:String,required:!1},data:{type:Object,required:!1,default:()=>({data:[],desc:{colDesc:[],showDesc:{showType:0,chartOptions:"{}",jsCodeSnippet:""},groupByDesc:[]}})},chartOptions:{type:null,required:!1,default:()=>({})},jsCodeSnippet:{type:String,required:!1,default:""}},setup(q,{expose:j}){const v=u.useNamespace("data-chart"),g={table:n.default,bar:c.default,line:l.default,pie:i.default,radar:p.default,scatter:d.default,funnel:m.default,area:f.default,card:h.default,"scatter-simple":y.default},b=e.computed((()=>r.cloneDeep(s.defaultChartOption[q.showTypeName]))),x=e.computed((()=>{const{desc:{colDesc:e=[],groupByDesc:t=[]}={},data:r=[]}=q.data;let s=[],o=null;s=t?.map((e=>(e.xAxis&&(o=e),e)));const a=o?r.filter((e=>e&&e[o.colDesc])):r;return{colDesc:e,modelName:q.modelName,subShowType:q.subShowType,xGroupByDesc:o||{groupByDesc:null,groupByValues:null,colDesc:null,xAxis:!1},groupByDesc:s,data:a}}));return j({exportExal:function(){if(0===q.data.data.length)return void console.log("暂无数据");const e=a.useDataToExcelJson(q.data);t.JsonToExcel(q.modelName,e)}}),e.provide(o.InjectionChartMerge,(function(e,t){let s=r.merge({},b.value,e,t)||{};if(q.jsCodeSnippet)try{s=new Function("config",`"use strict"; ${q.jsCodeSnippet}; return config;`)(s)}catch(e){console.error("代码执行失败:",e)}return s})),(t,r)=>(e.openBlock(),e.createBlock(e.resolveDynamicComponent(g[t.showTypeName]),{class:e.normalizeClass([e.unref(v).e("wrapper")]),"sub-show-type":t.subShowType,"chart-data":e.unref(x),"chart-options":t.chartOptions},null,8,["class","sub-show-type","chart-data","chart-options"]))}});exports.default=q;
|
2
2
|
//# sourceMappingURL=data-chart.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"data-chart.vue.cjs","sources":["../../../../../../packages/components/src/data-chart/src/data-chart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { EChartData, EChartsOption, IFormatPublicData } from './types'\nimport type { IconRow } from './types/index'\nimport { JsonToExcel } from '@qxs-bns/utils'\nimport { cloneDeep, merge as lodashMerge } from 'lodash-es'\nimport { defaultChartOption } from './utils/config'\nimport { InjectionChartMerge } from './utils/injectionKeys'\nimport { useDataToExcelJson } from './utils/useCharts'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport Table from './components/table.vue'\nimport Bar from './components/bar.vue'\nimport Line from './components/line.vue'\nimport Pie from './components/pie.vue'\nimport Radar from './components/radar.vue'\nimport Scatter from './components/scatter.vue'\nimport Funnel from './components/funnel.vue'\nimport Area from './components/area.vue'\nimport Card from './components/card.vue'\nimport ScatterSimple from './components/scatter-simple.vue'\n\ndefineOptions({\n name: 'QxsDataChart',\n})\n\nconst ns = useNamespace('data-chart')\n\nconst {\n showTypeName = 'table',\n subShowType,\n modelName = '',\n data: propData = {\n data: [],\n desc: {\n colDesc: [],\n showDesc: {\n showType: 0,\n chartOptions: '{}',\n jsCodeSnippet: '',\n },\n groupByDesc: [],\n },\n },\n chartOptions = {},\n jsCodeSnippet = '',\n} = defineProps<{\n modelName?: string\n showTypeName?: IconRow['showTypeName']\n subShowType?: string\n data?: EChartData\n chartOptions?: EChartsOption\n jsCodeSnippet?: string\n}>()\n\nconst coms: {\n [key: string]: any\n} = {\n table: Table,\n bar: Bar,\n line: Line,\n pie: Pie,\n radar: Radar,\n scatter: Scatter,\n funnel: Funnel,\n area: Area,\n card: Card,\n 'scatter-simple':ScatterSimple,\n}\n\nconst defaultChartOptionCopy = computed(() => {\n return cloneDeep(defaultChartOption[showTypeName])\n})\n\nconst formatPublicData = computed<IFormatPublicData>(() => {\n const { desc: { colDesc = [], groupByDesc = [] } = {}, data = [] } = propData\n\n // 处理 X 轴数据\n let xValue = []\n\n let xGroupByDesc: EChartData['desc']['groupByDesc'][0] | null = null\n xValue = groupByDesc?.map((groupByDescItem) => {\n // if (groupByDescItem.colValues) {\n // groupByDescItem.colValuesDesc = {}\n // groupByDescItem.colValues.split(',')?.forEach((item) => {\n // const [key, value] = item.split(':')\n // groupByDescItem.colValuesDesc[key] = value\n // })\n // }\n if (groupByDescItem.xAxis) {\n xGroupByDesc = groupByDescItem\n }\n return groupByDescItem\n })\n\n const dataValue = xGroupByDesc ? data.filter(item => item && item[xGroupByDesc!.colDesc!]) : data\n\n // if (xGroupByDesc && xGroupByDesc.colValuesDesc && Object.keys(xGroupByDesc.colValuesDesc).length) {\n // const { colDesc: colDescItem, colValuesDesc } = xGroupByDesc\n // console.log('colDesc: colDescItem, colValuesDesc: ', colDescItem, colValuesDesc)\n // dataValue = dataValue.map((item) => {\n // if (typeof item[colDescItem] === 'number') {\n // item[colDescItem] = colValuesDesc[item[colDescItem]]\n // }\n // return item\n // })\n // }\n\n return {\n colDesc,\n modelName,\n subShowType,\n xGroupByDesc: (xGroupByDesc || {\n groupByDesc: null,\n groupByValues: null,\n colDesc: null,\n xAxis: false,\n }),\n groupByDesc: xValue,\n data: dataValue,\n }\n})\n\n// 导出数据\nfunction exportExal() {\n if (propData.data.length === 0) {\n // useMessage.error('暂无数据')\n console.log('暂无数据')\n return\n }\n const arr = useDataToExcelJson(propData)\n JsonToExcel(modelName, arr)\n}\nfunction merge(config: EChartsOption, defaultConfig: EChartsOption) {\n const mergeOpt = lodashMerge({}, defaultChartOptionCopy.value, config, defaultConfig)\n let conf = mergeOpt || {}\n if (jsCodeSnippet) {\n try {\n // 用 Function 构造函数替代 eval\n const dynamicFunction = new Function(\n 'config',\n `\"use strict\"; ${jsCodeSnippet}; return config;`\n );\n \n // 执行动态函数并传递 conf 参数\n conf = dynamicFunction(conf);\n } catch (error) {\n console.error(\"代码执行失败:\", error);\n }\n }\n return conf\n}\n\n\ndefineExpose({\n exportExal,\n})\nprovide(InjectionChartMerge, merge)\n</script>\n\n<template>\n <component\n :is=\"coms[showTypeName]\"\n :class=\"[ns.e('wrapper')]\"\n :sub-show-type=\"subShowType\"\n :chart-data=\"formatPublicData\"\n :chart-options=\"chartOptions\"\n />\n</template>\n"],"names":["ns","useNamespace","coms","table","Table","default","bar","Bar","line","Line","pie","Pie","radar","Radar","scatter","Scatter","funnel","Funnel","area","Area","card","Card","ScatterSimple","defaultChartOptionCopy","computed","cloneDeep","defaultChartOption","__props","formatPublicData","desc","colDesc","groupByDesc","data","xValue","xGroupByDesc","map","groupByDescItem","xAxis","dataValue","filter","item","modelName","subShowType","groupByValues","__expose","exportExal","length","console","log","arr","useDataToExcelJson","JsonToExcel","provide","InjectionChartMerge","config","defaultConfig","conf","lodashMerge","value","jsCodeSnippet","Function","dynamicFunction","error"],"mappings":"
|
1
|
+
{"version":3,"file":"data-chart.vue.cjs","sources":["../../../../../../packages/components/src/data-chart/src/data-chart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { EChartData, EChartsOption, IFormatPublicData } from './types'\nimport type { IconRow } from './types/index'\nimport { JsonToExcel } from '@qxs-bns/utils'\nimport { cloneDeep, merge as lodashMerge } from 'lodash-es'\nimport { defaultChartOption } from './utils/config'\nimport { InjectionChartMerge } from './utils/injectionKeys'\nimport { useDataToExcelJson } from './utils/useCharts'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport Table from './components/table.vue'\nimport Bar from './components/bar.vue'\nimport Line from './components/line.vue'\nimport Pie from './components/pie.vue'\nimport Radar from './components/radar.vue'\nimport Scatter from './components/scatter.vue'\nimport Funnel from './components/funnel.vue'\nimport Area from './components/area.vue'\nimport Card from './components/card.vue'\nimport ScatterSimple from './components/scatter-simple.vue'\n\ndefineOptions({\n name: 'QxsDataChart',\n})\n\nconst ns = useNamespace('data-chart')\n\nconst {\n showTypeName = 'table',\n subShowType,\n modelName = '',\n data: propData = {\n data: [],\n desc: {\n colDesc: [],\n showDesc: {\n showType: 0,\n chartOptions: '{}',\n jsCodeSnippet: '',\n },\n groupByDesc: [],\n },\n },\n chartOptions = {},\n jsCodeSnippet = '',\n} = defineProps<{\n modelName?: string\n showTypeName?: IconRow['showTypeName']\n subShowType?: string\n data?: EChartData\n chartOptions?: EChartsOption\n jsCodeSnippet?: string\n}>()\n\nconst coms: {\n [key: string]: any\n} = {\n table: Table,\n bar: Bar,\n line: Line,\n pie: Pie,\n radar: Radar,\n scatter: Scatter,\n funnel: Funnel,\n area: Area,\n card: Card,\n 'scatter-simple':ScatterSimple,\n}\n\nconst defaultChartOptionCopy = computed(() => {\n return cloneDeep(defaultChartOption[showTypeName])\n})\n\nconst formatPublicData = computed<IFormatPublicData>(() => {\n const { desc: { colDesc = [], groupByDesc = [] } = {}, data = [] } = propData\n\n // 处理 X 轴数据\n let xValue = []\n\n let xGroupByDesc: EChartData['desc']['groupByDesc'][0] | null = null\n xValue = groupByDesc?.map((groupByDescItem) => {\n // if (groupByDescItem.colValues) {\n // groupByDescItem.colValuesDesc = {}\n // groupByDescItem.colValues.split(',')?.forEach((item) => {\n // const [key, value] = item.split(':')\n // groupByDescItem.colValuesDesc[key] = value\n // })\n // }\n if (groupByDescItem.xAxis) {\n xGroupByDesc = groupByDescItem\n }\n return groupByDescItem\n })\n\n const dataValue = xGroupByDesc ? data.filter(item => item && item[xGroupByDesc!.colDesc!]) : data\n\n // if (xGroupByDesc && xGroupByDesc.colValuesDesc && Object.keys(xGroupByDesc.colValuesDesc).length) {\n // const { colDesc: colDescItem, colValuesDesc } = xGroupByDesc\n // console.log('colDesc: colDescItem, colValuesDesc: ', colDescItem, colValuesDesc)\n // dataValue = dataValue.map((item) => {\n // if (typeof item[colDescItem] === 'number') {\n // item[colDescItem] = colValuesDesc[item[colDescItem]]\n // }\n // return item\n // })\n // }\n\n return {\n colDesc,\n modelName,\n subShowType,\n xGroupByDesc: (xGroupByDesc || {\n groupByDesc: null,\n groupByValues: null,\n colDesc: null,\n xAxis: false,\n }),\n groupByDesc: xValue,\n data: dataValue,\n }\n})\n\n// 导出数据\nfunction exportExal() {\n if (propData.data.length === 0) {\n // useMessage.error('暂无数据')\n console.log('暂无数据')\n return\n }\n const arr = useDataToExcelJson(propData)\n JsonToExcel(modelName, arr)\n}\nfunction merge(config: EChartsOption, defaultConfig: EChartsOption) {\n const mergeOpt = lodashMerge({}, defaultChartOptionCopy.value, config, defaultConfig)\n let conf = mergeOpt || {}\n if (jsCodeSnippet) {\n try {\n // 用 Function 构造函数替代 eval\n const dynamicFunction = new Function(\n 'config',\n `\"use strict\"; ${jsCodeSnippet}; return config;`\n );\n \n // 执行动态函数并传递 conf 参数\n conf = dynamicFunction(conf);\n } catch (error) {\n console.error(\"代码执行失败:\", error);\n }\n }\n return conf\n}\n\n\ndefineExpose({\n exportExal,\n})\nprovide(InjectionChartMerge, merge)\n</script>\n\n<template>\n <component\n :is=\"coms[showTypeName]\"\n :class=\"[ns.e('wrapper')]\"\n :sub-show-type=\"subShowType\"\n :chart-data=\"formatPublicData\"\n :chart-options=\"chartOptions\"\n />\n</template>\n"],"names":["ns","useNamespace","coms","table","Table","default","bar","Bar","line","Line","pie","Pie","radar","Radar","scatter","Scatter","funnel","Funnel","area","Area","card","Card","ScatterSimple","defaultChartOptionCopy","computed","cloneDeep","defaultChartOption","__props","formatPublicData","desc","colDesc","groupByDesc","data","xValue","xGroupByDesc","map","groupByDescItem","xAxis","dataValue","filter","item","modelName","subShowType","groupByValues","__expose","exportExal","length","console","log","arr","useDataToExcelJson","JsonToExcel","provide","InjectionChartMerge","config","defaultConfig","conf","lodashMerge","value","jsCodeSnippet","Function","dynamicFunction","error"],"mappings":"soCAwBM,MAAAA,EAAKC,eAAa,cA6BlBC,EAEF,CACFC,MAAOC,EAAAC,QACPC,IAAKC,EAAAF,QACLG,KAAMC,EAAAJ,QACNK,IAAKC,EAAAN,QACLO,MAAOC,EAAAR,QACPS,QAASC,EAAAV,QACTW,OAAQC,EAAAZ,QACRa,KAAMC,EAAAd,QACNe,KAAMC,EAAAhB,QACN,iBAAiBiB,EAAAA,SAGbC,EAAyBC,EAAAA,UAAS,IAC/BC,YAAUC,EAAAA,mBAAmBC,mBAGhCC,EAAmBJ,EAAAA,UAA4B,KACnD,MAAQK,MAAMC,QAAEA,EAAU,eAAIC,EAAc,IAAO,CAAI,EAAAC,KAAAA,EAAO,IAAOL,EAAAK,KAGrE,IAAIC,EAAS,GAETC,EAA4D,KACvDD,EAAAF,GAAaI,KAAKC,IAQrBA,EAAgBC,QACHH,EAAAE,GAEVA,KAGH,MAAAE,EAAYJ,EAAeF,EAAKO,QAAOC,GAAQA,GAAQA,EAAKN,EAAcJ,WAAaE,EAatF,MAAA,CACLF,UACAW,UAASd,EAAAc,UACTC,YAAWf,EAAAe,YACXR,aAAeA,GAAgB,CAC7BH,YAAa,KACbY,cAAe,KACfb,QAAS,KACTO,OAAO,GAETN,YAAaE,EACbD,KAAMM,EACR,WAkCWM,EAAA,CACXC,WA/BF,WACE,GAA6B,IAAzBlB,OAASK,KAAKc,OAGhB,YADAC,QAAQC,IAAI,QAGR,MAAAC,EAAMC,EAAAA,mBAAmBvB,EAAQK,MAC3BmB,cAAAxB,EAAAc,UAAWQ,EAAG,IA0B5BG,EAAAA,QAAQC,uBAxBC,SAAMC,EAAuBC,GAEhC,IAAAC,EADaC,EAAAA,MAAY,GAAIlC,EAAuBmC,MAAOJ,EAAQC,IAChD,CAAC,EACxB,GAAI5B,EAAAgC,cACE,IAQFH,EANwB,IAAII,SAC1B,SACA,iBAAiBjC,EAAAgC,gCAIZE,CAAgBL,SAChBM,GACCf,QAAAe,MAAM,UAAWA,EAAK,CAG3B,OAAAN,CAAA"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";var e=require("
|
1
|
+
"use strict";var e=require("echarts"),t=require("../components/empty.svg.cjs"),o=require("vue"),i=require("@vueuse/core");function n(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:function(){return e[o]}})}})),t.default=e,Object.freeze(t)}var r=n(e);function a(e,t){const{width:o,height:n}=i.useElementSize(t);i.watchDebounced([o,n],(()=>{e&&e.resize()}))}exports.useCharts=function(e){let{chartDOM:n,chartData:u,chartOptions:l,mountedBefore:s,initAfter:c,callback:d}=e,f=null;const v=o.ref(!1),p=window.devicePixelRatio||1;function g(){f&&!f.isDisposed()&&(f.dispose(),f=null)}function h(){if(f&&v.value&&n.value){f.showLoading();try{f.isDisposed()&&(f=r.init(n.value,null,{devicePixelRatio:p,renderer:"svg"})),f.setOption(...arguments)}catch(e){console.log("error: ",e),g(),n.value&&(f=r.init(n.value,null,{devicePixelRatio:p,renderer:"svg"}),x("配置项错误"))}finally{f?.hideLoading()}}}const{isOutside:m}=i.useMouseInElement(n);function x(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"暂无数据";h({title:[{text:u.value?.modelName,...l.value.title},{subtext:e,top:"center",left:"center",text:" {a|}",itemGap:-20,textStyle:{align:"center",rich:{a:{color:"#000",fontSize:"16",height:80,width:160,backgroundColor:{image:t.default}}}},subtextStyle:{fontSize:16}}]},{notMerge:!0,replaceMerge:["xAxis","yAxis","series"],lazyUpdate:!1})}return i.watchDebounced(m,(e=>{var t;"boolean"==typeof e&&(t=!e,f?.isDisposed()||f?.setOption({toolbox:{show:t}}))}),{debounce:200}),o.onMounted((async()=>{s&&await s(),n.value&&(g(),f=r.init(n.value,null,{devicePixelRatio:p,renderer:"svg"}),d&&d(f),c&&await c(),a(f,n),v.value=!0,u.value?.data?.length?h(l.value,{}):x())})),o.onUnmounted((()=>{f&&(f.getZr()?.off("mousemove"),f.getZr()?.off("mouseout"),g())})),{myChart:f}},exports.useDataToExcelJson=function(e){const{desc:{colDesc:t=[],groupByDesc:o=[]}={},data:i=[]}=e,n=[...o.map((e=>e.colDesc)),...t].filter((e=>e)),r=i.map((e=>n.map((t=>e[t]||""))));return[n,...r]},exports.useResize=a;
|
2
2
|
//# sourceMappingURL=useCharts.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useCharts.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/utils/useCharts.ts"],"sourcesContent":["import type { ECharts, SetOptionOpts } from 'echarts'\nimport type { ComputedRef, Ref } from 'vue'\nimport type { EChartData, EChartsOption, IFormatPublicData } from '../types'\nimport
|
1
|
+
{"version":3,"file":"useCharts.cjs","sources":["../../../../../../../packages/components/src/data-chart/src/utils/useCharts.ts"],"sourcesContent":["import type { ECharts, SetOptionOpts } from 'echarts'\nimport type { ComputedRef, Ref } from 'vue'\nimport type { EChartData, EChartsOption, IFormatPublicData } from '../types'\nimport * as echarts from 'echarts'\n\n// 使用别名路径导入 SVG\nimport emptyImg from '../components/empty.svg'\n\nexport function useCharts({ chartDOM, chartData, chartOptions, mountedBefore, initAfter, callback }: {\n chartDOM: Ref<HTMLElement | null>\n chartData: ComputedRef<IFormatPublicData>\n chartOptions: ComputedRef<EChartsOption>\n mountedBefore?: () => void\n initAfter?: () => void\n callback?: (e: ECharts) => void\n}) {\n let myChart: ECharts | null = null\n const initChartSuccess = ref(false)\n\n // 获取设备像素比\n const dpr = window.devicePixelRatio || 1\n\n function disposeChart() {\n if (myChart && !myChart.isDisposed()) {\n myChart.dispose()\n myChart = null\n }\n }\n\n function initChart(...opt: [EChartsOption, SetOptionOpts]) {\n if (!myChart || !initChartSuccess.value || !chartDOM.value) {\n return\n }\n\n myChart.showLoading()\n try {\n if (myChart.isDisposed()) {\n // 如果实例已被销毁,重新创建\n myChart = echarts.init(chartDOM.value, null, {\n devicePixelRatio: dpr,\n renderer: 'svg',\n })\n }\n myChart.setOption(...opt)\n }\n catch (error) {\n console.log('error: ', error)\n disposeChart()\n if (chartDOM.value) {\n myChart = echarts.init(chartDOM.value, null, {\n devicePixelRatio: dpr,\n renderer: 'svg',\n })\n setEmpty('配置项错误')\n }\n }\n finally {\n myChart?.hideLoading()\n }\n }\n\n const { isOutside: mouseInChart } = useMouseInElement(chartDOM)\n watchDebounced(mouseInChart, (newVal) => {\n if (typeof newVal !== 'boolean') {\n return\n }\n toggleToolbox(!newVal)\n }, { debounce: 200 })\n\n function setEmpty(subtext = '暂无数据') {\n const obj: EChartsOption = {\n title: [{\n text: chartData.value?.modelName,\n ...chartOptions.value.title,\n }, {\n subtext,\n top: 'center',\n left: 'center',\n text: ' {a|}',\n itemGap: -20,\n textStyle: {\n align: 'center',\n rich: {\n a: {\n color: '#000',\n fontSize: '16',\n height: 80,\n width: 160,\n backgroundColor: {\n image: emptyImg,\n },\n },\n },\n },\n subtextStyle: {\n fontSize: 16,\n },\n }],\n }\n initChart(obj, {\n notMerge: true,\n replaceMerge: ['xAxis', 'yAxis', 'series'],\n lazyUpdate: false,\n })\n }\n\n function toggleToolbox(show: boolean) {\n if (!myChart?.isDisposed()) {\n myChart?.setOption({\n toolbox: {\n show,\n },\n })\n }\n }\n\n onMounted(async () => {\n if (mountedBefore) {\n await mountedBefore()\n }\n if (!chartDOM.value) {\n return\n }\n disposeChart() // 确保旧实例被清理\n myChart = echarts.init(chartDOM.value, null, {\n devicePixelRatio: dpr,\n renderer: 'svg',\n })\n if (callback) {\n callback(myChart)\n }\n if (initAfter) {\n await initAfter()\n }\n\n useResize(myChart, chartDOM)\n\n initChartSuccess.value = true\n\n if (chartData.value?.data?.length) {\n initChart(chartOptions.value, {})\n }\n else {\n setEmpty()\n }\n })\n\n onUnmounted(() => {\n if (myChart) {\n myChart.getZr()?.off('mousemove')\n myChart.getZr()?.off('mouseout')\n disposeChart()\n }\n })\n\n return {\n myChart,\n }\n}\n\nexport function useResize(myChart: ECharts, chartDOM: Ref<HTMLElement | null>) {\n const { width, height } = useElementSize(chartDOM)\n watchDebounced([width, height], () => {\n if (myChart) {\n myChart.resize()\n }\n })\n}\n\nexport function useDataToExcelJson(dataSource: EChartData) {\n const { desc: { colDesc = [], groupByDesc = [] } = {}, data = [] } = dataSource\n const header = [...groupByDesc.map(item => item.colDesc), ...colDesc].filter(v => v) as string[]\n const json = data.map((item) => {\n return header.map((headerItem) => {\n return item[headerItem as keyof typeof item] || ''\n })\n })\n return [header, ...json]\n}\n"],"names":["useResize","myChart","chartDOM","width","height","useElementSize","watchDebounced","resize","_ref","chartData","chartOptions","mountedBefore","initAfter","callback","initChartSuccess","ref","dpr","window","devicePixelRatio","disposeChart","isDisposed","dispose","initChart","value","showLoading","echarts","init","renderer","setOption","arguments","error","console","log","setEmpty","hideLoading","isOutside","mouseInChart","useMouseInElement","subtext","title","text","modelName","top","left","itemGap","textStyle","align","rich","a","color","fontSize","backgroundColor","image","emptyImg","subtextStyle","notMerge","replaceMerge","lazyUpdate","newVal","show","toolbox","debounce","onMounted","async","data","length","onUnmounted","getZr","off","dataSource","desc","colDesc","groupByDesc","header","map","item","filter","v","json","headerItem"],"mappings":"wYAgKgB,SAAAA,EAAUC,EAAkBC,GAC1C,MAAMC,MAAEA,EAAAC,OAAOA,GAAWC,EAAAA,eAAeH,GACzCI,EAAAA,eAAe,CAACH,EAAOC,IAAS,KAC1BH,GACFA,EAAQM,QACV,GAEJ,mBA/JgB,SAAAC,GAOb,IAPuBN,SAAEA,EAAUO,UAAAA,EAAAC,aAAWA,gBAAcC,EAAeC,UAAAA,EAAAC,SAAWA,GAOtFL,EACGP,EAA0B,KACxB,MAAAa,EAAmBC,OAAI,GAGvBC,EAAMC,OAAOC,kBAAoB,EAEvC,SAASC,IACHlB,IAAYA,EAAQmB,eACtBnB,EAAQoB,UACEpB,EAAA,KAEd,CAEA,SAASqB,IACP,GAAKrB,GAAYa,EAAiBS,OAAUrB,EAASqB,MAArD,CAIAtB,EAAQuB,cACJ,IACEvB,EAAQmB,eAEVnB,EAAUwB,EAAQC,KAAKxB,EAASqB,MAAO,KAAM,CAC3CL,iBAAkBF,EAClBW,SAAU,SAGN1B,EAAA2B,aAAUC,iBAEbC,GACGC,QAAAC,IAAI,UAAWF,GACVX,IACTjB,EAASqB,QACXtB,EAAUwB,EAAQC,KAAKxB,EAASqB,MAAO,KAAM,CAC3CL,iBAAkBF,EAClBW,SAAU,QAEZM,EAAS,SAEb,CACA,QACEhC,GAASiC,aACX,CA1BA,CA2BF,CAEA,MAAQC,UAAWC,GAAiBC,EAAAA,kBAAkBnC,GAQ7C,SAAA+B,IAA2B,IAAlBK,yDAAU,OA8B1BhB,EA7B2B,CACzBiB,MAAO,CAAC,CACNC,KAAM/B,EAAUc,OAAOkB,aACpB/B,EAAaa,MAAMgB,OACrB,CACDD,UACAI,IAAK,SACLC,KAAM,SACNH,KAAM,QACNI,SAAS,GACTC,UAAW,CACTC,MAAO,SACPC,KAAM,CACJC,EAAG,CACDC,MAAO,OACPC,SAAU,KACV9C,OAAQ,GACRD,MAAO,IACPgD,gBAAiB,CACfC,MAAOC,EAAAA,YAKfC,aAAc,CACZJ,SAAU,OAID,CACbK,UAAU,EACVC,aAAc,CAAC,QAAS,QAAS,UACjCC,YAAY,GAEhB,CAmDO,OA7FQnD,EAAAA,eAAA8B,GAAesB,IA4C9B,IAAuBC,EA3CC,kBAAXD,IA2CUC,GAxCND,EAyCVzD,GAASmB,cACZnB,GAAS2B,UAAU,CACjBgC,QAAS,CACPD,UA5Ce,GACpB,CAAEE,SAAU,MAiDfC,EAAAA,WAAUC,UACJpD,SACIA,IAEHT,EAASqB,QAGDJ,IACblB,EAAUwB,EAAQC,KAAKxB,EAASqB,MAAO,KAAM,CAC3CL,iBAAkBF,EAClBW,SAAU,QAERd,GACFA,EAASZ,GAEPW,SACIA,IAGRZ,EAAUC,EAASC,GAEnBY,EAAiBS,OAAQ,EAErBd,EAAUc,OAAOyC,MAAMC,OACf3C,EAAAZ,EAAaa,MAAO,IAGrBU,IACX,IAGFiC,EAAAA,aAAY,KACNjE,IACMA,EAAAkE,SAASC,IAAI,aACbnE,EAAAkE,SAASC,IAAI,YACRjD,IACf,IAGK,CACLlB,UAEJ,6BAWO,SAA4BoE,GACjC,MAAQC,MAAMC,QAAEA,EAAU,GAAIC,YAAAA,EAAc,IAAO,CAAC,EAAAR,KAAGA,EAAO,IAAOK,EAC/DI,EAAS,IAAID,EAAYE,KAAYC,GAAAA,EAAKJ,aAAaA,GAASK,WAAYC,IAC5EC,EAAOd,EAAKU,KAAKC,GACdF,EAAOC,KAAKK,GACVJ,EAAKI,IAAoC,OAG7C,MAAA,CAACN,KAAWK,EACrB"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),l=require("@element-plus/icons-vue"),a=require("@qxs-bns/hooks")
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),l=require("@element-plus/icons-vue"),a=require("@qxs-bns/hooks");const r={class:"slot"},i={key:0,class:"el-upload__tip"},s={style:{display:"inline-block"}};var o=t.defineComponent({name:"QxsFileUpload",__name:"file-upload",props:{action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},size:{type:Number,required:!1,default:20},max:{type:Number,required:!1,default:3},accept:{type:String,required:!1,default:"zip,rar"},files:{type:Array,required:!1,default:()=>[]},notip:{type:Boolean,required:!1,default:!1},ext:{type:Array,required:!1}},emits:["onSuccess"],setup(o,{emit:n}){const d=n,u=a.useNamespace("file-upload"),c=t.computed((()=>o.accept.split(","))),p=t=>{const l=t.name.split(".").at(-1)??"",a=c.value.includes(l),r=t.size/1024/1024<o.size;return a||e.ElMessage.error(`上传文件只支持 ${c.value.join(" / ")} 格式!`),r||e.ElMessage.error(`上传文件大小不能超过 ${o.size}MB!`),a&&r},m=()=>{e.ElMessage.warning("文件上传超过限制")},f=(e,t,l)=>{d("onSuccess",e,t,l)};return(a,o)=>{const n=e.ElIcon,d=e.ElAlert,y=e.ElUpload;return t.openBlock(),t.createBlock(y,{headers:a.headers,action:a.action,data:a.data,name:a.name,"before-upload":p,"on-exceed":m,"on-success":f,"file-list":a.files,limit:a.max,drag:"",class:t.normalizeClass(t.unref(u).e("control"))},{tip:t.withCtx((()=>[a.notip?t.createCommentVNode("v-if",!0):(t.openBlock(),t.createElementBlock("div",i,[t.createElementVNode("div",s,[t.createVNode(d,{title:`上传文件支持 ${t.unref(c).join(" / ")} 格式,单个文件大小不超过 ${a.size}MB,且文件数量不超过 ${a.max} 个`,type:"info","show-icon":"",closable:!1},null,8,["title"])])]))])),default:t.withCtx((()=>[t.createElementVNode("div",r,[t.createVNode(n,{class:"el-icon--upload"},{default:t.withCtx((()=>[t.createVNode(t.unref(l.UploadFilled))])),_:1}),o[0]||(o[0]=t.createElementVNode("div",{class:"el-upload__text"},[t.createTextVNode("将文件拖到此处,或"),t.createElementVNode("em",null,"点击上传")],-1))])])),_:1},8,["headers","action","data","name","file-list","limit","class"])}}});exports.default=o;
|
2
2
|
//# sourceMappingURL=file-upload.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"file-upload.vue.cjs","sources":["../../../../../../packages/components/src/file-upload/src/file-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadProps, UploadUserFile } from
|
1
|
+
{"version":3,"file":"file-upload.vue.cjs","sources":["../../../../../../packages/components/src/file-upload/src/file-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadProps, UploadUserFile } from \"element-plus\";\nimport { UploadFilled } from \"@element-plus/icons-vue\";\nimport { useNamespace } from \"@qxs-bns/hooks\";\n\ndefineOptions({\n name: \"QxsFileUpload\",\n});\n\nconst {\n name = \"file\",\n size = 20,\n max = 3,\n files = [],\n notip = false,\n accept = \"zip,rar\",\n} = defineProps<{\n action: UploadProps[\"action\"];\n headers?: UploadProps[\"headers\"];\n data?: UploadProps[\"data\"];\n name?: UploadProps[\"name\"];\n size?: number;\n max?: number;\n accept?: string;\n files?: UploadUserFile[];\n notip?: boolean;\n ext?: string[];\n}>();\n\nconst emit = defineEmits([\"onSuccess\"]);\n\nconst ns = useNamespace(\"file-upload\");\n\nconst exts = computed(() => {\n return accept.split(\",\")\n});\nconst beforeUpload: UploadProps[\"beforeUpload\"] = (file) => {\n const fileName = file.name.split(\".\");\n const fileExt = fileName.at(-1) ?? \"\";\n const isTypeOk = exts.value.includes(fileExt);\n const isSizeOk = file.size / 1024 / 1024 < size;\n if (!isTypeOk) {\n ElMessage.error(`上传文件只支持 ${exts.value.join(\" / \")} 格式!`);\n }\n if (!isSizeOk) {\n ElMessage.error(`上传文件大小不能超过 ${size}MB!`);\n }\n return isTypeOk && isSizeOk;\n};\n\nconst onExceed: UploadProps[\"onExceed\"] = () => {\n ElMessage.warning(\"文件上传超过限制\");\n};\n\nconst onSuccess: UploadProps[\"onSuccess\"] = (res, file, fileList) => {\n emit(\"onSuccess\", res, file, fileList);\n};\n</script>\n\n<template>\n <el-upload\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :before-upload=\"beforeUpload\"\n :on-exceed=\"onExceed\"\n :on-success=\"onSuccess\"\n :file-list=\"files\"\n :limit=\"max\"\n drag\n :class=\"ns.e('control')\"\n >\n <div class=\"slot\">\n <el-icon class=\"el-icon--upload\">\n <UploadFilled />\n </el-icon>\n <div class=\"el-upload__text\">将文件拖到此处,或<em>点击上传</em></div>\n </div>\n <template #tip>\n <div v-if=\"!notip\" class=\"el-upload__tip\">\n <div style=\"display: inline-block\">\n <el-alert\n :title=\"`上传文件支持 ${exts.join(\n ' / '\n )} 格式,单个文件大小不超过 ${size}MB,且文件数量不超过 ${max} 个`\"\n type=\"info\"\n show-icon\n :closable=\"false\"\n />\n </div>\n </div>\n </template>\n </el-upload>\n</template>\n"],"names":["emit","__emit","ns","useNamespace","exts","computed","__props","accept","split","beforeUpload","file","fileExt","name","at","isTypeOk","value","includes","isSizeOk","size","ElMessage","error","join","onExceed","warning","onSuccess","res","fileList"],"mappings":"2wBA6BA,MAAMA,EAAOC,EAEPC,EAAKC,eAAa,eAElBC,EAAOC,EAAAA,UAAS,IACbC,EAAAC,OAAOC,MAAM,OAEhBC,EAA6CC,IACjD,MACMC,EADWD,EAAKE,KAAKJ,MAAM,KACRK,IAAG,IAAO,GAC7BC,EAAWV,EAAKW,MAAMC,SAASL,GAC/BM,EAAWP,EAAKQ,KAAO,KAAO,KAAOZ,EAAIY,KAO/C,OANKJ,GACHK,YAAUC,MAAM,WAAWhB,EAAKW,MAAMM,KAAK,cAExCJ,GACHE,EAAAA,UAAUC,MAAM,cAAcd,EAAIY,WAE7BJ,GAAYG,CAAA,EAGfK,EAAoC,KACxCH,EAAAA,UAAUI,QAAQ,WAAU,EAGxBC,EAAsC,CAACC,EAAKf,EAAMgB,KACjD1B,EAAA,YAAayB,EAAKf,EAAMgB,EAAQ"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/hooks"),n=require("@qxs-bns/utils");var
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/hooks"),n=require("@qxs-bns/utils"),r=require("lodash-es");var a=e.defineComponent({name:"QxsFixedActionBar",props:{padding:{type:Number,default:8},className:{type:String,default:""}},setup(a){const o=a,i=t.useNamespace("fixed-action-bar"),l=e.ref(!1),d=e.ref(null),s=e.ref(null),c=e.ref({width:0,height:0}),u=e.ref(0),p=e.ref(0),f={resize:null,parent:null},h=(e,t,n)=>{const r=new ResizeObserver((e=>{e.forEach((e=>requestAnimationFrame((()=>t(e)))))}));return r.observe(e,n),r},m=()=>{if(!d.value||!s.value)return;f.resize=h(d.value,(e=>{const t=(e=>{const t=getComputedStyle(e);return{x:parseFloat(t.paddingLeft)+parseFloat(t.paddingRight),y:parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)}})(e.target);c.value={width:e.contentRect.width+t.x,height:e.contentRect.height+t.y}}),{box:"border-box"});const e=s.value.parentElement;e&&(f.parent=h(e,(()=>{const t=e.getBoundingClientRect();u.value=t.width,p.value=t.left})))},v=r.debounce((()=>{const{scrollY:e}=window,{clientHeight:t,scrollHeight:n}=document.documentElement;l.value=Math.ceil(e+t)>=n}),100),g=e.computed((()=>l.value?"":i.is("shadow"))),x=e.computed((()=>"Android"===n.getDeviceType()?Math.max(o.padding,20):o.padding)),b=e.computed((()=>({width:`${u.value}px`,left:`${p.value}px`,...i.cssVarBlock({"actionbar-padding":`${o.padding}px`,"actionbar-padding-bottom":`${x.value}px`})})));return e.onMounted((()=>{m(),window.addEventListener("scroll",v,{passive:!0})})),e.onUnmounted((()=>{f.resize?.disconnect(),f.parent?.disconnect(),window.removeEventListener("scroll",v)})),(t,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"placeholderRef",ref:s,style:e.normalizeStyle({width:"100%",height:`${e.unref(c).height}px`})},[e.createElementVNode("div",{ref_key:"actionbar",ref:d,style:e.normalizeStyle(e.unref(b)),class:e.normalizeClass([e.unref(i).e("actionbar"),e.unref(g),a.className]),"data-fixed-calc-width":""},[e.renderSlot(t.$slots,"default")],6)],4))}});exports.default=a;
|
2
2
|
//# sourceMappingURL=fixed-action-bar.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"fixed-action-bar.vue.cjs","sources":["../../../../../../packages/components/src/fixed-action-bar/src/fixed-action-bar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"QxsFixedActionBar\",\n};\n</script>\n<script setup lang=\"ts\">\nimport { useNamespace } from \"@qxs-bns/hooks\";\nimport { getDeviceType } from \"@qxs-bns/utils\";\nimport {
|
1
|
+
{"version":3,"file":"fixed-action-bar.vue.cjs","sources":["../../../../../../packages/components/src/fixed-action-bar/src/fixed-action-bar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"QxsFixedActionBar\",\n};\n</script>\n<script setup lang=\"ts\">\nimport { useNamespace } from \"@qxs-bns/hooks\";\nimport { getDeviceType } from \"@qxs-bns/utils\";\nimport { debounce } from \"lodash-es\";\n\ntype ElementSize = { width: number; height: number };\n\nconst props = defineProps({\n padding: {\n type: Number,\n default: 8,\n },\n className: {\n type: String,\n default: \"\",\n },\n});\n\nconst ns = useNamespace(\"fixed-action-bar\");\nconst isBottom = ref(false);\nconst actionbar = ref<HTMLElement | null>(null);\nconst placeholderRef = ref<HTMLElement | null>(null);\n\nconst elementSize = ref<ElementSize>({ width: 0, height: 0 });\nconst parentWidth = ref(0);\nconst elementLeft = ref(0);\n\nconst observers = {\n resize: null as ResizeObserver | null,\n parent: null as ResizeObserver | null,\n};\n\nconst getTotalPadding = (el: HTMLElement) => {\n const style = getComputedStyle(el);\n return {\n x: parseFloat(style.paddingLeft) + parseFloat(style.paddingRight),\n y: parseFloat(style.paddingTop) + parseFloat(style.paddingBottom),\n };\n};\n\nconst createResizeObserver = (\n el: HTMLElement,\n callback: (entry: ResizeObserverEntry) => void,\n options?: ResizeObserverOptions\n) => {\n const observer = new ResizeObserver((entries) => {\n entries.forEach((entry) => requestAnimationFrame(() => callback(entry)));\n });\n observer.observe(el, options);\n return observer;\n};\n\nconst initObservers = () => {\n if (!actionbar.value || !placeholderRef.value) return;\n\n // 主元素尺寸观察\n observers.resize = createResizeObserver(\n actionbar.value,\n (entry) => {\n const padding = getTotalPadding(entry.target as HTMLElement);\n elementSize.value = {\n width: entry.contentRect.width + padding.x,\n height: entry.contentRect.height + padding.y,\n };\n },\n { box: \"border-box\" }\n );\n\n // 父元素观察\n const parent = placeholderRef.value.parentElement;\n if (parent) {\n observers.parent = createResizeObserver(parent, () => {\n const rect = parent.getBoundingClientRect();\n parentWidth.value = rect.width;\n elementLeft.value = rect.left;\n });\n }\n};\n\nconst calculateScrollDetails = debounce(() => {\n const { scrollY } = window;\n const { clientHeight, scrollHeight } = document.documentElement;\n isBottom.value = Math.ceil(scrollY + clientHeight) >= scrollHeight;\n}, 100);\n\nconst shadowClass = computed(() => (!isBottom.value ? ns.is(\"shadow\") : \"\"));\n\nconst paddingBottom = computed(() =>\n getDeviceType() === \"Android\" ? Math.max(props.padding, 20) : props.padding\n);\n\nconst actionbarStyle = computed(() => ({\n width: `${parentWidth.value}px`,\n left: `${elementLeft.value}px`,\n ...ns.cssVarBlock({\n \"actionbar-padding\": `${props.padding}px`,\n \"actionbar-padding-bottom\": `${paddingBottom.value}px`,\n }),\n}));\n\nonMounted(() => {\n initObservers();\n window.addEventListener(\"scroll\", calculateScrollDetails, { passive: true });\n});\n\nonUnmounted(() => {\n observers.resize?.disconnect();\n observers.parent?.disconnect();\n window.removeEventListener(\"scroll\", calculateScrollDetails);\n});\n</script>\n\n<template>\n <div\n ref=\"placeholderRef\"\n :style=\"{ width: '100%', height: `${elementSize.height}px` }\"\n >\n <div\n ref=\"actionbar\"\n :style=\"actionbarStyle\"\n :class=\"[ns.e('actionbar'), shadowClass, className]\"\n data-fixed-calc-width\n >\n <slot />\n </div>\n </div>\n</template>\n"],"names":["name","props","__props","ns","useNamespace","isBottom","ref","actionbar","placeholderRef","elementSize","width","height","parentWidth","elementLeft","observers","resize","parent","createResizeObserver","el","callback","options","observer","ResizeObserver","entries","forEach","entry","requestAnimationFrame","observe","initObservers","value","padding","style","getComputedStyle","x","parseFloat","paddingLeft","paddingRight","y","paddingTop","paddingBottom","getTotalPadding","target","contentRect","box","parentElement","rect","getBoundingClientRect","left","calculateScrollDetails","debounce","scrollY","window","clientHeight","scrollHeight","document","documentElement","Math","ceil","shadowClass","computed","is","getDeviceType","max","actionbarStyle","cssVarBlock","onMounted","addEventListener","passive","onUnmounted","disconnect","removeEventListener"],"mappings":"iMAEEA,KAAM,wGAUR,MAAMC,EAAQC,EAWRC,EAAKC,eAAa,oBAClBC,EAAWC,OAAI,GACfC,EAAYD,MAAwB,MACpCE,EAAiBF,MAAwB,MAEzCG,EAAcH,EAAAA,IAAiB,CAAEI,MAAO,EAAGC,OAAQ,IACnDC,EAAcN,MAAI,GAClBO,EAAcP,MAAI,GAElBQ,EAAY,CAChBC,OAAQ,KACRC,OAAQ,MAWJC,EAAuB,CAC3BC,EACAC,EACAC,KAEA,MAAMC,EAAW,IAAIC,gBAAgBC,IAC3BA,EAAAC,SAASC,GAAUC,uBAAsB,IAAMP,EAASM,MAAO,IAGlE,OADEJ,EAAAM,QAAQT,EAAIE,GACdC,CAAA,EAGHO,EAAgB,KACpB,IAAKrB,EAAUsB,QAAUrB,EAAeqB,MAAO,OAG/Cf,EAAUC,OAASE,EACjBV,EAAUsB,OACTJ,IACO,MAAAK,EA3BY,CAACZ,IACjB,MAAAa,EAAQC,iBAAiBd,GACxB,MAAA,CACLe,EAAGC,WAAWH,EAAMI,aAAeD,WAAWH,EAAMK,cACpDC,EAAGH,WAAWH,EAAMO,YAAcJ,WAAWH,EAAMQ,eACrD,EAsBoBC,CAAgBf,EAAMgB,QACtChC,EAAYoB,MAAQ,CAClBnB,MAAOe,EAAMiB,YAAYhC,MAAQoB,EAAQG,EACzCtB,OAAQc,EAAMiB,YAAY/B,OAASmB,EAAQO,EAC7C,GAEF,CAAEM,IAAK,eAIH,MAAA3B,EAASR,EAAeqB,MAAMe,cAChC5B,IACQF,EAAAE,OAASC,EAAqBD,GAAQ,KACxC,MAAA6B,EAAO7B,EAAO8B,wBACpBlC,EAAYiB,MAAQgB,EAAKnC,MACzBG,EAAYgB,MAAQgB,EAAKE,IAAA,IAC1B,EAICC,EAAyBC,EAAAA,UAAS,KAChC,MAAAC,QAAEA,GAAYC,QACdC,aAAEA,EAAAC,aAAcA,GAAiBC,SAASC,gBAChDlD,EAASwB,MAAQ2B,KAAKC,KAAKP,EAAUE,IAAiBC,CAAA,GACrD,KAEGK,EAAcC,YAAS,IAAQtD,EAASwB,MAA0B,GAAlB1B,EAAGyD,GAAG,YAEtDrB,EAAgBoB,EAAAA,UAAS,IACT,YAApBE,EAAcA,gBAAkBL,KAAKM,IAAI7D,EAAM6B,QAAS,IAAM7B,EAAM6B,UAGhEiC,EAAiBJ,EAAAA,UAAS,KAAO,CACrCjD,MAAO,GAAGE,EAAYiB,UACtBkB,KAAM,GAAGlC,EAAYgB,aAClB1B,EAAG6D,YAAY,CAChB,oBAAqB,GAAG/D,EAAM6B,YAC9B,2BAA4B,GAAGS,EAAcV,uBAIjDoC,EAAAA,WAAU,KACMrC,IACduB,OAAOe,iBAAiB,SAAUlB,EAAwB,CAAEmB,SAAS,GAAM,IAG7EC,EAAAA,aAAY,KACVtD,EAAUC,QAAQsD,aAClBvD,EAAUE,QAAQqD,aACXlB,OAAAmB,oBAAoB,SAAUtB,EAAsB"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),r=require("@element-plus/icons-vue"),l=require("@qxs-bns/hooks")
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("element-plus/es"),t=require("vue"),r=require("@element-plus/icons-vue"),l=require("@qxs-bns/hooks");const i={key:1,class:"image"},a={class:"mask"},o={class:"actions"},s={key:0,class:"el-upload__tip-text"},n={style:{display:"inline-block"}};var c=t.defineComponent({name:"QxsImageUpload",__name:"image-upload",props:{action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},url:{type:String,required:!1,default:""},size:{type:Number,required:!1,default:20},width:{type:Number,required:!1,default:160},accept:{type:String,required:!1,default:"image/jpeg,image/jpg,image/png,image/gif"},height:{type:Number,required:!1,default:90},placeholder:{type:String,required:!1,default:"点击上传图片"},notip:{type:Boolean,required:!1,default:!1},tipText:{type:String,required:!1},beforeUpload:{type:null,required:!1}},emits:["update:url","onSuccess"],setup(c,{emit:p}){const d=c,u=p,h=l.useNamespace("image-upload"),m=t.ref({imageViewerVisible:!1,progress:{preview:"",percent:0}}),g=t.computed((()=>d.accept.split(",").map((e=>e.split("/").pop()))));function f(){m.value.imageViewerVisible=!0}function y(){m.value.imageViewerVisible=!1}function w(){u("update:url","")}const v=t=>{const r=t.name.split(".").at(-1)??"",l=g.value.includes(r),i=t.size/1024/1024<d.size;return l?i?m.value.progress.preview=URL.createObjectURL(t):e.ElMessage.error(`上传图片大小不能超过 ${d.size}MB!`):e.ElMessage.error(`上传图片只支持${g.value.join(" / ")}格式!`),l&&i&&(!d.beforeUpload||d.beforeUpload(t))},V=e=>{m.value.progress.percent=~~e.percent},N=(...e)=>{m.value.progress.preview="",m.value.progress.percent=0,u("onSuccess",...e)};return(l,c)=>{const p=e.ElIcon,d=e.ElImage,u=e.ElProgress,x=e.ElUpload,k=e.ElImageViewer;return t.openBlock(),t.createElementBlock("div",{class:t.normalizeClass(t.unref(h).e("upload-container"))},[t.createVNode(x,{"show-file-list":!1,headers:l.headers,action:l.action,data:l.data,name:l.name,"before-upload":v,"on-progress":V,"on-success":N,drag:"",accept:l.accept,class:t.normalizeClass(t.unref(h).e("image-upload"))},{default:t.withCtx((()=>[""===l.url?(t.openBlock(),t.createBlock(d,{key:0,src:""===l.url?l.placeholder:l.url,style:t.normalizeStyle(`width:${l.width}px;height:${l.height}px;`),fit:"fill"},{error:t.withCtx((()=>[t.createElementVNode("div",{class:"image-slot",style:t.normalizeStyle(`width:${l.width}px;height:${l.height}px;`)},[t.createVNode(p,null,{default:t.withCtx((()=>[t.createVNode(t.unref(r.Plus))])),_:1}),t.createElementVNode("p",null,t.toDisplayString(l.placeholder),1)],4)])),_:1},8,["src","style"])):(t.openBlock(),t.createElementBlock("div",i,[t.createVNode(d,{src:l.url,style:t.normalizeStyle(`width:${l.width}px;height:${l.height}px;`),fit:"fill"},null,8,["src","style"]),t.createElementVNode("div",a,[t.createElementVNode("div",o,[t.createElementVNode("span",{title:"预览",onClick:t.withModifiers(f,["stop"])},[t.createVNode(p,null,{default:t.withCtx((()=>[t.createVNode(t.unref(r.ZoomIn))])),_:1})]),t.createElementVNode("span",{title:"移除",onClick:t.withModifiers(w,["stop"])},[t.createVNode(p,null,{default:t.withCtx((()=>[t.createVNode(t.unref(r.Delete))])),_:1})])])])])),t.withDirectives(t.createElementVNode("div",{class:"progress",style:t.normalizeStyle(`width:${l.width}px;height:${l.height}px;`)},[t.createVNode(d,{src:t.unref(m).progress.preview,style:t.normalizeStyle(`width:${l.width}px;height:${l.height}px;`),fit:"fill"},null,8,["src","style"]),t.createVNode(u,{type:"circle",width:.8*Math.min(l.width,l.height),percentage:t.unref(m).progress.percent},null,8,["width","percentage"])],4),[[t.vShow,""===l.url&&t.unref(m).progress.percent]])])),_:1},8,["headers","action","data","name","accept","class"]),l.notip?t.createCommentVNode("v-if",!0):(t.openBlock(),t.createElementBlock("div",s,[t.createElementVNode("div",n,t.toDisplayString(l.tipText||`上传图片支持 ${t.unref(g).join(" / ")} 格式,且图片大小不超过 ${l.size}MB,建议图片尺寸为 ${l.width}*${l.height}`),1)])),t.unref(m).imageViewerVisible?(t.openBlock(),t.createBlock(k,{key:1,"url-list":[l.url],teleported:"",onClose:y},null,8,["url-list"])):t.createCommentVNode("v-if",!0)],2)}}});exports.default=c;
|
2
2
|
//# sourceMappingURL=image-upload.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"image-upload.vue.cjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, Plus, ZoomIn } from '@element-plus/icons-vue'\nimport { useNamespace } from '@qxs-bns/hooks'\n\ndefineOptions({\n name: 'QxsImageUpload',\n})\nconst props = withDefaults(\n defineProps<{\n action: UploadProps['action']\n headers?: UploadProps['headers']\n data?: UploadProps['data']\n name?: UploadProps['name']\n url?: string\n size?: number\n width?: number\n accept?: string\n height?: number\n placeholder?: string\n notip?: boolean\n tipText?: string\n beforeUpload?: UploadProps['beforeUpload']\n }>(),\n {\n name: 'file',\n url: '',\n size: 20,\n width: 160,\n height: 90,\n placeholder: '点击上传图片',\n notip: false,\n accept: 'image/jpeg,image/jpg,image/png,image/gif',\n },\n)\nconst emits = defineEmits<{\n 'update:url': [\n url: string,\n ]\n 'onSuccess': [\n res: any,\n uploadFile: UploadFile,\n uploadFiles: UploadFiles,\n ]\n}>()\n\nconst ns = useNamespace('image-upload')\n\nconst uploadData = ref({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst exts = computed(() => {\n return props.accept.split(',').map(ext => ext.split('/').pop())\n})\n\n// 预览\nfunction preview() {\n uploadData.value.imageViewerVisible = true\n}\n// 关闭预览\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n// 移除\nfunction remove() {\n emits('update:url', '')\n}\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n const fileName = file.name.split('.')\n const fileExt = fileName.at(-1) ?? ''\n const isTypeOk = exts.value.includes(fileExt)\n const isSizeOk = file.size / 1024 / 1024 < props.size\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持${exts.value.join(' / ')}格式!`)\n }\n\n else if (!isSizeOk) {\n ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)\n }\n else {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n\n return isTypeOk && isSizeOk && (!props.beforeUpload || props.beforeUpload(file))\n}\nconst onProgress: UploadProps['onProgress'] = (file) => {\n uploadData.value.progress.percent = ~~file.percent\n}\nconst onSuccess: UploadProps['onSuccess'] = (...res) => {\n uploadData.value.progress.preview = ''\n uploadData.value.progress.percent = 0\n emits('onSuccess', ...res)\n}\n</script>\n\n<template>\n <div :class=\"ns.e('upload-container')\">\n <el-upload\n :show-file-list=\"false\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-success=\"onSuccess\"\n drag\n :accept=\"accept\"\n :class=\"ns.e('image-upload')\"\n >\n <el-image\n v-if=\"url === ''\"\n :src=\"url === '' ? placeholder : url\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n >\n <template #error>\n <div class=\"image-slot\" :style=\"`width:${width}px;height:${height}px;`\">\n <el-icon>\n <Plus />\n </el-icon>\n <p>\n {{ placeholder }}\n </p>\n </div>\n </template>\n </el-image>\n <div v-else class=\"image\">\n <el-image\n :src=\"url\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n />\n <div class=\"mask\">\n <div class=\"actions\">\n <span title=\"预览\" @click.stop=\"preview\">\n <el-icon><ZoomIn /></el-icon>\n </span>\n <span title=\"移除\" @click.stop=\"remove\">\n <el-icon>\n <Delete />\n </el-icon>\n </span>\n </div>\n </div>\n </div>\n <div\n v-show=\"url === '' && uploadData.progress.percent\"\n class=\"progress\"\n :style=\"`width:${width}px;height:${height}px;`\"\n >\n <el-image\n :src=\"uploadData.progress.preview\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n />\n <el-progress\n type=\"circle\"\n :width=\"Math.min(width, height) * 0.8\"\n :percentage=\"uploadData.progress.percent\"\n />\n </div>\n </el-upload>\n <div v-if=\"!notip\" class=\"el-upload__tip-text\">\n <div style=\"display: inline-block;\">\n {{ tipText || `上传图片支持 ${exts.join(' / ')} 格式,且图片大小不超过 ${size}MB,建议图片尺寸为 ${width}*${height}` }}\n </div>\n </div>\n <el-image-viewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"[url]\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["props","__props","emits","__emit","ns","useNamespace","uploadData","ref","imageViewerVisible","progress","preview","percent","exts","computed","accept","split","map","ext","pop","value","previewClose","remove","handleBeforeUpload","file","fileExt","name","at","isTypeOk","includes","isSizeOk","size","URL","createObjectURL","ElMessage","error","join","beforeUpload","onProgress","onSuccess","res"],"mappings":"
|
1
|
+
{"version":3,"file":"image-upload.vue.cjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, Plus, ZoomIn } from '@element-plus/icons-vue'\nimport { useNamespace } from '@qxs-bns/hooks'\n\ndefineOptions({\n name: 'QxsImageUpload',\n})\nconst props = withDefaults(\n defineProps<{\n action: UploadProps['action']\n headers?: UploadProps['headers']\n data?: UploadProps['data']\n name?: UploadProps['name']\n url?: string\n size?: number\n width?: number\n accept?: string\n height?: number\n placeholder?: string\n notip?: boolean\n tipText?: string\n beforeUpload?: UploadProps['beforeUpload']\n }>(),\n {\n name: 'file',\n url: '',\n size: 20,\n width: 160,\n height: 90,\n placeholder: '点击上传图片',\n notip: false,\n accept: 'image/jpeg,image/jpg,image/png,image/gif',\n },\n)\nconst emits = defineEmits<{\n 'update:url': [\n url: string,\n ]\n 'onSuccess': [\n res: any,\n uploadFile: UploadFile,\n uploadFiles: UploadFiles,\n ]\n}>()\n\nconst ns = useNamespace('image-upload')\n\nconst uploadData = ref({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst exts = computed(() => {\n return props.accept.split(',').map(ext => ext.split('/').pop())\n})\n\n// 预览\nfunction preview() {\n uploadData.value.imageViewerVisible = true\n}\n// 关闭预览\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n// 移除\nfunction remove() {\n emits('update:url', '')\n}\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n const fileName = file.name.split('.')\n const fileExt = fileName.at(-1) ?? ''\n const isTypeOk = exts.value.includes(fileExt)\n const isSizeOk = file.size / 1024 / 1024 < props.size\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持${exts.value.join(' / ')}格式!`)\n }\n\n else if (!isSizeOk) {\n ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)\n }\n else {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n\n return isTypeOk && isSizeOk && (!props.beforeUpload || props.beforeUpload(file))\n}\nconst onProgress: UploadProps['onProgress'] = (file) => {\n uploadData.value.progress.percent = ~~file.percent\n}\nconst onSuccess: UploadProps['onSuccess'] = (...res) => {\n uploadData.value.progress.preview = ''\n uploadData.value.progress.percent = 0\n emits('onSuccess', ...res)\n}\n</script>\n\n<template>\n <div :class=\"ns.e('upload-container')\">\n <el-upload\n :show-file-list=\"false\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-success=\"onSuccess\"\n drag\n :accept=\"accept\"\n :class=\"ns.e('image-upload')\"\n >\n <el-image\n v-if=\"url === ''\"\n :src=\"url === '' ? placeholder : url\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n >\n <template #error>\n <div class=\"image-slot\" :style=\"`width:${width}px;height:${height}px;`\">\n <el-icon>\n <Plus />\n </el-icon>\n <p>\n {{ placeholder }}\n </p>\n </div>\n </template>\n </el-image>\n <div v-else class=\"image\">\n <el-image\n :src=\"url\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n />\n <div class=\"mask\">\n <div class=\"actions\">\n <span title=\"预览\" @click.stop=\"preview\">\n <el-icon><ZoomIn /></el-icon>\n </span>\n <span title=\"移除\" @click.stop=\"remove\">\n <el-icon>\n <Delete />\n </el-icon>\n </span>\n </div>\n </div>\n </div>\n <div\n v-show=\"url === '' && uploadData.progress.percent\"\n class=\"progress\"\n :style=\"`width:${width}px;height:${height}px;`\"\n >\n <el-image\n :src=\"uploadData.progress.preview\"\n :style=\"`width:${width}px;height:${height}px;`\"\n fit=\"fill\"\n />\n <el-progress\n type=\"circle\"\n :width=\"Math.min(width, height) * 0.8\"\n :percentage=\"uploadData.progress.percent\"\n />\n </div>\n </el-upload>\n <div v-if=\"!notip\" class=\"el-upload__tip-text\">\n <div style=\"display: inline-block;\">\n {{ tipText || `上传图片支持 ${exts.join(' / ')} 格式,且图片大小不超过 ${size}MB,建议图片尺寸为 ${width}*${height}` }}\n </div>\n </div>\n <el-image-viewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"[url]\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["props","__props","emits","__emit","ns","useNamespace","uploadData","ref","imageViewerVisible","progress","preview","percent","exts","computed","accept","split","map","ext","pop","value","previewClose","remove","handleBeforeUpload","file","fileExt","name","at","isTypeOk","includes","isSizeOk","size","URL","createObjectURL","ElMessage","error","join","beforeUpload","onProgress","onSuccess","res"],"mappings":"w/BAQA,MAAMA,EAAQC,EA2BRC,EAAQC,EAWRC,EAAKC,eAAa,gBAElBC,EAAaC,EAAAA,IAAI,CACrBC,oBAAoB,EACpBC,SAAU,CACRC,QAAS,GACTC,QAAS,KAIPC,EAAOC,EAAAA,UAAS,IACbb,EAAMc,OAAOC,MAAM,KAAKC,KAAWC,GAAAA,EAAIF,MAAM,KAAKG,UAI3D,SAASR,IACPJ,EAAWa,MAAMX,oBAAqB,CAAA,CAGxC,SAASY,IACPd,EAAWa,MAAMX,oBAAqB,CAAA,CAGxC,SAASa,IACPnB,EAAM,aAAc,GAAE,CAElB,MAAAoB,EAAmDC,IACvD,MACMC,EADWD,EAAKE,KAAKV,MAAM,KACRW,IAAG,IAAO,GAC7BC,EAAWf,EAAKO,MAAMS,SAASJ,GAC/BK,EAAWN,EAAKO,KAAO,KAAO,KAAO9B,EAAM8B,KAajD,OAXKH,EAIKE,EAIRvB,EAAWa,MAAMV,SAASC,QAAUqB,IAAIC,gBAAgBT,GAHxDU,EAAAA,UAAUC,MAAM,cAAclC,EAAM8B,WAJpCG,YAAUC,MAAM,UAAUtB,EAAKO,MAAMgB,KAAK,aAUrCR,GAAYE,KAAc7B,EAAMoC,cAAgBpC,EAAMoC,aAAab,GAAI,EAE1Ec,EAAyCd,IAC7CjB,EAAWa,MAAMV,SAASE,UAAYY,EAAKZ,OAAA,EAEvC2B,EAAsC,IAAIC,KACnCjC,EAAAa,MAAMV,SAASC,QAAU,GACzBJ,EAAAa,MAAMV,SAASE,QAAU,EAC9BT,EAAA,eAAgBqC,EAAG"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";var e=require("vue
|
1
|
+
"use strict";var e=require("vue");exports.useCanvas=function(a){const l=e.ref(null);return a&&(l.value=a.getContext("2d")),{clearCanvas:()=>{l.value&&l.value.clearRect(0,0,a.width,a.height)},drawColor:(e,a,t,n,r)=>{l.value&&(l.value.fillStyle=r,l.value.fillRect(e,a,t,n))},drawImage:(e,a,t,n,r)=>{l.value.drawImage(e,a,t,n,r)},cropCanvas:(e,t,n,r)=>new Promise((u=>{if(l.value){const l=document.createElement("canvas");l.width=n,l.height=r;const i=l.getContext("2d");i?(i.drawImage(a,e,t,n,r,0,0,n,r),l.toBlob((e=>{if(e){const a=new File([e],"cropped_image.png",{type:"image/png"});u(a)}else u(null)}),"image/png")):u(null)}else u(null)}))}};
|
2
2
|
//# sourceMappingURL=composables.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"composables.cjs","sources":["../../../../../../packages/components/src/photo-crop-tool/src/composables.ts"],"sourcesContent":["// useCanvas.ts\nimport type { Ref } from 'vue-demi'\nimport { ref } from 'vue-demi'\n\nexport function useCanvas(canvasElement: HTMLCanvasElement) {\n const context: Ref<CanvasRenderingContext2D | null> = ref(null)\n\n if (canvasElement) {\n context.value = canvasElement.getContext('2d')\n }\n\n const clearCanvas = () => {\n if (context.value) {\n context.value.clearRect(0, 0, canvasElement.width, canvasElement.height)\n }\n }\n\n const drawColor = (x: number, y: number, width: number, height: number, color: string) => {\n if (context.value) {\n context.value.fillStyle = color\n context.value.fillRect(x, y, width, height)\n }\n }\n\n const drawImage = (image: HTMLImageElement, x: number, y: number, width: number, height: number) => {\n context.value!.drawImage(image, x, y, width, height)\n }\n\n const cropCanvas = (x: number, y: number, width: number, height: number): Promise<File | null> => {\n return new Promise((resolve) => {\n if (context.value) {\n const croppedCanvas = document.createElement('canvas')\n croppedCanvas.width = width\n croppedCanvas.height = height\n const croppedContext = croppedCanvas.getContext('2d')\n if (croppedContext) {\n croppedContext.drawImage(canvasElement, x, y, width, height, 0, 0, width, height)\n croppedCanvas.toBlob((blob) => {\n if (blob) {\n const file = new File([blob], 'cropped_image.png', { type: 'image/png' })\n resolve(file)\n }\n else {\n resolve(null)\n }\n }, 'image/png')\n }\n else {\n resolve(null)\n }\n }\n else {\n resolve(null)\n }\n })\n }\n\n return {\n clearCanvas,\n drawColor,\n drawImage,\n cropCanvas,\n }\n}\n"],"names":["canvasElement","context","ref","value","getContext","clearCanvas","clearRect","width","height","drawColor","x","y","color","fillStyle","fillRect","drawImage","image","cropCanvas","Promise","resolve","croppedCanvas","document","createElement","croppedContext","toBlob","blob","file","File","type"],"mappings":"
|
1
|
+
{"version":3,"file":"composables.cjs","sources":["../../../../../../packages/components/src/photo-crop-tool/src/composables.ts"],"sourcesContent":["// useCanvas.ts\nimport type { Ref } from 'vue-demi'\nimport { ref } from 'vue-demi'\n\nexport function useCanvas(canvasElement: HTMLCanvasElement) {\n const context: Ref<CanvasRenderingContext2D | null> = ref(null)\n\n if (canvasElement) {\n context.value = canvasElement.getContext('2d')\n }\n\n const clearCanvas = () => {\n if (context.value) {\n context.value.clearRect(0, 0, canvasElement.width, canvasElement.height)\n }\n }\n\n const drawColor = (x: number, y: number, width: number, height: number, color: string) => {\n if (context.value) {\n context.value.fillStyle = color\n context.value.fillRect(x, y, width, height)\n }\n }\n\n const drawImage = (image: HTMLImageElement, x: number, y: number, width: number, height: number) => {\n context.value!.drawImage(image, x, y, width, height)\n }\n\n const cropCanvas = (x: number, y: number, width: number, height: number): Promise<File | null> => {\n return new Promise((resolve) => {\n if (context.value) {\n const croppedCanvas = document.createElement('canvas')\n croppedCanvas.width = width\n croppedCanvas.height = height\n const croppedContext = croppedCanvas.getContext('2d')\n if (croppedContext) {\n croppedContext.drawImage(canvasElement, x, y, width, height, 0, 0, width, height)\n croppedCanvas.toBlob((blob) => {\n if (blob) {\n const file = new File([blob], 'cropped_image.png', { type: 'image/png' })\n resolve(file)\n }\n else {\n resolve(null)\n }\n }, 'image/png')\n }\n else {\n resolve(null)\n }\n }\n else {\n resolve(null)\n }\n })\n }\n\n return {\n clearCanvas,\n drawColor,\n drawImage,\n cropCanvas,\n }\n}\n"],"names":["canvasElement","context","ref","value","getContext","clearCanvas","clearRect","width","height","drawColor","x","y","color","fillStyle","fillRect","drawImage","image","cropCanvas","Promise","resolve","croppedCanvas","document","createElement","croppedContext","toBlob","blob","file","File","type"],"mappings":"oDAIO,SAAmBA,GAClB,MAAAC,EAAgDC,MAAI,MAoDnD,OAlDHF,IACMC,EAAAE,MAAQH,EAAcI,WAAW,OAiDpC,CACLC,YA/CkBA,KACdJ,EAAQE,OACVF,EAAQE,MAAMG,UAAU,EAAG,EAAGN,EAAcO,MAAOP,EAAcQ,OACnE,EA6CAC,UA1CgBA,CAACC,EAAWC,EAAWJ,EAAeC,EAAgBI,KAClEX,EAAQE,QACVF,EAAQE,MAAMU,UAAYD,EAC1BX,EAAQE,MAAMW,SAASJ,EAAGC,EAAGJ,EAAOC,GACtC,EAuCAO,UApCgBA,CAACC,EAAyBN,EAAWC,EAAWJ,EAAeC,KAC/EP,EAAQE,MAAOY,UAAUC,EAAON,EAAGC,EAAGJ,EAAOC,EAAM,EAoCnDS,WAjCiBA,CAACP,EAAWC,EAAWJ,EAAeC,IAChD,IAAIU,SAASC,IAClB,GAAIlB,EAAQE,MAAO,CACX,MAAAiB,EAAgBC,SAASC,cAAc,UAC7CF,EAAcb,MAAQA,EACtBa,EAAcZ,OAASA,EACjB,MAAAe,EAAiBH,EAAchB,WAAW,MAC5CmB,GACaA,EAAAR,UAAUf,EAAeU,EAAGC,EAAGJ,EAAOC,EAAQ,EAAG,EAAGD,EAAOC,GAC5DY,EAAAI,QAAQC,IACpB,GAAIA,EAAM,CACF,MAAAC,EAAO,IAAIC,KAAK,CAACF,GAAO,oBAAqB,CAAEG,KAAM,cAC3DT,EAAQO,EACV,MAEEP,EAAQ,KACV,GACC,cAGHA,EAAQ,KAEZ,MAEEA,EAAQ,KACV,IAUN"}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/hooks"),l=require("@vueuse/core"),a=require("./composables.cjs")
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),t=require("@qxs-bns/hooks"),l=require("@vueuse/core"),a=require("./composables.cjs");const o=["src"];var u=e.defineComponent({name:"QxsPhotoCropTool",__name:"photo-crop-tool",props:{imgFile:{type:Object,default:()=>null},aspectRatio:{type:String,default:()=>"16 / 9"},defaultWidth:{type:Number,default:()=>320},defaultHeight:{type:Number,default:()=>180},zoomType:{type:String,default:()=>"fixed"}},setup(u,{expose:i}){const n=u;let r=0,s=0,v=0,h=0;const c=t.useNamespace("photo-crop-tool"),f=e.ref(null),p=e.ref(null),d=e.ref(null),m=e.ref(""),g=e.ref(""),y=e.ref({x:0,y:0}),w=e.ref({width:n.defaultWidth,height:n.defaultHeight,x:0,y:0}),{width:x,height:b}=l.useElementSize(f),{width:z}=l.useElementSize(d),{x:E,y:N,style:R}=l.useDraggable(f,{containerElement:p,draggingElement:f,disabled:e.computed((()=>!!g.value)),exact:!0,initialValue:y}),k=e.computed((()=>n.imgFile?URL.createObjectURL(n.imgFile):""));e.watch((()=>n.imgFile),(e=>{e&&!e.type.startsWith("image/")?m.value="文件类型错误":m.value=""}));const H=e.computed((()=>(d.value?.naturalWidth||0)/z.value)),C=e.computed((()=>{const e={left:0,top:0};return"bottom-right"===g.value?(e.left=w.value.x,e.top=w.value.y):"top-left"===g.value?(e.left=w.value.x-x.value,e.top=w.value.y-b.value):"top-right"===g.value?(e.top=w.value.y-b.value,e.left=w.value.x):"bottom-left"===g.value&&(e.left=w.value.x-x.value,e.top=w.value.y),e})),T=e.computed((()=>{const{aspectRatio:e}=n,t={width:`${w.value.width||n.defaultWidth}`,height:`${w.value.height||n.defaultHeight}`,"aspect-ratio":e,top:`${C.value.top}px`,left:`${C.value.left}px`};return"free"===n.zoomType?delete t["aspect-ratio"]:"fixed"===n.zoomType&&delete t.height,c.cssVarBlock(t)}));function F(e){return e*H.value}function M(e,t){const l=p.value?.clientWidth||1/0,a=p.value?.clientHeight||1/0;return{width:Math.min(Math.max(e,0),l),height:Math.min(Math.max(t,0),a)}}function W(e){const t=e.clientX-r,l=e.clientY-s;if("bottom-right"===g.value){if("free"===n.zoomType){const{width:e,height:a}=M(v+t,h+l);w.value.width=e,w.value.height=a}else if("fixed"===n.zoomType){const e=Number.parseFloat(n.aspectRatio.split(" / ")[0])/Number.parseFloat(n.aspectRatio.split(" / ")[1]);let l=v+t,a=l/e;const{width:o,height:u}=M(l,a);u>(p.value?.clientHeight||1/0)&&(a=p.value?.clientHeight||1/0,l=a*e),w.value.width=o,w.value.height=u}}else if("top-left"===g.value){if("free"===n.zoomType){const{width:e,height:a}=M(v-t,h-l);w.value.width=e,w.value.height=a}else if("fixed"===n.zoomType){const e=Number.parseFloat(n.aspectRatio.split(" / ")[0])/Number.parseFloat(n.aspectRatio.split(" / ")[1]);let l=v-t,a=l/e;const{width:o,height:u}=M(l,a);u>(p.value?.clientHeight||1/0)&&(a=p.value?.clientHeight||1/0,l=a*e),w.value.width=o,w.value.height=u}E.value=C.value.left,N.value=C.value.top}else if("top-right"===g.value){if("free"===n.zoomType){const{width:e,height:a}=M(v+t,h-l);w.value.width=e,w.value.height=a}else if("fixed"===n.zoomType){const e=Number.parseFloat(n.aspectRatio.split(" / ")[0])/Number.parseFloat(n.aspectRatio.split(" / ")[1]);let l=v+t,a=l/e;const{width:o,height:u}=M(l,a);u>(p.value?.clientHeight||1/0)&&(a=p.value?.clientHeight||1/0,l=a*e),w.value.width=o,w.value.height=u}E.value=C.value.left,N.value=C.value.top}else if("bottom-left"===g.value){if("free"===n.zoomType){const{width:e,height:a}=M(v-t,h+l);w.value.width=e,w.value.height=a}else if("fixed"===n.zoomType){const e=Number.parseFloat(n.aspectRatio.split(" / ")[0])/Number.parseFloat(n.aspectRatio.split(" / ")[1]);let l=v-t,a=l/e;const{width:o,height:u}=M(l,a);u>(p.value?.clientHeight||1/0)&&(a=p.value?.clientHeight||1/0,l=a*e),w.value.width=o,w.value.height=u}E.value=C.value.left,N.value=C.value.top}e.preventDefault(),e.stopPropagation()}function B(e,t){g.value=t,r=e.clientX,s=e.clientY,v=w.value.width,h=w.value.height,"bottom-right"===t?(w.value.x=E.value,w.value.y=N.value):"top-left"===t?(w.value.x=E.value+x.value,w.value.y=N.value+b.value):"top-right"===t?(w.value.x=E.value,w.value.y=N.value+b.value):"bottom-left"===t&&(w.value.x=E.value+x.value,w.value.y=N.value)}function L(){g.value=""}return document.addEventListener("mouseup",L),document.addEventListener("mousemove",W),e.onMounted((()=>{e.nextTick((()=>{y.value.x=(p.value?.offsetWidth||0)/2-w.value.width/2,y.value.y=(p.value?.offsetHeight||0)/2-w.value.height/2}))})),e.onUnmounted((()=>{k.value&&URL.revokeObjectURL(k.value),document.removeEventListener("mouseup",L),document.removeEventListener("mousemove",W)})),i({crop:async function(e=d.value){let t="transparent";p.value&&(t=window.getComputedStyle(p.value).backgroundColor);const l=document.createElement("canvas");l.width=F(p.value?.clientWidth||0),l.height=F(p.value?.clientHeight||0);const{drawImage:o,cropCanvas:u,drawColor:i}=a.useCanvas(l);return i(0,0,l.width,l.height,t),o(e,F(e.offsetLeft),F(e.offsetTop),e.naturalWidth,e.naturalHeight),await u(F(E.value),F(N.value),F(x.value),F(b.value))},resize:function(){w.value.width=n.defaultWidth,w.value.height=n.defaultHeight,E.value=0,N.value=0}}),(t,l)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"containerBoxRef",ref:p,class:e.normalizeClass([e.unref(c).e("img-box")])},[e.unref(m)?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass([e.unref(c).e("error-message")])},e.toDisplayString(e.unref(m)),3)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("img",{ref_key:"imgRef",ref:d,class:e.normalizeClass([e.unref(c).e("image")]),src:e.unref(k)},null,10,o),e.createElementVNode("div",{ref_key:"cropBoxRef",ref:f,class:e.normalizeClass([e.unref(c).e("crop-tool-box")]),style:e.normalizeStyle([e.unref(T),e.unref(g)?`left: ${e.unref(C).left}px;top: ${e.unref(C).top}px`:e.unref(R)])},[e.createElementVNode("div",{class:e.normalizeClass([e.unref(c).e("top-left")]),onMousedown:l[0]||(l[0]=e=>B(e,"top-left"))},null,34),e.createElementVNode("div",{class:e.normalizeClass([e.unref(c).e("top-right")]),onMousedown:l[1]||(l[1]=e=>B(e,"top-right"))},null,34),e.createElementVNode("div",{class:e.normalizeClass([e.unref(c).e("bottom-right")]),onMousedown:l[2]||(l[2]=e=>B(e,"bottom-right"))},null,34),e.createElementVNode("div",{class:e.normalizeClass([e.unref(c).e("bottom-left")]),onMousedown:l[3]||(l[3]=e=>B(e,"bottom-left"))},null,34)],6)],64))],2))}});exports.default=u;
|
2
2
|
//# sourceMappingURL=photo-crop-tool.vue.cjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"photo-crop-tool.vue.cjs","sources":["../../../../../../packages/components/src/photo-crop-tool/src/photo-crop-tool.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport { useDraggable, useElementSize } from '@vueuse/core'\nimport { useCanvas } from './composables'\n\ndefineOptions({\n name: 'QxsPhotoCropTool',\n})\n\nconst props = defineProps({\n imgFile: {\n type: Object as PropType<File>,\n default: () => null,\n },\n aspectRatio: {\n type: String,\n default: () => '16 / 9',\n },\n defaultWidth: {\n type: Number,\n default: () => 320,\n },\n defaultHeight: {\n type: Number,\n default: () => 180,\n },\n /**\n * free 自由缩放\n * fixed 固定比例缩放\n */\n zoomType: {\n type: String,\n default: () => 'fixed',\n },\n})\nlet startX = 0\nlet startY = 0\nlet startWidth = 0\nlet startHeight = 0\n\nconst ns = useNamespace('photo-crop-tool')\n\nconst cropBoxRef = ref<HTMLElement | null>(null)\nconst containerBoxRef = ref<HTMLElement | null>(null)\nconst imgRef = ref<HTMLImageElement | null>(null)\nconst errorMessage = ref('')\nconst dargPoint = ref('')\nconst initialValue = ref({\n x: 0,\n y: 0,\n})\nconst cropInfo = ref({\n width: props.defaultWidth,\n height: props.defaultHeight,\n x: 0,\n y: 0,\n})\n\nconst { width, height } = useElementSize(cropBoxRef)\nconst { width: imgWidth } = useElementSize(imgRef)\n\nconst { x, y, style } = useDraggable(cropBoxRef, {\n containerElement: containerBoxRef,\n draggingElement: cropBoxRef,\n disabled: computed(() => !!dargPoint.value),\n exact: true,\n initialValue,\n})\n\nconst imageUrl = computed(() => {\n if (!props.imgFile) {\n return ''\n }\n return URL.createObjectURL(props.imgFile)\n})\n\nwatch(\n () => props.imgFile,\n (newFile: File | null) => {\n if (newFile && !newFile.type.startsWith('image/')) {\n errorMessage.value = '文件类型错误'\n }\n else {\n errorMessage.value = ''\n }\n },\n)\n\nconst ratio = computed(() => {\n return (imgRef.value?.naturalWidth || 0) / imgWidth.value\n})\n\nconst customStyle = computed(() => {\n const position = {\n left: 0,\n top: 0,\n }\n if (dargPoint.value === 'bottom-right') {\n position.left = cropInfo.value.x\n position.top = cropInfo.value.y\n }\n else if (dargPoint.value === 'top-left') {\n position.left = cropInfo.value.x - width.value\n position.top = cropInfo.value.y - height.value\n }\n else if (dargPoint.value === 'top-right') {\n position.top = cropInfo.value.y - height.value\n position.left = cropInfo.value.x\n }\n else if (dargPoint.value === 'bottom-left') {\n position.left = cropInfo.value.x - width.value\n position.top = cropInfo.value.y\n }\n return position\n})\n\nconst sizeStyle = computed(() => {\n const { aspectRatio } = props\n\n const style: {\n 'height'?: string\n 'width': string\n 'aspect-ratio'?: string\n 'top': string\n 'left': string\n } = {\n 'width': `${cropInfo.value.width || props.defaultWidth}`,\n 'height': `${cropInfo.value.height || props.defaultHeight}`,\n 'aspect-ratio': aspectRatio,\n 'top': `${customStyle.value.top}px`,\n 'left': `${customStyle.value.left}px`,\n }\n if (props.zoomType === 'free') {\n delete style['aspect-ratio']\n }\n else if (props.zoomType === 'fixed') {\n delete style.height\n }\n return ns.cssVarBlock(style)\n})\n\nfunction zoom(pixel: number) {\n return pixel * ratio.value\n}\nasync function crop(img: HTMLImageElement = imgRef.value!) {\n let backgroundColor = 'transparent'\n if (containerBoxRef.value) {\n backgroundColor = window.getComputedStyle(\n containerBoxRef.value,\n ).backgroundColor\n }\n const canvas = document.createElement('canvas')\n canvas.width = zoom(containerBoxRef.value?.clientWidth || 0)\n canvas.height = zoom(containerBoxRef.value?.clientHeight || 0)\n const { drawImage, cropCanvas, drawColor } = useCanvas(canvas)\n drawColor(0, 0, canvas.width, canvas.height, backgroundColor)\n drawImage(\n img,\n zoom(img.offsetLeft),\n zoom(img.offsetTop),\n img.naturalWidth,\n img.naturalHeight,\n )\n return await cropCanvas(\n zoom(x.value),\n zoom(y.value),\n zoom(width.value),\n zoom(height.value),\n )\n}\n\nfunction checkBoundaries(\n newWidth: number,\n newHeight: number,\n): { width: number, height: number } {\n const maxWidth = containerBoxRef.value?.clientWidth || Infinity\n const maxHeight = containerBoxRef.value?.clientHeight || Infinity\n\n return {\n width: Math.min(Math.max(newWidth, 0), maxWidth),\n height: Math.min(Math.max(newHeight, 0), maxHeight),\n }\n}\n\nfunction mousemove(e: MouseEvent) {\n const deltaX = e.clientX - startX\n const deltaY = e.clientY - startY\n\n if (dargPoint.value === 'bottom-right') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth + deltaX,\n startHeight + deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth + deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n }\n else if (dargPoint.value === 'top-left') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth - deltaX,\n startHeight - deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth - deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n else if (dargPoint.value === 'top-right') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth + deltaX,\n startHeight - deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth + deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n else if (dargPoint.value === 'bottom-left') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth - deltaX,\n startHeight + deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth - deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n e.preventDefault()\n e.stopPropagation()\n}\n\nfunction mousedown(e: MouseEvent, point: string) {\n dargPoint.value = point\n startX = e.clientX\n startY = e.clientY\n startWidth = cropInfo.value.width\n startHeight = cropInfo.value.height\n\n if (point === 'bottom-right') {\n cropInfo.value.x = x.value\n cropInfo.value.y = y.value\n }\n else if (point === 'top-left') {\n cropInfo.value.x = x.value + width.value\n cropInfo.value.y = y.value + height.value\n }\n else if (point === 'top-right') {\n cropInfo.value.x = x.value\n cropInfo.value.y = y.value + height.value\n }\n else if (point === 'bottom-left') {\n cropInfo.value.x = x.value + width.value\n cropInfo.value.y = y.value\n }\n}\n\nfunction mouseup() {\n dargPoint.value = ''\n}\n\nfunction resize() {\n cropInfo.value.width = props.defaultWidth\n cropInfo.value.height = props.defaultHeight\n x.value = 0\n y.value = 0\n}\n\ndocument.addEventListener('mouseup', mouseup)\ndocument.addEventListener('mousemove', mousemove)\n\nonMounted(() => {\n nextTick(() => {\n // 初始化位置\n initialValue.value.x\n = (containerBoxRef.value?.offsetWidth || 0) / 2 - cropInfo.value.width / 2\n initialValue.value.y\n = (containerBoxRef.value?.offsetHeight || 0) / 2\n - cropInfo.value.height / 2\n })\n})\n\nonUnmounted(() => {\n if (imageUrl.value) {\n URL.revokeObjectURL(imageUrl.value)\n }\n document.removeEventListener('mouseup', mouseup)\n document.removeEventListener('mousemove', mousemove)\n})\n\ndefineExpose({\n crop,\n resize,\n})\n</script>\n\n<template>\n <div ref=\"containerBoxRef\" :class=\"[ns.e('img-box')]\">\n <div v-if=\"errorMessage\" :class=\"[ns.e('error-message')]\">\n {{ errorMessage }}\n </div>\n <template v-else>\n <img\n ref=\"imgRef\"\n :class=\"[ns.e('image')]\"\n :src=\"imageUrl\"\n >\n <div\n ref=\"cropBoxRef\"\n :class=\"[ns.e('crop-tool-box')]\"\n :style=\"[\n sizeStyle,\n dargPoint\n ? `left: ${customStyle.left}px;top: ${customStyle.top}px`\n : style,\n ]\"\n >\n <div\n :class=\"[ns.e('top-left')]\"\n @mousedown=\"mousedown($event, 'top-left')\"\n />\n <div\n :class=\"[ns.e('top-right')]\"\n @mousedown=\"mousedown($event, 'top-right')\"\n />\n <div\n :class=\"[ns.e('bottom-right')]\"\n @mousedown=\"mousedown($event, 'bottom-right')\"\n />\n <div\n :class=\"[ns.e('bottom-left')]\"\n @mousedown=\"mousedown($event, 'bottom-left')\"\n />\n </div>\n </template>\n </div>\n</template>\n"],"names":["props","__props","startX","startY","startWidth","startHeight","ns","useNamespace","cropBoxRef","ref","containerBoxRef","imgRef","errorMessage","dargPoint","initialValue","x","y","cropInfo","width","defaultWidth","height","defaultHeight","useElementSize","imgWidth","style","useDraggable","containerElement","draggingElement","disabled","computed","value","exact","imageUrl","imgFile","URL","createObjectURL","watch","newFile","type","startsWith","ratio","naturalWidth","customStyle","position","left","top","sizeStyle","aspectRatio","zoomType","cssVarBlock","zoom","pixel","checkBoundaries","newWidth","newHeight","maxWidth","clientWidth","Infinity","maxHeight","clientHeight","Math","min","max","mousemove","e","deltaX","clientX","deltaY","clientY","Number","parseFloat","split","preventDefault","stopPropagation","mousedown","point","mouseup","document","addEventListener","onMounted","nextTick","offsetWidth","offsetHeight","onUnmounted","revokeObjectURL","removeEventListener","__expose","crop","async","img","backgroundColor","window","getComputedStyle","canvas","createElement","drawImage","cropCanvas","drawColor","useCanvas","offsetLeft","offsetTop","naturalHeight","resize"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"photo-crop-tool.vue.cjs","sources":["../../../../../../packages/components/src/photo-crop-tool/src/photo-crop-tool.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport { useDraggable, useElementSize } from '@vueuse/core'\nimport { useCanvas } from './composables'\n\ndefineOptions({\n name: 'QxsPhotoCropTool',\n})\n\nconst props = defineProps({\n imgFile: {\n type: Object as PropType<File>,\n default: () => null,\n },\n aspectRatio: {\n type: String,\n default: () => '16 / 9',\n },\n defaultWidth: {\n type: Number,\n default: () => 320,\n },\n defaultHeight: {\n type: Number,\n default: () => 180,\n },\n /**\n * free 自由缩放\n * fixed 固定比例缩放\n */\n zoomType: {\n type: String,\n default: () => 'fixed',\n },\n})\nlet startX = 0\nlet startY = 0\nlet startWidth = 0\nlet startHeight = 0\n\nconst ns = useNamespace('photo-crop-tool')\n\nconst cropBoxRef = ref<HTMLElement | null>(null)\nconst containerBoxRef = ref<HTMLElement | null>(null)\nconst imgRef = ref<HTMLImageElement | null>(null)\nconst errorMessage = ref('')\nconst dargPoint = ref('')\nconst initialValue = ref({\n x: 0,\n y: 0,\n})\nconst cropInfo = ref({\n width: props.defaultWidth,\n height: props.defaultHeight,\n x: 0,\n y: 0,\n})\n\nconst { width, height } = useElementSize(cropBoxRef)\nconst { width: imgWidth } = useElementSize(imgRef)\n\nconst { x, y, style } = useDraggable(cropBoxRef, {\n containerElement: containerBoxRef,\n draggingElement: cropBoxRef,\n disabled: computed(() => !!dargPoint.value),\n exact: true,\n initialValue,\n})\n\nconst imageUrl = computed(() => {\n if (!props.imgFile) {\n return ''\n }\n return URL.createObjectURL(props.imgFile)\n})\n\nwatch(\n () => props.imgFile,\n (newFile: File | null) => {\n if (newFile && !newFile.type.startsWith('image/')) {\n errorMessage.value = '文件类型错误'\n }\n else {\n errorMessage.value = ''\n }\n },\n)\n\nconst ratio = computed(() => {\n return (imgRef.value?.naturalWidth || 0) / imgWidth.value\n})\n\nconst customStyle = computed(() => {\n const position = {\n left: 0,\n top: 0,\n }\n if (dargPoint.value === 'bottom-right') {\n position.left = cropInfo.value.x\n position.top = cropInfo.value.y\n }\n else if (dargPoint.value === 'top-left') {\n position.left = cropInfo.value.x - width.value\n position.top = cropInfo.value.y - height.value\n }\n else if (dargPoint.value === 'top-right') {\n position.top = cropInfo.value.y - height.value\n position.left = cropInfo.value.x\n }\n else if (dargPoint.value === 'bottom-left') {\n position.left = cropInfo.value.x - width.value\n position.top = cropInfo.value.y\n }\n return position\n})\n\nconst sizeStyle = computed(() => {\n const { aspectRatio } = props\n\n const style: {\n 'height'?: string\n 'width': string\n 'aspect-ratio'?: string\n 'top': string\n 'left': string\n } = {\n 'width': `${cropInfo.value.width || props.defaultWidth}`,\n 'height': `${cropInfo.value.height || props.defaultHeight}`,\n 'aspect-ratio': aspectRatio,\n 'top': `${customStyle.value.top}px`,\n 'left': `${customStyle.value.left}px`,\n }\n if (props.zoomType === 'free') {\n delete style['aspect-ratio']\n }\n else if (props.zoomType === 'fixed') {\n delete style.height\n }\n return ns.cssVarBlock(style)\n})\n\nfunction zoom(pixel: number) {\n return pixel * ratio.value\n}\nasync function crop(img: HTMLImageElement = imgRef.value!) {\n let backgroundColor = 'transparent'\n if (containerBoxRef.value) {\n backgroundColor = window.getComputedStyle(\n containerBoxRef.value,\n ).backgroundColor\n }\n const canvas = document.createElement('canvas')\n canvas.width = zoom(containerBoxRef.value?.clientWidth || 0)\n canvas.height = zoom(containerBoxRef.value?.clientHeight || 0)\n const { drawImage, cropCanvas, drawColor } = useCanvas(canvas)\n drawColor(0, 0, canvas.width, canvas.height, backgroundColor)\n drawImage(\n img,\n zoom(img.offsetLeft),\n zoom(img.offsetTop),\n img.naturalWidth,\n img.naturalHeight,\n )\n return await cropCanvas(\n zoom(x.value),\n zoom(y.value),\n zoom(width.value),\n zoom(height.value),\n )\n}\n\nfunction checkBoundaries(\n newWidth: number,\n newHeight: number,\n): { width: number, height: number } {\n const maxWidth = containerBoxRef.value?.clientWidth || Infinity\n const maxHeight = containerBoxRef.value?.clientHeight || Infinity\n\n return {\n width: Math.min(Math.max(newWidth, 0), maxWidth),\n height: Math.min(Math.max(newHeight, 0), maxHeight),\n }\n}\n\nfunction mousemove(e: MouseEvent) {\n const deltaX = e.clientX - startX\n const deltaY = e.clientY - startY\n\n if (dargPoint.value === 'bottom-right') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth + deltaX,\n startHeight + deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth + deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n }\n else if (dargPoint.value === 'top-left') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth - deltaX,\n startHeight - deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth - deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n else if (dargPoint.value === 'top-right') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth + deltaX,\n startHeight - deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth + deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n else if (dargPoint.value === 'bottom-left') {\n if (props.zoomType === 'free') {\n const { width, height } = checkBoundaries(\n startWidth - deltaX,\n startHeight + deltaY,\n )\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n else if (props.zoomType === 'fixed') {\n const aspectRatio\n = Number.parseFloat(props.aspectRatio.split(' / ')[0])\n / Number.parseFloat(props.aspectRatio.split(' / ')[1])\n let newWidth = startWidth - deltaX\n let newHeight = newWidth / aspectRatio\n const { width, height } = checkBoundaries(newWidth, newHeight)\n if (height > (containerBoxRef.value?.clientHeight || Infinity)) {\n newHeight = containerBoxRef.value?.clientHeight || Infinity\n newWidth = newHeight * aspectRatio\n }\n cropInfo.value.width = width\n cropInfo.value.height = height\n }\n x.value = customStyle.value.left\n y.value = customStyle.value.top\n }\n e.preventDefault()\n e.stopPropagation()\n}\n\nfunction mousedown(e: MouseEvent, point: string) {\n dargPoint.value = point\n startX = e.clientX\n startY = e.clientY\n startWidth = cropInfo.value.width\n startHeight = cropInfo.value.height\n\n if (point === 'bottom-right') {\n cropInfo.value.x = x.value\n cropInfo.value.y = y.value\n }\n else if (point === 'top-left') {\n cropInfo.value.x = x.value + width.value\n cropInfo.value.y = y.value + height.value\n }\n else if (point === 'top-right') {\n cropInfo.value.x = x.value\n cropInfo.value.y = y.value + height.value\n }\n else if (point === 'bottom-left') {\n cropInfo.value.x = x.value + width.value\n cropInfo.value.y = y.value\n }\n}\n\nfunction mouseup() {\n dargPoint.value = ''\n}\n\nfunction resize() {\n cropInfo.value.width = props.defaultWidth\n cropInfo.value.height = props.defaultHeight\n x.value = 0\n y.value = 0\n}\n\ndocument.addEventListener('mouseup', mouseup)\ndocument.addEventListener('mousemove', mousemove)\n\nonMounted(() => {\n nextTick(() => {\n // 初始化位置\n initialValue.value.x\n = (containerBoxRef.value?.offsetWidth || 0) / 2 - cropInfo.value.width / 2\n initialValue.value.y\n = (containerBoxRef.value?.offsetHeight || 0) / 2\n - cropInfo.value.height / 2\n })\n})\n\nonUnmounted(() => {\n if (imageUrl.value) {\n URL.revokeObjectURL(imageUrl.value)\n }\n document.removeEventListener('mouseup', mouseup)\n document.removeEventListener('mousemove', mousemove)\n})\n\ndefineExpose({\n crop,\n resize,\n})\n</script>\n\n<template>\n <div ref=\"containerBoxRef\" :class=\"[ns.e('img-box')]\">\n <div v-if=\"errorMessage\" :class=\"[ns.e('error-message')]\">\n {{ errorMessage }}\n </div>\n <template v-else>\n <img\n ref=\"imgRef\"\n :class=\"[ns.e('image')]\"\n :src=\"imageUrl\"\n >\n <div\n ref=\"cropBoxRef\"\n :class=\"[ns.e('crop-tool-box')]\"\n :style=\"[\n sizeStyle,\n dargPoint\n ? `left: ${customStyle.left}px;top: ${customStyle.top}px`\n : style,\n ]\"\n >\n <div\n :class=\"[ns.e('top-left')]\"\n @mousedown=\"mousedown($event, 'top-left')\"\n />\n <div\n :class=\"[ns.e('top-right')]\"\n @mousedown=\"mousedown($event, 'top-right')\"\n />\n <div\n :class=\"[ns.e('bottom-right')]\"\n @mousedown=\"mousedown($event, 'bottom-right')\"\n />\n <div\n :class=\"[ns.e('bottom-left')]\"\n @mousedown=\"mousedown($event, 'bottom-left')\"\n />\n </div>\n </template>\n </div>\n</template>\n"],"names":["props","__props","startX","startY","startWidth","startHeight","ns","useNamespace","cropBoxRef","ref","containerBoxRef","imgRef","errorMessage","dargPoint","initialValue","x","y","cropInfo","width","defaultWidth","height","defaultHeight","useElementSize","imgWidth","style","useDraggable","containerElement","draggingElement","disabled","computed","value","exact","imageUrl","imgFile","URL","createObjectURL","watch","newFile","type","startsWith","ratio","naturalWidth","customStyle","position","left","top","sizeStyle","aspectRatio","zoomType","cssVarBlock","zoom","pixel","checkBoundaries","newWidth","newHeight","maxWidth","clientWidth","Infinity","maxHeight","clientHeight","Math","min","max","mousemove","e","deltaX","clientX","deltaY","clientY","Number","parseFloat","split","preventDefault","stopPropagation","mousedown","point","mouseup","document","addEventListener","onMounted","nextTick","offsetWidth","offsetHeight","onUnmounted","revokeObjectURL","removeEventListener","__expose","crop","async","img","backgroundColor","window","getComputedStyle","canvas","createElement","drawImage","cropCanvas","drawColor","useCanvas","offsetLeft","offsetTop","naturalHeight","resize"],"mappings":"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"}
|