jobsys-explore
Version:
Enhanced component based on vant
1 lines • 389 kB
Source Map (JSON)
{"version":3,"file":"jobsys-explore.cjs","sources":["../components/button/ExButton.jsx","../utils/withInstall.js","../components/button/index.js","../components/theme/ExTheme.jsx","../components/theme/index.js","../components/utils.js","../components/form/ExField.jsx","../components/form/PickerWrapper.jsx","../components/provider/ExProvider.jsx","../components/form/ExAddress.jsx","../components/form/ExCascader.jsx","../components/form/ExCheckbox.jsx","../../../node_modules/.pnpm/vant@4.6.6_vue@3.3.4/node_modules/vant/es/utils/format.mjs","../components/form/ExDate.jsx","../components/form/ExDatetime.jsx","../components/form/ExTime.jsx","../components/form/ExNumber.jsx","../components/form/ExRadio.jsx","../components/form/ExSelect.jsx","../components/form/ExSwitch.jsx","../components/form/ExRate.jsx","../components/form/ExSlider.jsx","../components/uploader/ExUploader.jsx","../components/form/ExFieldUploader.jsx","../components/form/ExMatrixRadio.jsx","../components/form/utils.js","../components/form/ExMatrixScale.jsx","../components/form/ExMatrixCheckbox.jsx","../components/form/FormItem.jsx","../components/form/ExForm.jsx","../components/form/index.js","../components/provider/index.js","../components/result/ExResult.jsx","../components/result/index.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/can-promise.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/utils.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/error-correction-level.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/bit-buffer.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/bit-matrix.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/alignment-pattern.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/finder-pattern.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/mask-pattern.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/error-correction-code.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/galois-field.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/polynomial.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/reed-solomon-encoder.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/version-check.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/regex.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/mode.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/version.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/format-info.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/numeric-data.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/alphanumeric-data.js","../../../node_modules/.pnpm/encode-utf8@1.0.3/node_modules/encode-utf8/index.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/byte-data.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/kanji-data.js","../../../node_modules/.pnpm/dijkstrajs@1.0.3/node_modules/dijkstrajs/dijkstra.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/segments.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/core/qrcode.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/renderer/utils.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/renderer/canvas.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/renderer/svg-tag.js","../../../node_modules/.pnpm/qrcode@1.5.3/node_modules/qrcode/lib/browser.js","../components/qrcode/ExQrcode.jsx","../components/qrcode/index.js","../utils/style.js","../components/grid/ExGrid.jsx","../components/search/components/Expand.jsx","../components/search/components/Quick.jsx","../components/search/components/Field.jsx","../components/search/ExSearch.jsx","../components/pagination/ExPagination.jsx","../components/pagination/index.js","../components/search/index.js","../components/uploader/index.js","../components/grid/index.js","../components/decorator/ExDecorator.jsx","../components/decorator/index.js","../components/sector/ExSector.jsx","../components/sector/index.js","../business-components/survey/ExSurvey.jsx","../business-components/survey/index.js","../index.js"],"sourcesContent":["import { defineComponent } from \"vue\"\r\nimport { Button } from \"vant\"\r\nimport \"./index.less\"\r\n\r\n/**\r\n * 主题组件\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExButton\",\r\n\tprops: {\r\n\t\t/**\r\n\t\t * 按钮类型\r\n\t\t * @values primary, success, warning, danger\r\n\t\t */\r\n\t\ttype: { type: String, default: \"default\" },\r\n\r\n\t\t/**\r\n\t\t * 按钮大小\r\n\t\t * @values large, normal, small, mini\r\n\t\t */\r\n\t\tsize: { type: String, default: \"normal\" },\r\n\r\n\t\t/**\r\n\t\t * 失效状态\r\n\t\t */\r\n\t\tdisabled: { type: Boolean, default: false },\r\n\r\n\t\t/**\r\n\t\t * 是否圆形按钮\r\n\t\t */\r\n\t\tround: { type: Boolean, default: true },\r\n\r\n\t\t/**\r\n\t\t * 是否块状按钮\r\n\t\t */\r\n\t\tblock: { type: Boolean, default: true },\r\n\r\n\t\t/**\r\n\t\t * 按钮标签\r\n\t\t */\r\n\t\ttext: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 按钮图标,需要使用\r\n\t\t *\r\n\t\t */\r\n\t\ticon: { type: Object, default: null },\r\n\r\n\t\t/**\r\n\t\t * 按钮图标位置\r\n\t\t * @values left, right\r\n\t\t */\r\n\t\ticonPosition: { type: String, default: \"left\" },\r\n\r\n\t\t/**\r\n\t\t * 请求状态控制器\r\n\t\t * @param {boolean} fetcher.loading 是否加载中\r\n\t\t */\r\n\t\tfetcher: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({ loading: false }),\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * [原生配置](https://vant-contrib.gitee.io/vant/#/zh-CN/button)\r\n\t\t */\r\n\t\tbuttonProps: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({}),\r\n\t\t},\r\n\t},\r\n\temits: [\r\n\t\t/**\r\n\t\t * @event click\r\n\t\t * @param {Event} event 点击事件\r\n\t\t */\r\n\t\t\"click\",\r\n\t],\r\n\r\n\tsetup(props, { emit, slots }) {\r\n\t\tconst onClick = (e) => {\r\n\t\t\t/**\r\n\t\t\t * @event click 点击事件\r\n\t\t\t */\r\n\t\t\temit(\"click\", e)\r\n\t\t}\r\n\r\n\t\tconst defaultLabel = () => {\r\n\t\t\treturn props.text || slots.default?.()\r\n\t\t}\r\n\r\n\t\tconst defaultSlot = () => {\r\n\t\t\tif (props.icon && props.iconPosition === \"left\") {\r\n\t\t\t\treturn [props.icon, defaultLabel()]\r\n\t\t\t} else if (props.icon && props.iconPosition === \"right\") {\r\n\t\t\t\treturn [defaultLabel(), props.icon]\r\n\t\t\t}\r\n\t\t\treturn [defaultLabel()]\r\n\t\t}\r\n\r\n\t\treturn () => (\r\n\t\t\t<Button\r\n\t\t\t\tclass={\"ex-button\"}\r\n\t\t\t\tloading={props.fetcher.loading}\r\n\t\t\t\ttype={props.type}\r\n\t\t\t\tsize={props.size}\r\n\t\t\t\tdisabled={props.disabled}\r\n\t\t\t\tround={props.round}\r\n\t\t\t\tblock={props.block}\r\n\t\t\t\tonClick={onClick}\r\n\t\t\t\t{...props.buttonProps}\r\n\t\t\t>\r\n\t\t\t\t{{\r\n\t\t\t\t\tdefault: () => defaultSlot(),\r\n\t\t\t\t}}\r\n\t\t\t</Button>\r\n\t\t)\r\n\t},\r\n})\r\n","export default (component) => {\r\n\tcomponent.install = (app) => {\r\n\t\tconst name = component.name || component.__name\r\n\t\tapp.component(name, component)\r\n\t}\r\n\treturn component\r\n}\r\n","import _ExButton from \"./ExButton.jsx\"\r\nimport withInstall from \"../../utils/withInstall\"\r\nexport const ExButton = withInstall(_ExButton)\r\nexport default ExButton\r\n","import { defineComponent } from \"vue\"\r\nimport \"./index.less\"\r\n\r\n/**\r\n * 主题组件\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExTheme\",\r\n})\r\n","import _ExTheme from \"./ExTheme.jsx\"\r\nimport withInstall from \"../../utils/withInstall\"\r\nexport const ExTheme = withInstall(_ExTheme)\r\nexport default ExTheme\r\n","import { cloneDeep, isFunction, isNumber, isString } from \"lodash-es\"\r\nimport { watch } from \"vue\"\r\nimport { useCache, useFetch } from \"../hooks\"\r\n\r\n/**\r\n * 通用 field props\r\n */\r\nexport const defaultFieldProps = {\r\n\t/**\r\n\t * 输入框左侧文本\r\n\t */\r\n\tlabel: { type: String, default: \"\" },\r\n\r\n\t/**\r\n\t * 名称,作为提交表单时的标识符\r\n\t */\r\n\tname: { type: String, default: \"\" },\r\n\r\n\t/**\r\n\t * 输入框占位提示文字\r\n\t */\r\n\tplaceholder: { type: String, default: \"请填写\" },\r\n\r\n\t/**\r\n\t * 提示文案\r\n\t */\r\n\thelp: { type: [String, Function], default: \"\" },\r\n\r\n\t/**\r\n\t * 元素的append slot\r\n\t */\r\n\tappend: { type: [String, Function], default: \"\" },\r\n\r\n\t/**\r\n\t * 是否禁用输入框\r\n\t */\r\n\tdisabled: { type: Boolean, default: false },\r\n\r\n\t/**\r\n\t * 是否显示表单必填星号\r\n\t */\r\n\trequired: { type: Boolean, default: false },\r\n\r\n\t/**\r\n\t * 是否展示右侧箭头并开启点击反馈\r\n\t */\r\n\tisLink: { type: Boolean, default: false },\r\n\r\n\t/**\r\n\t * 是否为只读状态,只读状态下无法输入内容\r\n\t */\r\n\treadonly: { type: Boolean, default: false },\r\n\r\n\t/**\r\n\t * 表单校验规则\r\n\t */\r\n\trules: { type: Array, default: null },\r\n\r\n\t/**\r\n\t * 原生 [Field 配置](https://vant-contrib.gitee.io/vant/#/zh-CN/field)\r\n\t */\r\n\tfieldProps: { type: Object, default: () => ({}) },\r\n\r\n\t/**\r\n\t * 原生输入组件的 props\r\n\t */\r\n\tdefaultProps: { type: Object, default: () => ({}) },\r\n}\r\n\r\n/**\r\n * 原生 Field 的 slots\r\n * 用于从组合组件中挑选\r\n */\r\nexport const defaultFieldSlots = {\r\n\tlabel: () => null,\r\n\tinput: () => null,\r\n\t\"left-icon\": () => null,\r\n\t\"right-icon\": () => null,\r\n\tbutton: () => null,\r\n\t\"error-message\": () => null,\r\n\textra: () => null,\r\n}\r\n\r\n/**\r\n * 通用的 options props\r\n */\r\nexport const defaultOptionsProps = {\r\n\t/**\r\n\t * 选项\r\n\t */\r\n\toptions: { type: [Array, Function], default: () => [] },\r\n\r\n\t/**\r\n\t * 选项 url\r\n\t */\r\n\turl: { type: String, default: null },\r\n\r\n\t/**\r\n\t * 缓存url返回的数据\r\n\t */\r\n\turlCache: { type: Boolean, default: true },\r\n\r\n\t/**\r\n\t * 选项获取后的回调\r\n\t */\r\n\tafterFetched: { type: Function, default: null },\r\n}\r\n\r\n/**\r\n * Prepare options for select\r\n *\r\n * @param options\r\n * @return {Array}\r\n */\r\nexport const prepareOptions = (options) => {\r\n\toptions = isFunction(options) ? options() : options\r\n\toptions = cloneDeep(options).map((op) => {\r\n\t\tif (op.children?.length) {\r\n\t\t\top.children = prepareOptions(op.children)\r\n\t\t}\r\n\t\treturn isString(op) || isNumber(op) ? { value: op, label: op, text: op } : { text: op.label, ...op }\r\n\t})\r\n\treturn options\r\n}\r\n\r\n//内部方法,为了useOptionTrait实现单次请求,避免重复请求\r\nconst recordOptionsUrl = {}\r\nconst optionsFetcher = (props) => {\r\n\treturn new Promise((resolve) => {\r\n\t\tuseFetch()\r\n\t\t\t.get(props.url)\r\n\t\t\t.then((items) => {\r\n\t\t\t\tif (props.afterFetched) {\r\n\t\t\t\t\titems = props.afterFetched(items)\r\n\t\t\t\t}\r\n\t\t\t\tresolve(items)\r\n\t\t\t})\r\n\t})\r\n}\r\n/**\r\n * 初始化选项\r\n * @param options\r\n * @param props\r\n * @param {Array|Function} [defaultOptions]\r\n *\r\n * @return void\r\n */\r\nexport const useOptionTrait = async (options, props, defaultOptions) => {\r\n\toptions.value = prepareOptions(props.options)\r\n\r\n\tconst fetchData = async (props) => {\r\n\t\tif (recordOptionsUrl[props.url]) {\r\n\t\t\treturn recordOptionsUrl[props.url]\r\n\t\t}\r\n\t\trecordOptionsUrl[props.url] = optionsFetcher(props)\r\n\r\n\t\tconst result = await recordOptionsUrl[props.url]\r\n\t\trecordOptionsUrl[props.url] = null\r\n\t\treturn new Promise((resolve) => {\r\n\t\t\tresolve(result)\r\n\t\t})\r\n\t}\r\n\r\n\twatch(\r\n\t\t() => props.options,\r\n\t\t() => {\r\n\t\t\toptions.value = prepareOptions(props.options)\r\n\t\t},\r\n\t)\r\n\r\n\tif (!options.value.length) {\r\n\t\tif (props.url) {\r\n\t\t\tif (props.urlCache && useCache(props.url).get()) {\r\n\t\t\t\toptions.value = useCache(props.url).get()\r\n\t\t\t} else {\r\n\t\t\t\tfetchData(props).then((items) => {\r\n\t\t\t\t\toptions.value = items\r\n\t\t\t\t\tif (props.urlCache) {\r\n\t\t\t\t\t\tuseCache(props.url).set(items)\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t}\r\n\t\t} else if (defaultOptions) {\r\n\t\t\toptions.value = defaultOptions\r\n\t\t}\r\n\t}\r\n}\r\n","import { computed, defineComponent, getCurrentInstance, reactive, watch } from \"vue\"\r\nimport { Field, Icon, Popover } from \"vant\"\r\nimport { defaultFieldProps, defaultFieldSlots } from \"../utils\"\r\nimport { omit, pick, isString } from \"lodash-es\"\r\n\r\n/**\r\n * ExField 输入框\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExField\",\r\n\tprops: {\r\n\t\t...defaultFieldProps,\r\n\r\n\t\t/**\r\n\t\t * 输入框内容\r\n\t\t */\r\n\t\tmodelValue: { type: [String, Number, Array, Object, Boolean], default: () => \"\" },\r\n\r\n\t\t/**\r\n\t\t * 输入框类型, 支持原生 input 标签的所有\r\n\t\t */\r\n\t\ttype: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 是否作为 Picker 的 Trigger\r\n\t\t */\r\n\t\tmask: { type: Boolean, default: false },\r\n\t},\r\n\temits: [\"update:modelValue\", \"click\"],\r\n\tsetup(props, { slots, emit }) {\r\n\t\tconst instance = getCurrentInstance()\r\n\t\tconst displayText = instance.parent?.parent?.exposed?.displayText\r\n\r\n\t\tconst state = reactive({\r\n\t\t\tvalue: props.mask ? displayText : props.modelValue,\r\n\t\t\tshowHelp: false,\r\n\t\t})\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => {\r\n\t\t\t\tstate.value = props.modelValue\r\n\t\t\t},\r\n\t\t)\r\n\r\n\t\tconst isLink = computed(() => (props.mask && !props.disabled && !props.readonly ? true : props.isLink))\r\n\t\tconst isReadonly = computed(() => (props.mask ? true : props.readonly))\r\n\r\n\t\tconst onUpdateValue = (value) => {\r\n\t\t\temit(\"update:modelValue\", value)\r\n\t\t}\r\n\r\n\t\t/****************** render **********************/\r\n\r\n\t\tconst helpElem = () => {\r\n\t\t\tif (props.help) {\r\n\t\t\t\treturn (\r\n\t\t\t\t\t<Popover v-model:show={state.showHelp} theme={\"dark\"} placement={\"bottom-start\"}>\r\n\t\t\t\t\t\t{{\r\n\t\t\t\t\t\t\tdefault: () => <div class={\"ex-field__help\"}>{isString(props.help) ? props.help : props.help()}</div>,\r\n\t\t\t\t\t\t\treference: () =>\r\n\t\t\t\t\t\t\t\tprops.help ? (\r\n\t\t\t\t\t\t\t\t\t<span class={\"ex-field__help-handler\"}>\r\n\t\t\t\t\t\t\t\t\t\t<Icon name={\"warning-o\"}></Icon>\r\n\t\t\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t\t\t) : null,\r\n\t\t\t\t\t\t}}\r\n\t\t\t\t\t</Popover>\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t}\r\n\t\tconst labelElem = () => (\r\n\t\t\t<div class={\"ex-field__label\"}>\r\n\t\t\t\t<span>{props.label || slots.label?.()}</span>\r\n\r\n\t\t\t\t{helpElem()}\r\n\t\t\t</div>\r\n\t\t)\r\n\r\n\t\tconst inputElem = () => {\r\n\t\t\tlet inputSlots = omit(slots, Object.keys(defaultFieldSlots))\r\n\t\t\tlet InputElem = slots.input ? slots.input() : null\r\n\r\n\t\t\tif (Object.keys(inputSlots).length) {\r\n\t\t\t\tif (InputElem.length > 1) {\r\n\t\t\t\t\tconsole.warn(\"More than one root element wrapped in ExField with input slots!\")\r\n\t\t\t\t}\r\n\t\t\t\tInputElem = InputElem[0]\r\n\t\t\t\treturn <InputElem>{inputSlots}</InputElem>\r\n\t\t\t}\r\n\t\t\treturn InputElem\r\n\t\t}\r\n\r\n\t\tconst appendElem = () => {\r\n\t\t\tif (props.append) {\r\n\t\t\t\tconst appendResult = isString(props.append) ? props.append : props.append()\r\n\t\t\t\treturn appendResult ? <div class={\"ex-field__append\"}>{appendResult}</div> : null\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t}\r\n\r\n\t\treturn () => {\r\n\t\t\tlet fieldSlots = pick(slots, Object.keys(defaultFieldSlots))\r\n\t\t\tif (!fieldSlots.label) {\r\n\t\t\t\tfieldSlots.label = labelElem\r\n\t\t\t}\r\n\r\n\t\t\tif (fieldSlots.input) {\r\n\t\t\t\tfieldSlots.input = inputElem\r\n\t\t\t}\r\n\r\n\t\t\treturn (\r\n\t\t\t\t<div class={`ex-field`}>\r\n\t\t\t\t\t<Field\r\n\t\t\t\t\t\tv-model={state.value}\r\n\t\t\t\t\t\ttype={props.type}\r\n\t\t\t\t\t\tname={props.name}\r\n\t\t\t\t\t\tplaceholder={props.placeholder}\r\n\t\t\t\t\t\treadonly={isReadonly.value}\r\n\t\t\t\t\t\tdisabled={props.disabled}\r\n\t\t\t\t\t\trequired={props.required}\r\n\t\t\t\t\t\tisLink={isLink.value}\r\n\t\t\t\t\t\trules={props.rules}\r\n\t\t\t\t\t\tonClickInput={() => emit(\"click\")}\r\n\t\t\t\t\t\tonUpdate:modelValue={onUpdateValue}\r\n\t\t\t\t\t\t{...props.fieldProps}\r\n\t\t\t\t\t\tshowWordLimit={isReadonly.value ? false : props.fieldProps?.showWordLimit}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t{{ ...fieldSlots }}\r\n\t\t\t\t\t</Field>\r\n\t\t\t\t\t{appendElem()}\r\n\t\t\t\t</div>\r\n\t\t\t)\r\n\t\t}\r\n\t},\r\n})\r\n","import { defineComponent, ref } from \"vue\"\r\nimport { Popup } from \"vant\"\r\nimport ExField from \"./ExField.jsx\"\r\nimport { omit, pick } from \"lodash-es\"\r\nimport { defaultFieldProps } from \"../utils\"\r\n\r\nexport default defineComponent({\r\n\tname: \"PickerWrapper\",\r\n\r\n\tprops: {\r\n\t\t/**\r\n\t\t * Picker 标题\r\n\t\t */\r\n\t\ttitle: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 是否启用卡片模式\r\n\t\t */\r\n\t\tinset: { type: Boolean, default: false },\r\n\r\n\t\t/**\r\n\t\t * 是否会弹窗\r\n\t\t */\r\n\t\tdisabled: { type: Boolean, default: false },\r\n\r\n\t\t/**\r\n\t\t * 是否显示关闭\r\n\t\t */\r\n\t\tcloseable: { type: Boolean, default: true },\r\n\t},\r\n\temits: [\"close\", \"open\"],\r\n\tsetup: (props, { emit, slots, expose }) => {\r\n\t\tconst showPopup = ref(false)\r\n\r\n\t\tconst onClickWrapper = () => {\r\n\t\t\tif (props.disabled) {\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\t\t\tshowPopup.value = true\r\n\t\t\temit(\"open\")\r\n\t\t}\r\n\r\n\t\tconst close = () => {\r\n\t\t\tshowPopup.value = false\r\n\t\t\temit(\"close\")\r\n\t\t}\r\n\r\n\t\texpose({ close })\r\n\r\n\t\treturn () => {\r\n\t\t\t// 为了让 ExField 的 onClickInput 事件才触发 Popup\r\n\t\t\t// 所以会手动获取 trigger slot 的第一个组件来手动监听 onClick 事件\r\n\t\t\t// 如果以后有需要多个组件的情况,再做调整\r\n\r\n\t\t\tlet TriggerElem = slots.trigger ? slots.trigger() : null\r\n\r\n\t\t\tif (TriggerElem && TriggerElem.length) {\r\n\t\t\t\tTriggerElem = TriggerElem[0]\r\n\t\t\t}\r\n\r\n\t\t\treturn [\r\n\t\t\t\t<span class={\"ex-field-popup-wrapper\"}>\r\n\t\t\t\t\t<TriggerElem onClick={onClickWrapper}></TriggerElem>\r\n\t\t\t\t</span>,\r\n\r\n\t\t\t\t<Popup\r\n\t\t\t\t\tv-model:show={showPopup.value}\r\n\t\t\t\t\tcloseable={props.closeable}\r\n\t\t\t\t\tposition={\"bottom\"}\r\n\t\t\t\t\tround={true}\r\n\t\t\t\t\tteleport={\"body\"}\r\n\t\t\t\t\tcloseOnPopstate={true}\r\n\t\t\t\t\tclass={`ex-field-popup ${props.inset ? \"ex-field-popup-inset\" : \"\"}`}\r\n\t\t\t\t\tsafeAreaInsetBottom={true}\r\n\t\t\t\t\tsafeAreaInsetTop={true}\r\n\t\t\t\t\tonClickOverlay={close}\r\n\t\t\t\t\tonClickCloseIcon={close}\r\n\t\t\t\t>\r\n\t\t\t\t\t{{\r\n\t\t\t\t\t\tdefault: () => [\r\n\t\t\t\t\t\t\tprops.closeable ? (\r\n\t\t\t\t\t\t\t\t<div class={\"ex-field-popup__header\"}>\r\n\t\t\t\t\t\t\t\t\t<h2 class={\"ex-field-popup__title\"}>{props.title}</h2>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t) : null,\r\n\t\t\t\t\t\t\tslots.default?.(),\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t}}\r\n\t\t\t\t</Popup>,\r\n\t\t\t]\r\n\t\t}\r\n\t},\r\n})\r\n\r\nexport const pickerProps = (props) => {\r\n\treturn {\r\n\t\ttitle: props.title || `请选择${props.label}`,\r\n\t\tdisabled: props.readonly || props.disabled,\r\n\t}\r\n}\r\n\r\nexport const pickerSlots = (slots, props) => {\r\n\tlet triggerElem = slots.default ? slots.default() : null\r\n\r\n\tif (!triggerElem) {\r\n\t\tconst fieldProps = pick(props, Object.keys(defaultFieldProps))\r\n\t\t// default slot 是 trigger, 其它的 slots 全部传给 ExField\r\n\t\tconst fieldSlots = omit(slots, \"default\")\r\n\r\n\t\ttriggerElem = (\r\n\t\t\t<ExField {...fieldProps} mask={true}>\r\n\t\t\t\t{fieldSlots}\r\n\t\t\t</ExField>\r\n\t\t)\r\n\t}\r\n\r\n\treturn {\r\n\t\ttrigger: () => triggerElem,\r\n\t}\r\n}\r\n","import { defineComponent, provide } from \"vue\"\r\n\r\nexport const EX_UPLOADER = Symbol(\"EX_UPLOADER\")\r\nexport const EX_ADDRESS = Symbol(\"EX_ADDRESS\")\r\nexport const EX_FORM = Symbol(\"EX_FORM\")\r\nexport const EX_SEARCH = Symbol(\"EX_SEARCH\")\r\nexport const EX_PAGINATION = Symbol(\"EX_PAGINATION\")\r\n\r\n/**\r\n * Explore 配置组件\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExProvider\",\r\n\t/**\r\n\t * @typedef {Object} ProviderProps\r\n\t * @property {UploaderProviderProps} [uploader] `ExUploader` 配置\r\n\t * @property {AddressProviderProps} [address] `ExAddress` 配置\r\n\t * @property {FormProviderProps} [form] `ExForm` 配置\r\n\t * @property {SearchProviderProps} [search] `ExSearch` 配置\r\n\t * @property {PaginationProviderProps} [pagination] `ExPagination` 配置\r\n\t *\r\n\t */\r\n\tprops: {\r\n\t\t/**\r\n\t\t * @typedef {Object} UploaderProviderProps `ExUploader` 配置\r\n\t\t * @property {string} uploadUrl 上传地址\r\n\t\t * @property {UploadFileItem} defaultFileItem 默认文件项\r\n\t\t *\r\n\t\t * @typedef {Object} UploadFileItem 文件项\r\n\t\t * @property {string} [id] 文件 ID\r\n\t\t * @property {string} [name] 文件名\r\n\t\t * @property {string} defaultFileItem.url 文件地址\r\n\t\t * @property {string} defaultFileItem.path 文件路径\r\n\t\t * @property {string} [thumbUrl] 缩略图地址\r\n\t\t */\r\n\t\tuploader: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({\r\n\t\t\t\tuploadUrl: \"\",\r\n\t\t\t\tdefaultFileItem: {\r\n\t\t\t\t\tid: \"id\",\r\n\t\t\t\t\tname: \"name\",\r\n\t\t\t\t\turl: \"url\",\r\n\t\t\t\t\tpath: \"path\",\r\n\t\t\t\t\tthumbUrl: \"thumbUrl\",\r\n\t\t\t\t},\r\n\t\t\t}),\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * @typedef {Object} AddressProviderProps `ExAddress` 配置\r\n\t\t * @property {string} addressUrl 选项请求地址\r\n\t\t * @property {string} displayTextType 显示值的类型。\"all\": 所有, last:最后选中的值\r\n\t\t * @property {Function} [afterFetched] 处理接口返回数据的函数\r\n\t\t * @property {AddressOptionKeys} optionKeys 地址选项键名\r\n\t\t *\r\n\t\t * @typedef {Object} AddressOptionKeys 地址选项键名\r\n\t\t * @property {string} optionKeys.value 选项对应的值\r\n\t\t * @property {string} optionKeys.text 选项文字\r\n\t\t * @property {string} optionKeys.children 子选项列表\r\n\t\t */\r\n\t\taddress: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({\r\n\t\t\t\taddressUrl: \"\",\r\n\t\t\t\tdisplayTextType: \"\",\r\n\t\t\t\tafterFetched: null,\r\n\t\t\t\toptionKeys: {\r\n\t\t\t\t\tvalue: \"code\",\r\n\t\t\t\t\ttext: \"name\",\r\n\t\t\t\t\tchildren: \"children\",\r\n\t\t\t\t},\r\n\t\t\t}),\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * @typedef {Object} FormProviderProps `ExForm` 配置\r\n\t\t * @property {Object} [format] 格式化配置, 如 {date: true} 表示在提交表单时使用 `useFormFormat` 格式所有日期字段\r\n\t\t * @property {Function} [afterFetched] 处理接口返回数据的函数\r\n\t\t */\r\n\t\tform: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({\r\n\t\t\t\tformat: {},\r\n\t\t\t\tafterFetched: null,\r\n\t\t\t}),\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * @typedef {Object} SearchProviderProps `ExSearch` 配置\r\n\t\t * @property {Object} [maskClass] 定制伪 Input 样式\r\n\t\t * @property {Object} [inputClass] 弹层中 Input 的样式\r\n\t\t */\r\n\t\tsearch: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({\r\n\t\t\t\tmaskClass: \"\",\r\n\t\t\t\tinputClass: \"\",\r\n\t\t\t}),\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * @typedef {Object} PaginationRes\r\n\t\t * @property {Array} items 数据\r\n\t\t * @property {number} currentPage 当前页码\r\n\t\t * @property {number} totalSize 总条数\r\n\t\t * @property {String} [errorMessage] 错误信息\r\n\t\t */\r\n\r\n\t\t/**\r\n * @typedef {Object} PaginationProviderProps `ExPagination` 配置\r\n * @property {function():PaginationRes} [afterFetched] 处理接口返回数据的函数\r\n * @property {PaginationRequestKeys} [requestKeys] 请求参数键名\r\n * /\r\n\r\n /**\r\n * @typedef {Object} PaginationRequestKeys 请求参数键名\r\n * @property {string} [currentPage] 当前页码\r\n * @property {string} [pageSize] 每页条数\r\n */\r\n\t\tpagination: {\r\n\t\t\ttype: Object,\r\n\t\t\tdefault: () => ({\r\n\t\t\t\tafterFetched: null,\r\n\t\t\t\trequestKeys: {\r\n\t\t\t\t\tcurrentPage: \"currentPage\",\r\n\t\t\t\t\tpageSize: \"pageSize\",\r\n\t\t\t\t},\r\n\t\t\t}),\r\n\t\t},\r\n\t},\r\n\tsetup(props, { slots }) {\r\n\t\tprovide(EX_UPLOADER, {\r\n\t\t\tuploadUrl: props.uploader?.uploadUrl || \"\",\r\n\t\t\tdefaultFileItem: {\r\n\t\t\t\tid: \"id\",\r\n\t\t\t\tname: \"name\",\r\n\t\t\t\turl: \"url\",\r\n\t\t\t\tpath: \"path\",\r\n\t\t\t\tthumbUrl: \"thumbUrl\",\r\n\t\t\t\t...props.uploader?.defaultFileItem,\r\n\t\t\t},\r\n\t\t})\r\n\t\tprovide(EX_ADDRESS, {\r\n\t\t\taddressUrl: props.address?.addressUrl || \"\",\r\n\t\t\tdisplayTextType: props.address?.displayTextType || \"\",\r\n\t\t\tafterFetched: props.address?.afterFetched,\r\n\t\t\toptionKeys: {\r\n\t\t\t\tvalue: \"code\",\r\n\t\t\t\ttext: \"name\",\r\n\t\t\t\tchildren: \"children\",\r\n\t\t\t\t...props.address?.optionKeys,\r\n\t\t\t},\r\n\t\t})\r\n\t\tprovide(EX_FORM, { format: {}, ...props.form })\r\n\t\tprovide(EX_SEARCH, {\r\n\t\t\tmaskClass: \"\",\r\n\t\t\tinputClass: \"\",\r\n\t\t\t...props.search,\r\n\t\t})\r\n\t\tprovide(EX_PAGINATION, {\r\n\t\t\tafterFetched: props.pagination?.afterFetched,\r\n\t\t\trequestKeys: {\r\n\t\t\t\tcurrentPage: \"currentPage\",\r\n\t\t\t\tpageSize: \"pageSize\",\r\n\t\t\t\t...props.pagination?.requestKeys,\r\n\t\t\t},\r\n\t\t})\r\n\r\n\t\treturn () => <div>{slots.default?.()}</div>\r\n\t},\r\n})\r\n","import { computed, defineComponent, inject, ref, watch } from \"vue\"\r\nimport { Cascader } from \"vant\"\r\nimport localData from \"./addressData.json\"\r\nimport PickerWrapper, { pickerProps, pickerSlots } from \"./PickerWrapper.jsx\"\r\nimport { defaultFieldProps, defaultOptionsProps, useOptionTrait } from \"../utils\"\r\nimport { cloneDeep, isArray, last } from \"lodash-es\"\r\nimport { useFindTextsFromPath } from \"../../hooks\"\r\nimport { EX_ADDRESS } from \"../provider/ExProvider.jsx\"\r\n\r\n/**\r\n * 地址组件\r\n *\r\n * 数据优先级:`dataSource` > `url` > `本地数据`\r\n *\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExAddress\",\r\n\tprops: {\r\n\t\t...defaultOptionsProps,\r\n\t\t...defaultFieldProps,\r\n\r\n\t\tmodelValue: { type: [String, Number, Array], default: () => [] },\r\n\r\n\t\t/**\r\n\t\t * 标题\r\n\t\t */\r\n\t\ttitle: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 生成哪个级别的数据\r\n\t\t * 1: 省, 2: 省市, 3: 省市区\r\n\t\t */\r\n\t\tlevel: { type: Number, default: 3 },\r\n\r\n\t\t/**\r\n\t\t * 显示值的类型\r\n\t\t * 空值或all: 所有, last:最后\r\n\t\t */\r\n\t\tdisplayTextType: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 是否把选项的值返回到modelValue\r\n\t\t */\r\n\t\ttextInValue: { type: Boolean, default: false },\r\n\t},\r\n\temits: [\"update:modelValue\"],\r\n\tsetup(props, { emit, slots, expose }) {\r\n\t\tconst addressProvider = inject(EX_ADDRESS, () => ({}))\r\n\t\tconst defaultAddressUrl = addressProvider.addressUrl || \"\"\r\n\t\tconst defaultDisplayTextType = addressProvider.displayTextType || \"\"\r\n\t\tconst defaultAfterFetched = addressProvider.afterFetched || \"\"\r\n\t\tconst optionKeys = addressProvider.optionKeys || {}\r\n\r\n\t\tconst { text: textKey, value: valueKey, children: childrenKey } = optionKeys\r\n\r\n\t\tconst componentValue = ref(\"\")\r\n\r\n\t\tconst setModelValue = () => {\r\n\t\t\tlet value = isArray(props.modelValue) ? last(props.modelValue) : props.modelValue\r\n\t\t\tif (props.textInValue && value) {\r\n\t\t\t\tvalue = value[valueKey]\r\n\t\t\t}\r\n\t\t\tcomponentValue.value = value\r\n\t\t}\r\n\t\tsetModelValue()\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => setModelValue(),\r\n\t\t)\r\n\r\n\t\tconst pickerRef = ref(null)\r\n\t\tconst options = ref([])\r\n\r\n\t\tconst displayText = computed(() => {\r\n\t\t\tif (props.modelValue.length === 0) {\r\n\t\t\t\treturn \"\"\r\n\t\t\t}\r\n\t\t\tconst displayTextType = props.displayTextType || defaultDisplayTextType\r\n\r\n\t\t\t//textInValue状态下的初始值\r\n\t\t\tif (props.textInValue && props.modelValue && props.modelValue.length === 1) {\r\n\t\t\t\treturn last(props.modelValue)[textKey]\r\n\t\t\t}\r\n\r\n\t\t\t//反向赋值\r\n\t\t\tconst mValue = props.textInValue ? props.modelValue.map((item) => item[valueKey]) : props.modelValue\r\n\t\t\tconst optionsTexts = useFindTextsFromPath(options.value, mValue, {\r\n\t\t\t\tvalue: valueKey,\r\n\t\t\t\tchildren: childrenKey,\r\n\t\t\t\tlabel: textKey,\r\n\t\t\t})\r\n\r\n\t\t\treturn displayTextType === \"last\" ? last(optionsTexts) : optionsTexts.join(\"/\")\r\n\t\t})\r\n\r\n\t\t//把默认值赋值给props\r\n\t\tconst cloneProps = cloneDeep(props)\r\n\t\tif (!cloneProps.url && defaultAddressUrl) {\r\n\t\t\tcloneProps.url = defaultAddressUrl\r\n\t\t}\r\n\t\tif (!cloneProps.afterFetched && defaultAfterFetched) {\r\n\t\t\tcloneProps.afterFetched = defaultAfterFetched\r\n\t\t}\r\n\t\t//先处理好 options\r\n\t\tconst dealOptions = () => {\r\n\t\t\tuseOptionTrait(options, cloneProps, localData)\r\n\t\t}\r\n\t\tdealOptions()\r\n\r\n\t\twatch(\r\n\t\t\t() => props.options,\r\n\t\t\t() => {\r\n\t\t\t\tdealOptions()\r\n\t\t\t},\r\n\t\t)\r\n\r\n\t\tconst onFinish = ({ selectedOptions }) => {\r\n\t\t\tpickerRef.value.close()\r\n\t\t\temit(\"update:modelValue\", props.textInValue ? selectedOptions : selectedOptions.map((item) => item[valueKey]))\r\n\t\t}\r\n\r\n\t\texpose({ displayText })\r\n\r\n\t\t/********** render **********/\r\n\r\n\t\treturn () => (\r\n\t\t\t<PickerWrapper ref={pickerRef} {...pickerProps(props)}>\r\n\t\t\t\t{{\r\n\t\t\t\t\t...pickerSlots(slots, props),\r\n\t\t\t\t\tdefault: () => (\r\n\t\t\t\t\t\t<Cascader\r\n\t\t\t\t\t\t\tv-model={componentValue.value}\r\n\t\t\t\t\t\t\tfieldNames={{ text: textKey, value: valueKey, children: childrenKey }}\r\n\t\t\t\t\t\t\tcloseable={false}\r\n\t\t\t\t\t\t\tshowHeader={false}\r\n\t\t\t\t\t\t\toptions={options.value}\r\n\t\t\t\t\t\t\tonFinish={onFinish}\r\n\t\t\t\t\t\t\t{...props.defaultProps}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t),\r\n\t\t\t\t}}\r\n\t\t\t</PickerWrapper>\r\n\t\t)\r\n\t},\r\n})\r\n\r\n/**\r\n *\r\n * 根据地址编码获取完整的地址编码\r\n *\r\n * @param code\r\n * @param {number} [level] 地址级别: 1: 省, 2: 省市, 3: 省市区\r\n * @return {string[]|(string|*)[]|*[]}\r\n */\r\nexport function useAddressFullCode(code, level) {\r\n\tcode += \"\"\r\n\tif (code && code.length === 6) {\r\n\t\tif (!level) {\r\n\t\t\tif (/0000$/.test(code)) {\r\n\t\t\t\tlevel = 1\r\n\t\t\t} else if (/00$/.test(code)) {\r\n\t\t\t\tlevel = 2\r\n\t\t\t} else {\r\n\t\t\t\tlevel = 3\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (level === 1) {\r\n\t\t\treturn [`${code.substr(0, 2)}0000`]\r\n\t\t}\r\n\t\tif (level === 2) {\r\n\t\t\treturn [`${code.substr(0, 2)}0000`, `${code.substr(0, 4)}00`]\r\n\t\t}\r\n\t\tif (level === 3) {\r\n\t\t\treturn [`${code.substr(0, 2)}0000`, `${code.substr(0, 4)}00`, code]\r\n\t\t}\r\n\t}\r\n\treturn []\r\n}\r\n\r\n/**\r\n * 根据地址编码获取完整的地址名称\r\n * @param code\r\n * @param {number} [level] 地址级别: 1: 省, 2: 省市, 3: 省市区\r\n * @return {*[]}\r\n */\r\nexport function useAddressNameFormCode(code, level) {\r\n\tif (!isArray(code)) {\r\n\t\tcode = useAddressFullCode(code, level)\r\n\t}\r\n\treturn useFindTextsFromPath(localData, code, { value: \"code\", label: \"name\", children: \"children\" })\r\n}\r\n\r\nexport const addressData = localData\r\n","import { computed, defineComponent, ref, watch } from \"vue\"\r\nimport PickerWrapper, { pickerProps, pickerSlots } from \"./PickerWrapper.jsx\"\r\nimport { Button, Cascader, Search } from \"vant\"\r\nimport { defaultFieldProps, defaultOptionsProps, useOptionTrait } from \"../utils\"\r\nimport { useFindParentLabels } from \"../../hooks\"\r\nimport { cloneDeep, isArray, last } from \"lodash-es\"\r\n\r\n/**\r\n * ExCascader 级联选择\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExCascader\",\r\n\tprops: {\r\n\t\t...defaultOptionsProps,\r\n\t\t...defaultFieldProps,\r\n\r\n\t\tmodelValue: { type: [Array, String], default: () => [] },\r\n\r\n\t\t/**\r\n\t\t * 标题\r\n\t\t */\r\n\t\ttitle: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 是否显示清除按钮\r\n\t\t */\r\n\t\tclearable: { type: Boolean, default: false },\r\n\r\n\t\t/**\r\n\t\t * 显示值的类型\r\n\t\t * 空值或all: 所有, last:最后\r\n\t\t */\r\n\t\tdisplayTextType: { type: String, default: \"\" },\r\n\r\n\t\t/**\r\n\t\t * 是否把选项的值返回到modelValue\r\n\t\t */\r\n\t\ttextInValue: { type: Boolean, default: false },\r\n\t},\r\n\temits: [\"update:modelValue\", \"change\"],\r\n\tsetup(props, { emit, slots, expose }) {\r\n\t\tconst componentValue = ref(\"\")\r\n\r\n\t\tconst setModelValue = () => {\r\n\t\t\tlet value = isArray(props.modelValue) ? last(props.modelValue) : props.modelValue\r\n\t\t\tif (props.textInValue && value) {\r\n\t\t\t\tvalue = value.value\r\n\t\t\t}\r\n\t\t\tcomponentValue.value = value\r\n\t\t}\r\n\t\tsetModelValue()\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => setModelValue(),\r\n\t\t)\r\n\r\n\t\tconst pickerRef = ref(null)\r\n\r\n\t\tconst options = ref([]) //整理后的原始 Options\r\n\t\tconst shownOptions = ref([]) //根据 keyword 过滤后的 Options\r\n\t\tconst keyword = ref(\"\")\r\n\r\n\t\t//先处理好 options\r\n\t\tconst dealOptions = () => {\r\n\t\t\tuseOptionTrait(options, props)\r\n\t\t\tshownOptions.value = options.value\r\n\t\t}\r\n\t\tdealOptions()\r\n\r\n\t\twatch(\r\n\t\t\t() => props.options,\r\n\t\t\t() => {\r\n\t\t\t\tdealOptions()\r\n\t\t\t},\r\n\t\t)\r\n\r\n\t\twatch(\r\n\t\t\t() => keyword.value,\r\n\t\t\t(keyword) => {\r\n\t\t\t\tcomponentValue.value = \"\"\r\n\t\t\t\tif (keyword) {\r\n\t\t\t\t\tshownOptions.value = filterByText(cloneDeep(options.value), keyword)\r\n\t\t\t\t} else {\r\n\t\t\t\t\tshownOptions.value = options.value\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t)\r\n\r\n\t\tconst filterByText = (data, keyword) => {\r\n\t\t\t// 递归函数,用于过滤每一层级的数据\r\n\t\t\tfunction filterRecursively(items) {\r\n\t\t\t\treturn items.filter((item) => {\r\n\t\t\t\t\t// 判断是否包含关键字\r\n\t\t\t\t\tlet hasKeyword = item.text.toLowerCase().includes(keyword.toLowerCase())\r\n\t\t\t\t\tif (item.children && item.children.length) {\r\n\t\t\t\t\t\titem.children = filterRecursively(item.children)\r\n\t\t\t\t\t\tif (item.children.length) {\r\n\t\t\t\t\t\t\thasKeyword = true\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// 如果包含关键字,或者有子级包含关键字,则保留该项\r\n\t\t\t\t\treturn hasKeyword\r\n\t\t\t\t})\r\n\t\t\t}\r\n\r\n\t\t\t// 调用递归函数开始过滤\r\n\t\t\treturn filterRecursively(data)\r\n\t\t}\r\n\r\n\t\tconst displayText = computed(() => {\r\n\t\t\tif (!componentValue.value) {\r\n\t\t\t\treturn \"\"\r\n\t\t\t}\r\n\r\n\t\t\tconst labels = useFindParentLabels(options.value, componentValue.value, props.defaultProps?.fieldNames)\r\n\r\n\t\t\treturn labels ? (props.displayTextType === \"last\" ? last(labels) : labels.join(\"/\")) : \"\"\r\n\t\t})\r\n\r\n\t\tconst onFinish = ({ selectedOptions }) => {\r\n\t\t\tconst value = props.textInValue ? selectedOptions : selectedOptions.map((item) => item.value)\r\n\t\t\temit(\"change\", value)\r\n\t\t\temit(\"update:modelValue\", value)\r\n\t\t\tpickerRef.value.close()\r\n\t\t}\r\n\r\n\t\tconst onClear = () => {\r\n\t\t\temit(\"change\", [])\r\n\t\t\temit(\"update:modelValue\", [])\r\n\t\t\tpickerRef.value.close()\r\n\t\t}\r\n\r\n\t\texpose({ displayText })\r\n\r\n\t\treturn () => (\r\n\t\t\t<PickerWrapper ref={pickerRef} {...pickerProps(props)}>\r\n\t\t\t\t{{\r\n\t\t\t\t\t...pickerSlots(slots, props),\r\n\t\t\t\t\tdefault: () => [\r\n\t\t\t\t\t\t<Cascader\r\n\t\t\t\t\t\t\tclass={\"ex-cascader\"}\r\n\t\t\t\t\t\t\tv-model={componentValue.value}\r\n\t\t\t\t\t\t\tcloseable={false}\r\n\t\t\t\t\t\t\tshowHeader={true}\r\n\t\t\t\t\t\t\toptions={shownOptions.value}\r\n\t\t\t\t\t\t\tonFinish={onFinish}\r\n\t\t\t\t\t\t\t{...props.defaultProps}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{{\r\n\t\t\t\t\t\t\t\ttitle: () => {\r\n\t\t\t\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t\t\t\t<Search shape={\"round\"} placeholder={\"选项搜索\"} v-model={keyword.value} style={{ width: \"100%\" }}></Search>\r\n\t\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t</Cascader>,\r\n\t\t\t\t\t\tprops.clearable ? (\r\n\t\t\t\t\t\t\t<div class={\"ex-field-popup__clear-btn\"}>\r\n\t\t\t\t\t\t\t\t<Button block type={\"primary\"} plain={true} round={true} onClick={onClear}>\r\n\t\t\t\t\t\t\t\t\t清除\r\n\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t) : null,\r\n\t\t\t\t\t],\r\n\t\t\t\t}}\r\n\t\t\t</PickerWrapper>\r\n\t\t)\r\n\t},\r\n})\r\n","import { defineComponent, ref, watch } from \"vue\"\r\nimport { defaultFieldProps, defaultOptionsProps, useOptionTrait } from \"../utils\"\r\nimport { Checkbox, CheckboxGroup } from \"vant\"\r\nimport ExField from \"./ExField.jsx\"\r\nimport { pick } from \"lodash-es\"\r\n\r\n/**\r\n * ExCheckbox 多选\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExCheckbox\",\r\n\tprops: {\r\n\t\t...defaultFieldProps,\r\n\t\t...defaultOptionsProps,\r\n\r\n\t\tmodelValue: { type: Array, default: () => [] },\r\n\t},\r\n\temits: [\"update:modelValue\"],\r\n\tsetup(props, { emit, slots }) {\r\n\t\tconst componentValue = ref(props.modelValue)\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => (componentValue.value = props.modelValue),\r\n\t\t)\r\n\r\n\t\tconst options = ref([])\r\n\r\n\t\tuseOptionTrait(options, props)\r\n\r\n\t\tconst onChange = (value) => {\r\n\t\t\temit(\"update:modelValue\", value)\r\n\t\t}\r\n\r\n\t\tconst fieldProps = pick(props, Object.keys(defaultFieldProps))\r\n\r\n\t\treturn () => (\r\n\t\t\t<ExField {...fieldProps}>\r\n\t\t\t\t{{\r\n\t\t\t\t\t...slots,\r\n\t\t\t\t\tinput: () => (\r\n\t\t\t\t\t\t<CheckboxGroup\r\n\t\t\t\t\t\t\tv-model={componentValue.value}\r\n\t\t\t\t\t\t\tdisabled={props.disabled || props.readonly}\r\n\t\t\t\t\t\t\t{...props.defaultProps}\r\n\t\t\t\t\t\t\tonChange={onChange}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{{\r\n\t\t\t\t\t\t\t\tdefault: () =>\r\n\t\t\t\t\t\t\t\t\toptions.value.map((option) => <Checkbox name={option.value}>{{ default: () => option.text }}</Checkbox>),\r\n\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t</CheckboxGroup>\r\n\t\t\t\t\t),\r\n\t\t\t\t}}\r\n\t\t\t</ExField>\r\n\t\t)\r\n\t},\r\n})\r\n","import { inBrowser } from \"./basic.mjs\";\nimport { windowWidth, windowHeight } from \"./dom.mjs\";\nimport { isDef, isNumeric } from \"./basic.mjs\";\nfunction addUnit(value) {\n if (isDef(value)) {\n return isNumeric(value) ? `${value}px` : String(value);\n }\n return void 0;\n}\nfunction getSizeStyle(originSize) {\n if (isDef(originSize)) {\n if (Array.isArray(originSize)) {\n return {\n width: addUnit(originSize[0]),\n height: addUnit(originSize[1])\n };\n }\n const size = addUnit(originSize);\n return {\n width: size,\n height: size\n };\n }\n}\nfunction getZIndexStyle(zIndex) {\n const style = {};\n if (zIndex !== void 0) {\n style.zIndex = +zIndex;\n }\n return style;\n}\nlet rootFontSize;\nfunction getRootFontSize() {\n if (!rootFontSize) {\n const doc = document.documentElement;\n const fontSize = doc.style.fontSize || window.getComputedStyle(doc).fontSize;\n rootFontSize = parseFloat(fontSize);\n }\n return rootFontSize;\n}\nfunction convertRem(value) {\n value = value.replace(/rem/g, \"\");\n return +value * getRootFontSize();\n}\nfunction convertVw(value) {\n value = value.replace(/vw/g, \"\");\n return +value * windowWidth.value / 100;\n}\nfunction convertVh(value) {\n value = value.replace(/vh/g, \"\");\n return +value * windowHeight.value / 100;\n}\nfunction unitToPx(value) {\n if (typeof value === \"number\") {\n return value;\n }\n if (inBrowser) {\n if (value.includes(\"rem\")) {\n return convertRem(value);\n }\n if (value.includes(\"vw\")) {\n return convertVw(value);\n }\n if (value.includes(\"vh\")) {\n return convertVh(value);\n }\n }\n return parseFloat(value);\n}\nconst camelizeRE = /-(\\w)/g;\nconst camelize = (str) => str.replace(camelizeRE, (_, c) => c.toUpperCase());\nconst kebabCase = (str) => str.replace(/([A-Z])/g, \"-$1\").toLowerCase().replace(/^-/, \"\");\nfunction padZero(num, targetLength = 2) {\n let str = num + \"\";\n while (str.length < targetLength) {\n str = \"0\" + str;\n }\n return str;\n}\nconst clamp = (num, min, max) => Math.min(Math.max(num, min), max);\nfunction trimExtraChar(value, char, regExp) {\n const index = value.indexOf(char);\n if (index === -1) {\n return value;\n }\n if (char === \"-\" && index !== 0) {\n return value.slice(0, index);\n }\n return value.slice(0, index + 1) + value.slice(index).replace(regExp, \"\");\n}\nfunction formatNumber(value, allowDot = true, allowMinus = true) {\n if (allowDot) {\n value = trimExtraChar(value, \".\", /\\./g);\n } else {\n value = value.split(\".\")[0];\n }\n if (allowMinus) {\n value = trimExtraChar(value, \"-\", /-/g);\n } else {\n value = value.replace(/-/, \"\");\n }\n const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g;\n return value.replace(regExp, \"\");\n}\nfunction addNumber(num1, num2) {\n const cardinal = 10 ** 10;\n return Math.round((num1 + num2) * cardinal) / cardinal;\n}\nexport {\n addNumber,\n addUnit,\n camelize,\n clamp,\n formatNumber,\n getSizeStyle,\n getZIndexStyle,\n kebabCase,\n padZero,\n unitToPx\n};\n","import { computed, defineComponent, ref, watch } from \"vue\"\r\nimport PickerWrapper, { pickerSlots } from \"./PickerWrapper.jsx\"\r\nimport { DatePicker } from \"vant\"\r\nimport { padZero } from \"vant/es/utils\"\r\nimport { defaultFieldProps } from \"../utils\"\r\nimport { isUndefined } from \"lodash-es\"\r\nimport { isDayjs } from \"dayjs\"\r\n\r\n/**\r\n * ExDate 日期选择\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExDate\",\r\n\tprops: {\r\n\t\t...defaultFieldProps,\r\n\r\n\t\tmodelValue: { type: [Date, String, Object], default: () => null },\r\n\r\n\t\t/**\r\n\t\t * 标题\r\n\t\t */\r\n\t\ttitle: { type: String, default: \"选择日期\" },\r\n\t},\r\n\temits: [\"update:modelValue\"],\r\n\tsetup(props, { emit, slots, expose }) {\r\n\t\tconst columnsType = props.defaultProps?.columnsType || [\"year\", \"month\", \"day\"]\r\n\r\n\t\tconst getYear = (value) => {\r\n\t\t\treturn isDayjs(value) ? value.year() : value.getFullYear()\r\n\t\t}\r\n\t\tconst getMonth = (value) => {\r\n\t\t\treturn isDayjs(value) ? value.month() + 1 : value.getMonth() + 1\r\n\t\t}\r\n\t\tconst getDate = (value) => {\r\n\t\t\treturn isDayjs(value) ? value.date() : value.getDate()\r\n\t\t}\r\n\r\n\t\tconst _setValueByColumns = (columnsType, value, date) => {\r\n\t\t\tcolumnsType.forEach((column) => {\r\n\t\t\t\tif (column === \"year\") {\r\n\t\t\t\t\tvalue.push(getYear(date))\r\n\t\t\t\t} else if (column === \"month\") {\r\n\t\t\t\t\tvalue.push(getMonth(date))\r\n\t\t\t\t} else if (column === \"day\") {\r\n\t\t\t\t\tvalue.push(getDate(date))\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\treturn value\r\n\t\t}\r\n\t\tconst prepareDate = (date) => {\r\n\t\t\tconst value = []\r\n\r\n\t\t\tif (!date) {\r\n\t\t\t\treturn value\r\n\t\t\t}\r\n\r\n\t\t\treturn _setValueByColumns(columnsType, value, date)\r\n\t\t}\r\n\r\n\t\tlet defaultValue = prepareDate(props.modelValue)\r\n\r\n\t\tif (!defaultValue.length) {\r\n\t\t\tconst now = new Date()\r\n\t\t\tdefaultValue = _setValueByColumns(columnsType, defaultValue, now)\r\n\t\t}\r\n\r\n\t\tconst componentValue = ref(defaultValue)\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => {\r\n\t\t\t\tcomponentValue.value = prepareDate(props.modelValue)\r\n\t\t\t},\r\n\t\t)\r\n\r\n\t\tconst pickerRef = ref(null)\r\n\r\n\t\tconst displayText = computed(() => {\r\n\t\t\tif (props.modelValue) {\r\n\t\t\t\tlet text = \"\"\r\n\t\t\t\tcolumnsType.forEach((column) => {\r\n\t\t\t\t\tif (column === \"year\") {\r\n\t\t\t\t\t\ttext += getYear(props.modelValue)\r\n\t\t\t\t\t} else if (column === \"month\") {\r\n\t\t\t\t\t\tif (text) {\r\n\t\t\t\t\t\t\ttext += \"/\"\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttext += padZero(getMonth(props.modelValue), 2)\r\n\t\t\t\t\t} else if (column === \"day\") {\r\n\t\t\t\t\t\tif (text) {\r\n\t\t\t\t\t\t\ttext += \"/\"\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttext += padZero(getDate(props.modelValue), 2)\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t\treturn text\r\n\t\t\t}\r\n\r\n\t\t\treturn \"\"\r\n\t\t})\r\n\r\n\t\texpose({ displayText })\r\n\r\n\t\tconst onConfirm = ({ selectedValues }) => {\r\n\t\t\tpickerRef.value.close()\r\n\r\n\t\t\tconst now = new Date()\r\n\t\t\tlet date = {}\r\n\t\t\tcolumnsType.forEach((column, index) => {\r\n\t\t\t\tif (column === \"year\") {\r\n\t\t\t\t\tdate.year = selectedValues[index]\r\n\t\t\t\t} else if (column === \"month\") {\r\n\t\t\t\t\tdate.month = selectedValues[index] - 1\r\n\t\t\t\t} else if (column === \"day\") {\r\n\t\t\t\t\tdate.date = selectedValues[index]\r\n\t\t\t\t}\r\n\t\t\t})\r\n\r\n\t\t\temit(\r\n\t\t\t\t\"update:modelValue\",\r\n\t\t\t\tnew Date(date.year || now.getFullYear(), isUndefined(date.month) ? now.getMonth() : date.month, date.date || now.getDate()),\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn () => (\r\n\t\t\t<PickerWrapper ref={pickerRef} closeable={false} disabled={props.disabled || props.readonly}>\r\n\t\t\t\t{{\r\n\t\t\t\t\t...pickerSlots(slots, props),\r\n\t\t\t\t\tdefault: () => (\r\n\t\t\t\t\t\t<DatePicker\r\n\t\t\t\t\t\t\tv-model={componentValue.value}\r\n\t\t\t\t\t\t\tonConfirm={onConfirm}\r\n\t\t\t\t\t\t\tonCancel={() => pickerRef.value.close()}\r\n\t\t\t\t\t\t\ttitle={props.title}\r\n\t\t\t\t\t\t\t{...props.defaultProps}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t),\r\n\t\t\t\t}}\r\n\t\t\t</PickerWrapper>\r\n\t\t)\r\n\t},\r\n})\r\n","import PickerWrapper, { pickerSlots } from \"./PickerWrapper.jsx\"\r\nimport { ref, defineComponent, computed, watch } from \"vue\"\r\nimport { Calendar, Collapse, CollapseItem, TimePicker } from \"vant\"\r\nimport ExButton from \"../button/ExButton.jsx\"\r\nimport { padZero } from \"vant/es/utils\"\r\nimport { defaultFieldProps } from \"../utils\"\r\nimport { cloneDeep } from \"lodash-es\"\r\n\r\n/**\r\n * ExDatetime 日期时间选择器\r\n * @version 1.0.0\r\n */\r\nexport default defineComponent({\r\n\tname: \"ExDatetime\",\r\n\tprops: {\r\n\t\t...defaultFieldProps,\r\n\r\n\t\tmodelValue: { type: Date, default: () => null },\r\n\t},\r\n\temits: [\"update:modelValue\"],\r\n\tsetup(props, { slots, emit, expose }) {\r\n\t\tconst dateValue = ref(null)\r\n\t\tconst timeValue = ref(null)\r\n\t\tconst displayText = ref(null)\r\n\t\tconst pickerRef = ref()\r\n\r\n\t\tconst activeName = ref(\"date\")\r\n\r\n\t\tconst minDate = new Date(2010, 0, 1)\r\n\t\tconst maxDate = new Date(2045, 11, 31)\r\n\r\n\t\tconst weekdays = [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"]\r\n\r\n\t\tconst dateText = computed(() => {\r\n\t\t\tif (dateValue.value) {\r\n\t\t\t\treturn `${dateValue.value.getFullYear()}/${dateValue.value.getMonth() + 1}/${dateValue.value.getDate()} 星期${\r\n\t\t\t\t\tweekdays[dateValue.value.getDay()]\r\n\t\t\t\t}`\r\n\t\t\t}\r\n\t\t\treturn \"请选择日期\"\r\n\t\t})\r\n\t\tconst timeText = computed(() => {\r\n\t\t\tif (timeValue.value) {\r\n\t\t\t\treturn timeValue.value\r\n\t\t\t}\r\n\t\t\treturn \"请选择时间\"\r\n\t\t})\r\n\t\tconst timeModel = computed(() => {\r\n\t\t\tif (timeValue.value) {\r\n\t\t\t\tconst [hours, minutes] = timeValue.value.split(\":\")\r\n\t\t\t\treturn [hours, minutes]\r\n\t\t\t}\r\n\t\t\treturn []\r\n\t\t})\r\n\r\n\t\tconst defaultDate = ref(props.modelValue || new Date())\r\n\r\n\t\tconst setDisplayText = () => {\r\n\t\t\tdisplayText.value = dateValue.value && timeValue.value ? `${dateText.value} ${timeText.value}` : \"\"\r\n\t\t}\r\n\t\t/**\r\n\t\t *\r\n\t\t * @param {Date|null} date\r\n\t\t */\r\n\t\tconst prepareDate = (date) => {\r\n\t\t\tif (date) {\r\n\t\t\t\tdateValue.value = cloneDeep(date)\r\n\t\t\t\ttimeValue.value = `${padZero(date.getHours(), 2)}:${padZero(date.getMinutes(), 2)}`\r\n\t\t\t}\r\n\t\t\tsetDisplayText()\r\n\t\t}\r\n\r\n\t\tprepareDate(props.modelValue)\r\n\r\n\t\twatch(\r\n\t\t\t() => props.modelValue,\r\n\t\t\t() => prepareDate(props.modelValue),\r\n\t\t)\r\n\r\n\t\texpose({ displayText })\r\n\r\n\t\tconst onSelectDate = (date) => {\r\n\t\t\tdateValue.value = date\r\n\t\t}\r\n\r\n\t\tconst onTimeChange = ({ selectedValues }) => {\r\n\t\t\ttimeValue.value = selectedValues.join(\":\")\r\n\t\t}\r\n\r\n\t\tconst onConfirm = () => {\r\n\t\t\tif (!dateValue.value) {\r\n\t\t\t\tdateValue.value = new Date()\r\n\t\t\t}\r\n\t\t\tlet dateString = `${dateValue.value.getFullYear()}/${dateValue.value.getMonth() + 1}/${dateValue.value.getDate()}`\r\n\r\n\t\t\tif (!timeValue.value) {\r\n\t\t\t\tdateString += ` 00:00:00`\r\n\t\t\t} else {\r\n\t\t\t\tdateString += ` ${timeValue.value}`\r\n\t\t\t}\r\n\r\n\t\t\tpickerRef.value.close()\r\n\t\t\tsetDisplayText()\r\n\r\n\t\t\temit(\"update:modelValue\", new Date(dateString))\r\n\t\t}\r\n\r\n\t\treturn () => {\r\n\t\t\treturn (\r\n\t\t\t\t<PickerWrapper ref={pickerRef} inset={true} disabled={props.disabled || props.readonly}>\r\n\t\t\t\t\t{{\r\n\t\t\t\t\t\t...pickerSlots(slots, props),\r\n\t\t\t\t\t\tdefault: () => [\r\n\t\t\t\t\t\t\t<Collapse accordion={true} v-model={activeName.value} border={false} class={\"ex-datetime_collapse\"}>\r\n\t\t\t\t\t\t\t\t{{\r\n\t\t\t\t\t\t\t\t\tdefault: () => [\r\n\t\t\t\t\t\t\t\t\t\t<CollapseItem name={\"date\"} icon={\"calendar-o\"} value={dateText.value} isLink={false}>\r\n\t\t\t\t\t\t\t\t\t\t\t{{\r\n\t\t\t\t\t\t\t\t\t\t\t\ttitle: () => <span style={{ fontWeight: \"bold\" }}>日期</span>,\r\n\t\t\t\t\t\t\t\t\t\t\t\tdefault: () => (\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div style={{ height: \"300px\" }}>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Calendar\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tminDate={minDate}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmaxDate={maxDate}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowSubtitle={false}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowConfirm={false}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdefaultDate={defaultDate.value}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpoppable={false}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowTitle={false}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlazyRender={true}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trowHeight={36}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelect={onSelectDate}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{...props.defaultProps.calendarProps}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t></Calendar>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t\t\t\t\t\t),\r\n\t\t\t\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\t\t</CollapseItem>,\r\n\t\t\t\t\t\t\t\t\t\t<CollapseItem name={\"time\"} icon={\"clo