jobsys-explore 1.0.1

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.
Files changed (127) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc.cjs +38 -0
  3. package/.prettierrc.cjs +38 -0
  4. package/README.md +42 -0
  5. package/components/button/ExButton.jsx +119 -0
  6. package/components/button/index.js +4 -0
  7. package/components/button/index.less +8 -0
  8. package/components/form/ExAddress.jsx +125 -0
  9. package/components/form/ExCascader.jsx +98 -0
  10. package/components/form/ExCheckbox.jsx +59 -0
  11. package/components/form/ExDate.jsx +130 -0
  12. package/components/form/ExDatetime.jsx +152 -0
  13. package/components/form/ExField.jsx +123 -0
  14. package/components/form/ExFieldUploader.jsx +44 -0
  15. package/components/form/ExForm.jsx +395 -0
  16. package/components/form/ExNumber.jsx +49 -0
  17. package/components/form/ExRadio.jsx +58 -0
  18. package/components/form/ExRate.jsx +47 -0
  19. package/components/form/ExSelect.jsx +151 -0
  20. package/components/form/ExSlider.jsx +53 -0
  21. package/components/form/ExSwitch.jsx +49 -0
  22. package/components/form/ExTime.jsx +104 -0
  23. package/components/form/FormItem.jsx +229 -0
  24. package/components/form/PickerWrapper.jsx +111 -0
  25. package/components/form/addressData.json +1 -0
  26. package/components/form/index.js +37 -0
  27. package/components/form/index.less +108 -0
  28. package/components/form/utils.js +47 -0
  29. package/components/grid/ExGrid.jsx +53 -0
  30. package/components/grid/index.js +4 -0
  31. package/components/grid/index.less +3 -0
  32. package/components/index.js +9 -0
  33. package/components/pagination/ExPagination.jsx +148 -0
  34. package/components/pagination/index.js +5 -0
  35. package/components/pagination/index.less +15 -0
  36. package/components/provider/ExProvider.jsx +91 -0
  37. package/components/provider/index.js +4 -0
  38. package/components/qrcode/ExQrcode.jsx +86 -0
  39. package/components/qrcode/index.js +5 -0
  40. package/components/qrcode/index.less +8 -0
  41. package/components/result/ExResult.jsx +122 -0
  42. package/components/result/index.js +5 -0
  43. package/components/result/index.less +60 -0
  44. package/components/search/ExSearch.jsx +252 -0
  45. package/components/search/components/Expand.jsx +77 -0
  46. package/components/search/components/Field.jsx +27 -0
  47. package/components/search/components/Quick.jsx +53 -0
  48. package/components/search/components/index.js +5 -0
  49. package/components/search/index.js +5 -0
  50. package/components/search/index.less +119 -0
  51. package/components/search/utils.js +30 -0
  52. package/components/theme/ExTheme.jsx +10 -0
  53. package/components/theme/index.js +4 -0
  54. package/components/theme/index.less +97 -0
  55. package/components/uploader/ExUploader.jsx +248 -0
  56. package/components/uploader/index.js +5 -0
  57. package/components/utils.js +150 -0
  58. package/dist/__vite-browser-external-2447137e.mjs +5 -0
  59. package/dist/__vite-browser-external-2447137e.mjs.map +1 -0
  60. package/dist/__vite-browser-external-b3701507.js +2 -0
  61. package/dist/__vite-browser-external-b3701507.js.map +1 -0
  62. package/dist/hooks.cjs +2 -0
  63. package/dist/hooks.cjs.map +1 -0
  64. package/dist/hooks.js +35 -0
  65. package/dist/hooks.js.map +1 -0
  66. package/dist/index-82d74e5f.mjs +2120 -0
  67. package/dist/index-82d74e5f.mjs.map +1 -0
  68. package/dist/index-b8729555.js +2 -0
  69. package/dist/index-b8729555.js.map +1 -0
  70. package/dist/jobsys-explore.cjs +9 -0
  71. package/dist/jobsys-explore.cjs.map +1 -0
  72. package/dist/jobsys-explore.js +18673 -0
  73. package/dist/jobsys-explore.js.map +1 -0
  74. package/dist/style.css +1 -0
  75. package/docgen.config.cjs +9 -0
  76. package/docs/.vitepress/cache/deps/_metadata.json +19 -0
  77. package/docs/.vitepress/cache/deps/package.json +3 -0
  78. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +162 -0
  79. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  80. package/docs/.vitepress/cache/deps/vue.js +10795 -0
  81. package/docs/.vitepress/cache/deps/vue.js.map +7 -0
  82. package/docs/.vitepress/config.mjs +43 -0
  83. package/docs/.vitepress/dist/404.html +19 -0
  84. package/docs/.vitepress/dist/assets/app.e0eb4814.js +1 -0
  85. package/docs/.vitepress/dist/assets/chunks/framework.7a64ad8e.js +2 -0
  86. package/docs/.vitepress/dist/assets/chunks/theme.ffc5f35c.js +7 -0
  87. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 +0 -0
  88. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.ea42a392.woff2 +0 -0
  89. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.4fbe9427.woff2 +0 -0
  90. package/docs/.vitepress/dist/assets/inter-italic-greek.8f4463c4.woff2 +0 -0
  91. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.bd8920cc.woff2 +0 -0
  92. package/docs/.vitepress/dist/assets/inter-italic-latin.bd3b6f56.woff2 +0 -0
  93. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.6ce511fb.woff2 +0 -0
  94. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.e75737ce.woff2 +0 -0
  95. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.5f2c6c8c.woff2 +0 -0
  96. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.ab0619bc.woff2 +0 -0
  97. package/docs/.vitepress/dist/assets/inter-roman-greek.d5a6d92a.woff2 +0 -0
  98. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.0030eebd.woff2 +0 -0
  99. package/docs/.vitepress/dist/assets/inter-roman-latin.2ed14f66.woff2 +0 -0
  100. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.14ce25a6.woff2 +0 -0
  101. package/docs/.vitepress/dist/assets/style.6747f984.css +1 -0
  102. package/docs/.vitepress/dist/hashmap.json +1 -0
  103. package/docs/.vitepress/theme/index.css +0 -0
  104. package/docs/.vitepress/theme/index.js +12 -0
  105. package/hooks/cipher.js +40 -0
  106. package/hooks/form.js +176 -0
  107. package/hooks/index.js +4 -0
  108. package/hooks/network.js +153 -0
  109. package/hooks/utils.js +61 -0
  110. package/index.html +17 -0
  111. package/index.js +10 -0
  112. package/package.json +75 -0
  113. package/playground/App.vue +45 -0
  114. package/playground/TestButton.vue +15 -0
  115. package/playground/TestForm.vue +271 -0
  116. package/playground/TestFormItem.vue +110 -0
  117. package/playground/TestGrid.vue +22 -0
  118. package/playground/TestPagination.vue +89 -0
  119. package/playground/TestQrcode.vue +7 -0
  120. package/playground/TestResult.vue +12 -0
  121. package/playground/TestSearch.vue +84 -0
  122. package/playground/http.js +23 -0
  123. package/playground/main.js +12 -0
  124. package/postcss.config.cjs +8 -0
  125. package/utils/style.js +13 -0
  126. package/utils/withInstall.js +7 -0
  127. package/vite.config.js +52 -0
package/.eslintignore ADDED
@@ -0,0 +1,4 @@
1
+ dist
2
+ node_modules
3
+ .prettierrc.cjs
4
+ vite.config.js
package/.eslintrc.cjs ADDED
@@ -0,0 +1,38 @@
1
+ module.exports = {
2
+ env: {
3
+ browser: true,
4
+ es2021: true
5
+ },
6
+ globals: {
7
+ defineOptions: true
8
+ },
9
+ extends: ["eslint-config-prettier", "plugin:import/recommended", "eslint:recommended", "plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
10
+ overrides: [],
11
+ parserOptions: {
12
+ ecmaVersion: "latest",
13
+ sourceType: "module",
14
+ ecmaFeatures: {
15
+ jsx: true
16
+ }
17
+ },
18
+ plugins: ["vue"],
19
+ rules: {
20
+ "import/prefer-default-export": "off",
21
+ "import/no-extraneous-dependencies": "off",
22
+ "import/no-duplicates": "off",
23
+ "import/named": "off",
24
+ "import/order": "off",
25
+ "import/first": "off",
26
+ "vue/attributes-order": "off",
27
+ "vue/no-mutating-props": "off",
28
+ "vue/no-reserved-component-names": "off",
29
+ "vue/no-v-html": "off",
30
+ "no-param-reassign": "off",
31
+ "no-console": "off",
32
+ "no-restricted-globals": "off",
33
+ "no-debugger": "off",
34
+ "no-use-before-define": "off",
35
+ "no-promise-executor-return": "off",
36
+ "spaced-comment": "off"
37
+ }
38
+ };
@@ -0,0 +1,38 @@
1
+ module.exports = {
2
+ // 一行最多多少个字符
3
+ printWidth: 150,
4
+ // 指定每个缩进级别的空格数
5
+ tabWidth: 4,
6
+ // 使用制表符而不是空格缩进行
7
+ useTabs: true,
8
+ // 在语句末尾是否需要分号
9
+ semi: false,
10
+ // 是否使用单引号
11
+ singleQuote: false,
12
+ // 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
13
+ quoteProps: "as-needed",
14
+ // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
15
+ trailingComma: "all",
16
+ // 在对象文字中的括号之间打印空格
17
+ bracketSpacing: true,
18
+ // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
19
+ arrowParens: "always",
20
+ // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
21
+ rangeStart: 0,
22
+ rangeEnd: Infinity,
23
+ // 指定要使用的解析器,不需要写文件开头的 @prettier
24
+ requirePragma: false,
25
+ // 不需要自动在文件开头插入 @prettier
26
+ insertPragma: false,
27
+ // 使用默认的折行标准 always\never\preserve
28
+ proseWrap: "preserve",
29
+ // 指定HTML文件的全局空格敏感度 css\strict\ignore
30
+ htmlWhitespaceSensitivity: "css",
31
+ // Vue文件脚本和样式标签缩进
32
+ vueIndentScriptAndStyle: false,
33
+ // 在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
34
+ // 然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
35
+ // 对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
36
+ // 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
37
+ endOfLine: "auto"
38
+ }
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+
2
+ # TODOs
3
+
4
+ ---
5
+
6
+ ## 增强
7
+
8
+ - [ ] ExploreForm
9
+ - [ ] Address
10
+ - [ ] Cascader
11
+ - [ ] Checkbox
12
+ - [ ] Date
13
+ - [ ] Group
14
+ - [ ] Html
15
+ - [ ] Input
16
+ - [ ] Number
17
+ - [ ] Radio
18
+ - [ ] Remote
19
+ - [ ] Select
20
+ - [ ] Switch
21
+ - [ ] Tag
22
+ - [ ] Text
23
+ - [ ] Time
24
+ - [ ] TreeSelect
25
+ - [ ] Uploader
26
+
27
+ - [ ] ExploreSearch
28
+ - [ ] 同上
29
+
30
+
31
+ - [ ] Field
32
+ - [ ] Disabled
33
+ - [ ] Help
34
+
35
+
36
+ ## 新增
37
+
38
+ - [ ] 样式定制
39
+ - [ ] 浮动按钮
40
+ - [ ] 列表组件
41
+ - [ ] 背景生成
42
+ - [ ] 简易图表
@@ -0,0 +1,119 @@
1
+ import { defineComponent } from "vue"
2
+ import { Button } from "vant"
3
+ import "./index.less"
4
+
5
+ /**
6
+ * 主题组件
7
+ * @version 1.0.0
8
+ */
9
+ export default defineComponent({
10
+ name: "ExButton",
11
+ props: {
12
+ /**
13
+ * 按钮类型
14
+ * @values primary, success, warning, danger
15
+ */
16
+ type: { type: String, default: "default" },
17
+
18
+ /**
19
+ * 按钮大小
20
+ * @values large, normal, small, mini
21
+ */
22
+ size: { type: String, default: "normal" },
23
+
24
+ /**
25
+ * 失效状态
26
+ */
27
+ disabled: { type: Boolean, default: false },
28
+
29
+ /**
30
+ * 是否圆形按钮
31
+ */
32
+ round: { type: Boolean, default: true },
33
+
34
+ /**
35
+ * 是否块状按钮
36
+ */
37
+ block: { type: Boolean, default: true },
38
+
39
+ /**
40
+ * 按钮标签
41
+ */
42
+ text: { type: String, default: "" },
43
+
44
+ /**
45
+ * 按钮图标,需要使用
46
+ *
47
+ */
48
+ icon: { type: Object, default: null },
49
+
50
+ /**
51
+ * 按钮图标位置
52
+ * @values left, right
53
+ */
54
+ iconPosition: { type: String, default: "left" },
55
+
56
+ /**
57
+ * 请求状态控制器
58
+ * @param {boolean} fetcher.loading 是否加载中
59
+ */
60
+ fetcher: {
61
+ type: Object,
62
+ default: () => ({ loading: false }),
63
+ },
64
+
65
+ /**
66
+ * [原生配置](https://vant-contrib.gitee.io/vant/#/zh-CN/button)
67
+ */
68
+ buttonProps: {
69
+ type: Object,
70
+ default: () => ({}),
71
+ },
72
+ },
73
+ emits: [
74
+ /**
75
+ * @event click
76
+ * @param {Event} event 点击事件
77
+ */
78
+ "click",
79
+ ],
80
+
81
+ setup(props, { emit, slots }) {
82
+ const onClick = (e) => {
83
+ /**
84
+ * @event click 点击事件
85
+ */
86
+ emit("click", e)
87
+ }
88
+
89
+ const defaultLabel = () => {
90
+ return props.text || slots.default?.()
91
+ }
92
+
93
+ const defaultSlot = () => {
94
+ if (props.icon && props.iconPosition === "left") {
95
+ return [props.icon, defaultLabel()]
96
+ } else if (props.icon && props.iconPosition === "right") {
97
+ return [defaultLabel(), props.icon]
98
+ }
99
+ return [defaultLabel()]
100
+ }
101
+
102
+ return () => (
103
+ <Button
104
+ loading={props.fetcher.loading}
105
+ type={props.type}
106
+ size={props.size}
107
+ disabled={props.disabled}
108
+ round={props.round}
109
+ block={props.block}
110
+ onClick={onClick}
111
+ {...props.buttonProps}
112
+ >
113
+ {{
114
+ default: () => defaultSlot(),
115
+ }}
116
+ </Button>
117
+ )
118
+ },
119
+ })
@@ -0,0 +1,4 @@
1
+ import _ExButton from "./ExButton.jsx"
2
+ import withInstall from "../../utils/withInstall"
3
+ export const ExButton = withInstall(_ExButton)
4
+ export default ExButton
@@ -0,0 +1,8 @@
1
+ .van-button{
2
+ padding: 0 40px;
3
+ }
4
+
5
+ :root:root{
6
+ --van-button-normal-font-size: 16px;
7
+ --van-button-default-height: 48px;
8
+ }
@@ -0,0 +1,125 @@
1
+ import { computed, defineComponent, ref, watch } from "vue"
2
+ import { Cascader } from "vant"
3
+ import localData from "./addressData.json"
4
+ import PickerWrapper, { pickerProps, pickerSlots } from "./PickerWrapper.jsx"
5
+ import { defaultFieldProps, defaultOptionsProps, useOptionTrait } from "../utils"
6
+ import { isArray, last } from "lodash-es"
7
+ import { useFindTextsFromPath } from "../../hooks"
8
+
9
+ /**
10
+ * 地址组件
11
+ *
12
+ * 数据优先级:`dataSource` > `url` > `本地数据`
13
+ *
14
+ * @version 1.0.0
15
+ */
16
+ export default defineComponent({
17
+ name: "ExAddress",
18
+ props: {
19
+ ...defaultOptionsProps,
20
+ ...defaultFieldProps,
21
+
22
+ modelValue: { type: [String, Number, Array], default: () => [] },
23
+
24
+ /**
25
+ * 标题
26
+ */
27
+ title: { type: String, default: "" },
28
+
29
+ /**
30
+ * 生成哪个级别的数据
31
+ * 1: 省, 2: 省市, 3: 省市区
32
+ */
33
+ level: { type: Number, default: 3 },
34
+ },
35
+ emits: ["update:modelValue"],
36
+ setup(props, { emit, slots, expose }) {
37
+ const defaultValue = isArray(props.modelValue) ? last(props.modelValue) : props.modelValue
38
+
39
+ const componentValue = ref(defaultValue)
40
+
41
+ watch(
42
+ () => props.modelValue,
43
+ () => (componentValue.value = isArray(props.modelValue) ? last(props.modelValue) : props.modelValue),
44
+ )
45
+
46
+ const pickerRef = ref(null)
47
+ const options = ref([])
48
+
49
+ const displayText = computed(() => {
50
+ if (props.modelValue.length === 0) {
51
+ return ""
52
+ }
53
+ return useFindTextsFromPath(options.value, props.modelValue, {
54
+ value: "code",
55
+ children: "children",
56
+ label: "name",
57
+ }).join("/")
58
+ })
59
+
60
+ useOptionTrait(options, props, localData)
61
+
62
+ const onFinish = ({ selectedOptions }) => {
63
+ pickerRef.value.close()
64
+ emit(
65
+ "update:modelValue",
66
+ selectedOptions.map((item) => item.code),
67
+ )
68
+ }
69
+
70
+ expose({ displayText })
71
+
72
+ /********** render **********/
73
+
74
+ return () => (
75
+ <PickerWrapper ref={pickerRef} {...pickerProps(props)}>
76
+ {{
77
+ ...pickerSlots(slots, props),
78
+ default: () => (
79
+ <Cascader
80
+ v-model={componentValue.value}
81
+ fieldNames={{ text: "name", value: "code", children: "children" }}
82
+ closeable={false}
83
+ showHeader={false}
84
+ options={options.value}
85
+ onFinish={onFinish}
86
+ />
87
+ ),
88
+ }}
89
+ </PickerWrapper>
90
+ )
91
+ },
92
+ })
93
+
94
+ /**
95
+ *
96
+ * 根据地址编码获取完整的地址编码
97
+ *
98
+ * @param code
99
+ * @param {number} [level] 地址级别: 1: 省, 2: 省市, 3: 省市区
100
+ * @return {string[]|(string|*)[]|*[]}
101
+ */
102
+ export function useAddressFullCode(code, level) {
103
+ code += ""
104
+ if (code && code.length === 6) {
105
+ if (!level) {
106
+ if (/0000$/.test(code)) {
107
+ level = 1
108
+ } else if (/00$/.test(code)) {
109
+ level = 2
110
+ } else {
111
+ level = 3
112
+ }
113
+ }
114
+ if (level === 1) {
115
+ return [`${code.substr(0, 2)}0000`]
116
+ }
117
+ if (level === 2) {
118
+ return [`${code.substr(0, 2)}0000`, `${code.substr(0, 4)}00`]
119
+ }
120
+ if (level === 3) {
121
+ return [`${code.substr(0, 2)}0000`, `${code.substr(0, 4)}00`, code]
122
+ }
123
+ }
124
+ return []
125
+ }
@@ -0,0 +1,98 @@
1
+ import { computed, defineComponent, ref, watch } from "vue"
2
+ import PickerWrapper, { pickerProps, pickerSlots } from "./PickerWrapper.jsx"
3
+ import { Button, Cascader } from "vant"
4
+ import { defaultFieldProps, defaultOptionsProps, useOptionTrait } from "../utils"
5
+ import { useFindTextsFromPath } from "../../hooks"
6
+
7
+ /**
8
+ * ExCascader 级联选择
9
+ * @version 1.0.0
10
+ */
11
+ export default defineComponent({
12
+ name: "ExCascader",
13
+ props: {
14
+ ...defaultOptionsProps,
15
+ ...defaultFieldProps,
16
+
17
+ modelValue: { type: Array, default: () => [] },
18
+
19
+ /**
20
+ * 标题
21
+ */
22
+ title: { type: String, default: "" },
23
+
24
+ /**
25
+ * 是否显示清除按钮
26
+ */
27
+ clearable: { type: Boolean, default: false },
28
+
29
+ /**
30
+ * [原生配置](https://vant-contrib.gitee.io/vant/#/zh-CN/cascader)
31
+ */
32
+ cascaderProps: { type: Object, default: () => ({}) },
33
+ },
34
+ emits: ["update:modelValue", "change"],
35
+ setup(props, { emit, slots, expose }) {
36
+ const defaultValue = props.modelValue?.[0] || ""
37
+
38
+ const componentValue = ref(defaultValue)
39
+
40
+ watch(
41
+ () => props.modelValue,
42
+ () => (componentValue.value = props.modelValue?.[0] || ""),
43
+ )
44
+
45
+ const pickerRef = ref(null)
46
+
47
+ const options = ref([])
48
+
49
+ const displayText = computed(() => {
50
+ if (props.modelValue.length === 0) {
51
+ return ""
52
+ }
53
+ return useFindTextsFromPath(options.value, props.modelValue).join("/")
54
+ })
55
+
56
+ useOptionTrait(options, props)
57
+
58
+ const onFinish = ({ selectedOptions }) => {
59
+ const value = selectedOptions.map((item) => item.value)
60
+ emit("change", value)
61
+ emit("update:modelValue", value)
62
+ pickerRef.value.close()
63
+ }
64
+
65
+ const onClear = () => {
66
+ emit("change", [])
67
+ emit("update:modelValue", [])
68
+ pickerRef.value.close()
69
+ }
70
+
71
+ expose({ displayText })
72
+
73
+ return () => (
74
+ <PickerWrapper ref={pickerRef} {...pickerProps(props)}>
75
+ {{
76
+ ...pickerSlots(slots, props),
77
+ default: () => [
78
+ <Cascader
79
+ v-model={componentValue.value}
80
+ closeable={false}
81
+ showHeader={false}
82
+ options={options.value}
83
+ onFinish={onFinish}
84
+ {...props.cascaderProps}
85
+ />,
86
+ props.clearable ? (
87
+ <div class={"ex-field-popup__clear-btn"}>
88
+ <Button block type={"primary"} plain={true} round={true} onClick={onClear}>
89
+ 清除
90
+ </Button>
91
+ </div>
92
+ ) : null,
93
+ ],
94
+ }}
95
+ </PickerWrapper>
96
+ )
97
+ },
98
+ })
@@ -0,0 +1,59 @@
1
+ import { defineComponent, ref, watch } from "vue"
2
+ import { defaultFieldProps, defaultOptionsProps, useOptionTrait } from "../utils"
3
+ import { Checkbox, CheckboxGroup } from "vant"
4
+ import ExField from "./ExField.jsx"
5
+ import { pick } from "lodash-es"
6
+
7
+ /**
8
+ * ExCheckbox 多选
9
+ * @version 1.0.0
10
+ */
11
+ export default defineComponent({
12
+ name: "ExCheckbox",
13
+ props: {
14
+ ...defaultFieldProps,
15
+ ...defaultOptionsProps,
16
+
17
+ modelValue: { type: Array, default: () => [] },
18
+
19
+ /**
20
+ * [原生配置](https://vant-contrib.gitee.io/vant/#/zh-CN/cascader)
21
+ */
22
+ checkboxProps: { type: Object, default: () => ({}) },
23
+ },
24
+ emits: ["update:modelValue"],
25
+ setup(props, { emit, slots }) {
26
+ const componentValue = ref(props.modelValue)
27
+
28
+ watch(
29
+ () => props.modelValue,
30
+ () => (componentValue.value = props.modelValue),
31
+ )
32
+
33
+ const options = ref([])
34
+
35
+ useOptionTrait(options, props)
36
+
37
+ const onChange = (value) => {
38
+ emit("update:modelValue", value)
39
+ }
40
+
41
+ const fieldProps = pick(props, Object.keys(defaultFieldProps))
42
+
43
+ return () => (
44
+ <ExField {...fieldProps}>
45
+ {{
46
+ ...slots,
47
+ input: () => (
48
+ <CheckboxGroup v-model={componentValue.value} {...props.checkboxProps} onChange={onChange}>
49
+ {{
50
+ default: () =>
51
+ options.value.map((option) => <Checkbox name={option.value}>{{ default: () => option.text }}</Checkbox>),
52
+ }}
53
+ </CheckboxGroup>
54
+ ),
55
+ }}
56
+ </ExField>
57
+ )
58
+ },
59
+ })
@@ -0,0 +1,130 @@
1
+ import { computed, defineComponent, ref, watch } from "vue"
2
+ import PickerWrapper, { pickerSlots } from "./PickerWrapper.jsx"
3
+ import { DatePicker } from "vant"
4
+ import { isDate } from "lodash-es"
5
+ import { padZero } from "vant/es/utils"
6
+ import { defaultFieldProps } from "../utils"
7
+
8
+ /**
9
+ * ExDate 日期选择
10
+ * @version 1.0.0
11
+ */
12
+ export default defineComponent({
13
+ name: "ExDate",
14
+ props: {
15
+ ...defaultFieldProps,
16
+
17
+ modelValue: { type: Date, default: () => [] },
18
+
19
+ /**
20
+ * 标题
21
+ */
22
+ title: { type: String, default: "选择日期" },
23
+
24
+ /**
25
+ * [原生配置](https://vant-contrib.gitee.io/vant/#/zh-CN/date-picker)
26
+ */
27
+ dateProps: { type: Object, default: () => ({}) },
28
+ },
29
+ emits: ["update:modelValue"],
30
+ setup(props, { emit, slots, expose }) {
31
+ const columnsType = props.dateProps?.columnsType || ["year", "month", "day"]
32
+ const prepareDate = (date) => {
33
+ const value = []
34
+
35
+ if (!date) {
36
+ return value
37
+ }
38
+
39
+ columnsType.forEach((column) => {
40
+ if (column === "year") {
41
+ value.push(date.getFullYear())
42
+ } else if (column === "month") {
43
+ value.push(date.getMonth() + 1)
44
+ } else if (column === "day") {
45
+ value.push(date.getDate())
46
+ }
47
+ })
48
+
49
+ return value
50
+ }
51
+
52
+ let defaultValue = prepareDate(props.modelValue)
53
+
54
+ if (!defaultValue.length) {
55
+ const now = new Date()
56
+ defaultValue = [now.getFullYear(), now.getMonth() + 1, now.getDate()]
57
+ }
58
+
59
+ const componentValue = ref(defaultValue)
60
+
61
+ watch(
62
+ () => props.modelValue,
63
+ () => {
64
+ if (props.modelValue && isDate(props.modelValue)) {
65
+ componentValue.value = prepareDate(props.modelValue)
66
+ } else {
67
+ componentValue.value = props.modelValue
68
+ }
69
+ },
70
+ )
71
+
72
+ const pickerRef = ref(null)
73
+
74
+ const displayText = computed(() => {
75
+ if (props.modelValue) {
76
+ let text = ""
77
+ columnsType.forEach((column) => {
78
+ if (column === "year") {
79
+ text += `${props.modelValue.getFullYear()}年`
80
+ } else if (column === "month") {
81
+ text += `${padZero(props.modelValue.getMonth() + 1, 2)}月`
82
+ } else if (column === "day") {
83
+ text += `${padZero(props.modelValue.getDate(), 2)}日`
84
+ }
85
+ })
86
+
87
+ return text
88
+ }
89
+
90
+ return ""
91
+ })
92
+
93
+ expose({ displayText })
94
+
95
+ const onConfirm = ({ selectedValues }) => {
96
+ pickerRef.value.close()
97
+
98
+ const now = new Date()
99
+ let date = {}
100
+ columnsType.forEach((column, index) => {
101
+ if (column === "year") {
102
+ date.year = selectedValues[index]
103
+ } else if (column === "month") {
104
+ date.month = selectedValues[index] - 1
105
+ } else if (column === "day") {
106
+ date.date = selectedValues[index]
107
+ }
108
+ })
109
+
110
+ emit("update:modelValue", new Date(date.year || now.getFullYear(), date.month || now.getMonth(), date.date || now.getDate()))
111
+ }
112
+
113
+ return () => (
114
+ <PickerWrapper ref={pickerRef} closeable={false}>
115
+ {{
116
+ ...pickerSlots(slots, props),
117
+ default: () => (
118
+ <DatePicker
119
+ v-model={componentValue.value}
120
+ onConfirm={onConfirm}
121
+ onCancel={() => pickerRef.value.close()}
122
+ title={props.title}
123
+ {...props.dateProps}
124
+ />
125
+ ),
126
+ }}
127
+ </PickerWrapper>
128
+ )
129
+ },
130
+ })