1 line
11 KiB
JSON
1 line
11 KiB
JSON
{"remainingRequest":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/vue-loader/lib/index.js??vue-loader-options!/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/src/tool/form/ConfigForm.vue?vue&type=style&index=0&id=78009953&scoped=true&lang=stylus","dependencies":[{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/src/tool/form/ConfigForm.vue","mtime":1742646402774},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/css-loader/dist/cjs.js","mtime":1743264596127},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/vue-loader/lib/loaders/stylePostLoader.js","mtime":1743264597030},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/postcss-loader/src/index.js","mtime":1743264596321},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/stylus-loader/index.js","mtime":1743264596421},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/style-resources-loader/lib/index.js","mtime":1743264596701},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/cache-loader/dist/cjs.js","mtime":1743264595665},{"path":"/Users/shuguang/Desktop/毕设/CodeMaster/CodeMaster/node_modules/vue-loader/lib/index.js","mtime":1743264596512}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:Ci5mb3JtLWNvbnRhaW5lciA+Pj4KICBkaXNwbGF5IGdyaWQKICBncmlkLXRlbXBsYXRlLWNvbHVtbnMgcmVwZWF0KGF1dG8tZmlsbCwgbWlubWF4KDI0MHB4LCAxZnIpKQogIGdyaWQtZ2FwIDEycHgKICBqdXN0aWZ5LWl0ZW1zIGNlbnRlcgoKLmZvcm0taXRlbQogIHdpZHRoIDEwMCUKICBkaXNwbGF5IGZsZXgKICBmbGV4LWRpcmVjdGlvbiBjb2x1bW4KCi5mb3JtLWl0ZW0tbGFiZWwgPj4+CiAgaGVpZ2h0IDIycHgKICBsaW5lLWhlaWdodCAyMnB4CiAgbWFyZ2luLWJvdHRvbSAxMHB4CiAgY29sb3IgcHJpbWFyeS10ZXh0LWNvbG9yCiAgZm9udC1zaXplIDE0cHgKICAuYnVpLXNlbGVjdC13cmFwcGVyLXBsYWluCiAgICBkaXNwbGF5IGZsZXgKICAgIGFsaWduLWl0ZW1zIGNlbnRlcgogICAgaGVpZ2h0IDIycHgKICAgIC5idWktc2VsZWN0LWljb24tcGxhaW4KICAgICAgbWFyZ2luLWJvdHRvbSAwCgouZm9ybS1pdGVtLWNvbnRlbnQKICAuY29udGVudAogICAgd2lkdGggMTAwJQogIC5lcnItbXNnCiAgICBtYXJnaW4tdG9wIDVweAogICAgZm9udC1zaXplIDEycHgKICAgIGNvbG9yIGVycm9yLWNvbG9yCg=="},{"version":3,"sources":["ConfigForm.vue"],"names":[],"mappings":";AAuSA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA","file":"ConfigForm.vue","sourceRoot":"src/tool/form","sourcesContent":["e<template lang=\"pug\">\n.form-container\n .form-item(\n v-for=\"option in options\",\n :key=\"option.key\",\n :class=\"{ [errorClass]: !!errors[option.key] }\"\n )\n .form-item-label\n FormItemLabel(ref=\"formItem\", :option=\"option.label\")\n .form-item-content\n FormItemContent.content(ref=\"formItem\", :option=\"option\")\n .err-msg(v-if=\"errors[option.key]\") {{ errors[option.key] }}\n</template>\n\n<script>\nimport FormItemLabel from './label';\nimport FormItemContent from './content';\nimport AsyncValidator from 'async-validator';\nimport {\n isFunction,\n isPlainObject,\n cloneDeep,\n isString,\n omit,\n noop,\n has,\n} from 'lodash-es';\nimport {\n getDefaultValue,\n getInjectedEvents,\n getFilterData,\n notEmpty,\n} from './helpers';\n\nexport default {\n name: 'ConfigForm',\n components: {\n FormItemLabel,\n FormItemContent,\n },\n props: {\n /**\n * 组件核心配置项\n */\n options: {\n type: Array,\n default: () => [],\n },\n /**\n * 用于匹配组件,用户可以根据接收到的组件名称返回想要的组件,返回结果将作为createElement的第一个参数\n */\n matcher: {\n type: Function,\n default: noop,\n },\n /**\n * 简单的i18n处理函数\n */\n locale: {\n type: Function,\n default: key => key,\n },\n /**\n * 为校验失败项添加的默认类名,外部可根据这个类名去定义/修改组件样式\n */\n errorClass: {\n type: String,\n default: 'form-item-error',\n },\n },\n data() {\n return {\n formData: {},\n flatOptions: {}, // 按key将原始选项存储\n validator: null,\n errors: {},\n };\n },\n computed: {\n result() {\n const result = {};\n const { formData, flatOptions } = this;\n for (const [key, value] of Object.entries(flatOptions)) {\n const { mapper } = value;\n\n // mapper为false代表当前key值不需要加入最终结果\n if (mapper === false) continue;\n\n // mapper没有返回值的话默认使用当前值 formData[key] 兜底\n const mapperValue = isFunction(mapper) ? mapper(formData) : formData[key];\n // 空值过滤\n if (isPlainObject(mapperValue)) {\n Object.assign(result, getFilterData(mapperValue));\n } else if (notEmpty(mapperValue)) {\n result[key] = mapperValue;\n }\n }\n return result;\n },\n },\n watch: {\n options: {\n deep: true,\n immediate: true,\n handler() {\n this.initFormData();\n },\n },\n formData: {\n deep: true,\n handler(val) {\n this.$emit('change', val);\n },\n },\n },\n methods: {\n match(name) {\n // 匹配组件\n return this.matcher(name) ?? name;\n },\n initFormData() {\n const formData = {};\n const flatOptions = {};\n const descriptor = {};\n\n for (const item of this.options) {\n const { label, key, rules } = item;\n\n flatOptions[key] = item;\n if (rules) {\n // rules为函数时视为validator选项\n descriptor[key] = isFunction(rules) ? { validator: rules } : rules;\n }\n\n // 设置默认值,考虑项目可能没有引入VueRouter\n Object.assign(formData, getDefaultValue(item, this.$route?.query));\n\n // 处理label\n if (isPlainObject(label)) {\n flatOptions[label.key] = label;\n }\n }\n\n Object.assign(this, {\n flatOptions,\n formData,\n validator: new AsyncValidator(descriptor),\n });\n },\n getProps(key, options) {\n const { formData } = this;\n const {\n props = {},\n attrs = {},\n on: event = {},\n nativeOn: nativeEvent = {},\n ...otherOptions\n } = options;\n\n /**\n * 为事件处理函数注入setState参数\n */\n const on = getInjectedEvents(event, this.setState.bind(this));\n const nativeOn = getInjectedEvents(nativeEvent, this.setState.bind(this));\n\n const update = newVal => {\n this.$set(this.errors, key, null); // 清除错误状态\n this.setState({ [key]: newVal });\n };\n\n const allAttrs = Object.assign(attrs, props);\n\n return {\n ...otherOptions, // 其他选项直接原样传递,保证拓展性\n formOption: this.flatOptions[key], // 基本信息,便于用户使用matcher自定义组件\n key,\n nativeOn,\n on: Object.assign({}, on, {\n input: isFunction(on.input)\n ? newVal => { on.input(newVal); update(newVal); }\n : update,\n }),\n /**\n * 合并attrs/props,统一传给attrs\n * Vue内部解析属性时,会将对应组件的`props从所有的attrs中提取出来\n * 并将props传递给组件的props,剩下的attrs放进`$attrs`,所以默认传给attrs没有问题\n * 但是如果默认传给props将可能会导致某些自定义组件无法正确解析得到`$attrs`\n * 比如一些透传属性,组件中如果没有声明对应的props,没有被组件接搜的props属性将不会进入`$attrs`\n * 从而导致内部使用到`$attrs`变量的地方出现问题\n */\n attrs: Object.assign({}, allAttrs, {\n // 优先采用 value\n value: has(allAttrs, 'value')\n ? allAttrs.value\n : formData[key],\n }),\n };\n },\n createComponent(options) {\n const h = this.$createElement;\n const { component, key, ...otherOptions } = options;\n\n if (!key) {\n console.error('Missing required prop \\'key\\'');\n }\n\n // component 要么是string要么是function\n if (isString(component)) {\n return h(\n this.match(component),\n this.getProps(key, otherOptions),\n );\n }\n\n if (isFunction(component)) {\n const result = component(h, this.formData, this.setState);\n if (result instanceof this.$vnode.constructor) {\n return result;\n }\n // 不是VNode就认为是对象,包含component、props、attrs、on等属性\n return h(\n this.match(result.component),\n this.getProps(key, omit(result, 'component')),\n );\n }\n\n console.warn('\\'component\\' must be string or function');\n },\n /**\n * 下列函数外部可调用\n */\n getResult() {\n return cloneDeep(this.result);\n },\n getFormData() {\n return cloneDeep(this.formData);\n },\n setState(callback) {\n const data = isFunction(callback) ? callback(this.formData) : callback;\n if (isPlainObject(data)) {\n Object.assign(this.formData, data);\n }\n },\n reset() {\n const formData = {};\n for (const [key, value] of Object.entries(this.flatOptions)) {\n const { default: defaultValue } = value;\n formData[key] = isFunction(defaultValue)\n ? defaultValue({}) // 外部可能解构,传入空对象防报错\n : defaultValue;\n }\n this.formData = formData;\n this.errors = {};\n },\n toQuery() {\n const query = {};\n for (const key of Object.keys(this.flatOptions)) {\n const { toQuery, mapper } = this.flatOptions[key];\n let value;\n if (toQuery === true && isFunction(mapper)) {\n value = mapper(this.formData) ?? this.formData[key];\n } else if (isFunction(toQuery)) {\n value = toQuery(this.formData);\n }\n // 空值过滤, value不为 undefined 或 null 或 ''\n if (notEmpty(value)) {\n if (isPlainObject(value)) {\n Object.assign(query, getFilterData(value));\n } else {\n query[key] = value;\n }\n }\n }\n return query;\n },\n validate(options = {}) {\n return this.validator?.validate(this.formData, options).then(() => {\n this.errors = {};\n return this.getResult();\n }).catch(e => {\n const { errors } = e;\n if (Array.isArray(errors)) {\n this.errors = errors.reduce((result, item) => {\n result[item.field] = item.message;\n return result;\n }, {});\n }\n throw e;\n });\n },\n },\n};\n</script>\n\n<style scoped lang=\"stylus\">\n.form-container >>>\n display grid\n grid-template-columns repeat(auto-fill, minmax(240px, 1fr))\n grid-gap 12px\n justify-items center\n\n.form-item\n width 100%\n display flex\n flex-direction column\n\n.form-item-label >>>\n height 22px\n line-height 22px\n margin-bottom 10px\n color primary-text-color\n font-size 14px\n .bui-select-wrapper-plain\n display flex\n align-items center\n height 22px\n .bui-select-icon-plain\n margin-bottom 0\n\n.form-item-content\n .content\n width 100%\n .err-msg\n margin-top 5px\n font-size 12px\n color error-color\n</style>\n"]}]} |