diff --git a/packages/cli/src/config/vite-component.ts b/packages/cli/src/config/vite-component.ts index 9fc833c578d481f5b6f133238c19dfb0e556a216..c4af3f379294898111e72ed0bcb86b88c3febcf1 100644 --- a/packages/cli/src/config/vite-component.ts +++ b/packages/cli/src/config/vite-component.ts @@ -5,7 +5,7 @@ import { createComponentStyle } from "../plugins/create-component-style.js"; export default mergeConfig(CommonConfig, { logLevel: 'silent', - plugins: [createComponentStyle(), replace((format, args)=> `..${args[1]}/index.${format}.js`)], + plugins: [createComponentStyle(), replace((format, args)=> `../${args[0]}/index.${format}.js`)], build:{ lib: { fileName: "index", @@ -15,7 +15,7 @@ export default mergeConfig(CommonConfig, { output: { exports: "named", globals: (id: string)=>{ - if(id.includes('@components')) { + if(id.includes('@farris/mobile-ui-vue')) { const name = id.split('/').pop() || ''; return name.slice(0,1).toUpperCase() + name.slice(1); } diff --git a/packages/cli/src/plugins/create-component-style.ts b/packages/cli/src/plugins/create-component-style.ts index aa0f43ba824ae8d1d5725704cd908f8e3f516e16..0839337bc5611799899a6a068fb1938c6028698c 100644 --- a/packages/cli/src/plugins/create-component-style.ts +++ b/packages/cli/src/plugins/create-component-style.ts @@ -4,17 +4,17 @@ const getComponentStyle = (imports: string[]) => { const components = imports .filter(path => { - return path.startsWith('@components/') && !NotStyleComponents.find(notStylecomponent => path.includes(notStylecomponent)); + return path.startsWith('@farris/mobile-ui-vue/') && !NotStyleComponents.find(notStylecomponent => path.includes(notStylecomponent)); }) .filter((item, index, array) => { const targetIndex = array.filter(e=> e!==item).findIndex(e => item.includes(e)); return targetIndex < 0; }) .map(name => { - const paths = name.split('/'); + const component = name.split('/').pop(); return { - name: paths[1], - path: `../${paths[1]}/style.js` + name: component, + path: `../${component}/style.js` }; }); diff --git a/packages/cli/src/plugins/replace.ts b/packages/cli/src/plugins/replace.ts index 9e1825497749cd9416dbdf582b79771a2de19055..6aea2950c5a53144fdf000246f95b35ac72de72e 100644 --- a/packages/cli/src/plugins/replace.ts +++ b/packages/cli/src/plugins/replace.ts @@ -4,8 +4,8 @@ export function replace(path: (format: string, args: string[]) => string){ renderChunk(code: string, chunk: any) { const fileNames = chunk.fileName.split('.'); const format = fileNames[fileNames.length-2]; - return code.replace(/@components(\/\w+)/g, (...args)=>{ - return path(format, args); + return code.replace(/@farris\/mobile-ui-vue\/([\w-]+)/g, (match, captureGroup)=>{ + return path(format, [captureGroup]); }); } }; diff --git a/packages/designer/farris.config.mjs b/packages/designer/farris.config.mjs index fab0811a566e9472a18565b86accc6c5e2fa398d..e987a5432476f67d15d17b52b9e4272440064062 100644 --- a/packages/designer/farris.config.mjs +++ b/packages/designer/farris.config.mjs @@ -12,6 +12,7 @@ const replaceUIVueComponentsPath = function () { const chunk = bundle[fileName]; if (chunk.type === 'chunk') { chunk.code = chunk.code.replace(/@farris\/ui-vue\/components/g, '@farris/ui-vue'); + chunk.code = chunk.code.replace(/@farris\/mobile-ui-vue\/components/g, '@farris/mobile-ui-vue'); } } } @@ -23,7 +24,7 @@ export default { // outDir: fileURLToPath(new URL('./dist', import.meta.url)), // 外部依赖排除项 默认值 { include: [], exclude: [] } externals: { - include: ['jsonp', 'echarts', 'lodash-es', 'lodash', 'axios', '@farris/ui-vue', 'vue','rxjs','rxjs/operators'], + include: ['jsonp', 'echarts', 'lodash-es', 'lodash', 'axios', '@farris/ui-vue', '@farris/mobile-ui-vue', 'vue','rxjs','rxjs/operators'], filter: (externals) => { return (id) => { return externals.find((item) => { @@ -38,6 +39,7 @@ export default { alias: [ { find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) }, { find: '@farris/ui-vue/components', replacement: fileURLToPath(new URL('../ui-vue/components', import.meta.url)) }, + { find: '@farris/mobile-ui-vue/components', replacement: fileURLToPath(new URL('../mobile-ui-vue/components', import.meta.url)) }, { find: '@farris/code-editor-vue/components', replacement: fileURLToPath(new URL('../code-editor/components', import.meta.url)) } ], // 插件 默认值 [vue(), vueJsx()] 不要重复添加 diff --git a/packages/designer/index.html b/packages/designer/index.html index 7a905fd401862b12ed31c88276e16ab914d4bb06..627d3926d155b07f72857780d3e1891a82eb746c 100644 --- a/packages/designer/index.html +++ b/packages/designer/index.html @@ -5,6 +5,8 @@ + + Farris Vue Designer diff --git a/packages/designer/package.json b/packages/designer/package.json index ae954e68d4a19d09c6153455f3ad363a4a49db14..12679748b463e80ed73d50df83f82320f6ceadfd 100644 --- a/packages/designer/package.json +++ b/packages/designer/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@farris/ui-vue": "workspace:^", + "@farris/mobile-ui-vue": "workspace:^", "@farris/code-editor-vue":"workspace:^", "@monaco-editor/loader": "^1.4.0", "monaco-editor": "^0.52.2", diff --git a/packages/designer/public/assets/farris-mobile-page.css b/packages/designer/public/assets/farris-mobile-page.css new file mode 100644 index 0000000000000000000000000000000000000000..6c30cece8c14516dc4d9e3b36684b4c0d620da53 --- /dev/null +++ b/packages/designer/public/assets/farris-mobile-page.css @@ -0,0 +1,5124 @@ +@charset "UTF-8"; + +#app, +.fm-page { + position: absolute; + left: 0; + right: 0; + top: 0 +} + +a, +abbr, +acronym, +address, +applet, +article, +aside, +audio, +b, +big, +blockquote, +body, +canvas, +caption, +center, +cite, +code, +dd, +del, +details, +dfn, +div, +dl, +dt, +em, +embed, +fieldset, +figcaption, +figure, +footer, +form, +h1, +h2, +h3, +h4, +h5, +h6, +header, +hgroup, +html, +i, +iframe, +img, +ins, +kbd, +label, +legend, +li, +mark, +menu, +nav, +object, +ol, +output, +p, +pre, +q, +ruby, +s, +samp, +section, +small, +span, +strike, +strong, +sub, +summary, +sup, +table, +tbody, +td, +tfoot, +th, +thead, +time, +tr, +tt, +u, +ul, +var, +video { + margin: 0; + padding: 0 +} + +html { + line-height: 1; + -webkit-tap-highlight-color: transparent +} + +ol, +ul { + list-style: none +} + +table { + border-collapse: collapse; + border-spacing: 0 +} + +caption, +td, +th { + font-weight: 400; + vertical-align: middle +} + +blockquote, +q { + quotes: none +} + +blockquote::after, +blockquote::before, +q::after, +q::before { + content: ''; + content: none +} + +a img { + border: none +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +summary { + display: block +} + +*, +::after, +::before { + box-sizing: border-box +} + +#app, +body, +html { + overflow: hidden; + -webkit-overflow-scrolling: auto +} + +body { + min-height: 100vh; + display: flex; + color: #333; + background-color: #fff +} + +a { + text-decoration: none; + background: 0 0 +} + +button, +input[type=number], +input[type=text], +input[type=password], +input[type=email], +input[type=search], +select, +textarea { + margin: 0; + font-family: inherit; + -moz-appearance: none; + appearance: none; + -webkit-appearance: none +} + +#app { + bottom: 0 +} + +@supports ((height:constant(safe-area-inset-top)) or (height:env(safe-area-inset-top))) and (-webkit-overflow-scrolling:touch) { + #app { + bottom: 20px + } + + #app #app { + bottom: 0 + } +} + +.fm-text-light { + color: #888 +} + +.fm-text-lighter { + color: #777 +} + +.fm-text-lightest { + color: #666 +} + +.fm-text-emph { + color: #333 +} + +.fm-text-primary { + color: #3A90FF +} + +.fm-utils-clearfix::after { + content: ''; + clear: both; + overflow: hidden +} + +.fm-page { + flex: 1; + display: flex; + flex-direction: column; + background: #f9fafb; + overflow: hidden; + bottom: 0; + -webkit-overflow-scrolling: auto +} + +.fm-page-header { + flex-shrink: 0 +} + +.fm-page-main { + flex-basis: 0; + flex-shrink: 1; + flex-grow: 1; + padding-bottom: 12px; + overflow: auto; + display: flex; + flex-direction: column +} + +.fm-page-main::-webkit-scrollbar { + display: none +} + +.fm-page-navbar { + flex-shrink: 0 +} + +.fm-page-footer { + background-color: #fff +} + +.fm-page-footer-btns { + display: flex; + flex-direction: row; + align-items: center; + height: 100% +} + +.fm-page-footer-btns-item { + flex: 1; + display: flex; + flex-direction: column; + text-align: center; + justify-content: center +} + +.fm-page-footer-btns-item-icon { + margin-bottom: 4px; + font-size: 18px +} + +.fm-page-footer-btns-item-text { + font-size: 12px; + color: #999 +} + +.fm-page-footer-btns-item:hover .fm-page-footer-btns-item-icon { + font-size: 22px; + color: #3a90ff +} + +.fm-page-footer-btns-item:hover .fm-page-footer-btns-item-text { + color: #3a90ff +} + +.fm-form-control { + display: block; + width: 100%; + min-width: 0; + height: 22px; + margin: 0; + padding: 0 4px; + font-size: 14px; + color: #333; + line-height: inherit; + text-align: left; + background-color: transparent; + border: 1px solid #ddd; + border-radius: 3px; + resize: none +} + +.fm-form-control:focus { + border-color: #3499f6 +} + +.fm-textarea { + border-radius: 4px; + padding: 6px 16px; + width: 100%; + border: 1px solid #ddd; + outline: 0; + font-size: 14px; + line-height: 24px; + color: #333; + display: inline-flex; + vertical-align: middle +} + +.fm-textarea:focus { + border-color: #3499f6 +} + +.align-baseline { + vertical-align: baseline !important +} + +.align-top { + vertical-align: top !important +} + +.align-middle { + vertical-align: middle !important +} + +.align-bottom { + vertical-align: bottom !important +} + +.align-text-bottom { + vertical-align: text-bottom !important +} + +.align-text-top { + vertical-align: text-top !important +} + +.bg-info { + background-color: #4D9AFF !important +} + +.bg-submit { + background-color: #5AC1C3 !important +} + +.bg-success { + background-color: #5CC171 !important +} + +.bg-warning { + background-color: #FF9800 !important +} + +.bg-danger { + background-color: #F24645 !important +} + +.bg-white { + background-color: #fff !important +} + +.bg-transparent { + background-color: transparent !important +} + +.border { + border: 1px solid #DDD; + border-radius: 0 +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .border { + position: relative; + border: none + } + + html:not([data-scale]) .border::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 200%; + height: 200%; + border: 1px solid #DDD; + border-radius: 0; + transform-origin: 0 0; + transform: scale(.5); + box-sizing: border-box; + pointer-events: none + } +} + +.border-top { + border-top: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .border-top { + border-top: none + } + + html:not([data-scale]) .border-top::before { + content: ''; + position: absolute; + background-color: #DDD; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } +} + +.border-right { + border-right: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .border-right { + border-right: none + } + + html:not([data-scale]) .border-right::after { + content: ''; + position: absolute; + display: block; + z-index: 1; + top: 0; + right: 0; + bottom: auto; + left: auto; + width: 1PX; + height: 100%; + background: #DDD; + transform-origin: 100% 50%; + transform: scaleX(.5) + } +} + +.border-bottom { + border-bottom: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .border-bottom { + border-bottom: none + } + + html:not([data-scale]) .border-bottom::after { + content: ''; + position: absolute; + background-color: #DDD; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.border-left { + border-left: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .border-left { + border-left: none + } + + html:not([data-scale]) .border-left::before { + content: ''; + position: absolute; + background-color: #DDD; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 1PX; + height: 100%; + transform-origin: 100% 50%; + transform: scaleX(.5) + } +} + +.border-0::before, +.border-bottom-0::after, +.border-left-0::before, +.border-right-0::after, +.border-top-0::before { + display: none !important +} + +.border-0 { + border: 0 +} + +.border-top-0 { + border-top: 0 +} + +.border-right-0 { + border-right: 0 +} + +.border-bottom-0 { + border-bottom: 0 +} + +.border-left-0 { + border-left: 0 +} + +.clearfix::after { + display: block; + clear: both; + content: "" +} + +.display-none { + display: none !important +} + +.display-inline { + display: inline !important +} + +.display-inline-block { + display: inline-block !important +} + +.d-block, +.display-block { + display: block !important +} + +.display-table { + display: table !important +} + +.display-table-row { + display: table-row !important +} + +.display-table-cell { + display: table-cell !important +} + +.d-flex, +.display-flex, +.fm-utils-flex-column { + display: flex !important +} + +.display-inline-flex { + display: inline-flex !important +} + +.flex-direction-row, +.flex-row { + flex-direction: row !important +} + +.flex-column, +.flex-direction-column { + flex-direction: column !important +} + +.flex-direction-row-reverse, +.flex-row-reverse { + flex-direction: row-reverse !important +} + +.flex-column-reverse, +.flex-direction-column-reverse { + flex-direction: column-reverse !important +} + +.flex-row, +.fm-utils-flex-row { + flex-direction: row !important +} + +.float-left { + float: left !important +} + +.float-right { + float: right !important +} + +.float-none { + float: none !important +} + +.position-static { + position: static !important +} + +.position-relative { + position: relative !important +} + +.position-absolute { + position: absolute !important +} + +.position-fixed { + position: fixed !important +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important +} + +.fixed-bottom, +.fixed-top { + position: fixed; + z-index: 1030; + right: 0; + left: 0 +} + +.fixed-top { + top: 0 +} + +.fixed-bottom { + bottom: 0 +} + +.shadow-none { + box-shadow: none !important +} + +.w-25 { + width: 25% !important +} + +.w-50 { + width: 50% !important +} + +.w-75 { + width: 75% !important +} + +.w-100 { + width: 100% !important +} + +.w-auto { + width: auto !important +} + +.h-25 { + height: 25% !important +} + +.h-50 { + height: 50% !important +} + +.h-75 { + height: 75% !important +} + +.h-100 { + height: 100% !important +} + +.h-auto { + height: auto !important +} + +.mw-100 { + max-width: 100% !important +} + +.mh-100 { + max-height: 100% !important +} + +.m-0 { + margin: 0 !important +} + +.mt-0, +.my-0 { + margin-top: 0 !important +} + +.mr-0, +.mx-0 { + margin-right: 0 !important +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important +} + +.ml-0, +.mx-0 { + margin-left: 0 !important +} + +.p-0 { + padding: 0 !important +} + +.pt-0, +.py-0 { + padding-top: 0 !important +} + +.pr-0, +.px-0 { + padding-right: 0 !important +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important +} + +.pl-0, +.px-0 { + padding-left: 0 !important +} + +.m-base { + margin: 4px !important +} + +.mt-base, +.my-base { + margin-top: 4px !important +} + +.mr-base, +.mx-base { + margin-right: 4px !important +} + +.mb-base, +.my-base { + margin-bottom: 4px !important +} + +.ml-base, +.mx-base { + margin-left: 4px !important +} + +.p-base { + padding: 4px !important +} + +.pt-base, +.py-base { + padding-top: 4px !important +} + +.pr-base, +.px-base { + padding-right: 4px !important +} + +.pb-base, +.py-base { + padding-bottom: 4px !important +} + +.pl-base, +.px-base { + padding-left: 4px !important +} + +.m-xs { + margin: 8px !important +} + +.mt-xs, +.my-xs { + margin-top: 8px !important +} + +.mr-xs, +.mx-xs { + margin-right: 8px !important +} + +.mb-xs, +.my-xs { + margin-bottom: 8px !important +} + +.ml-xs, +.mx-xs { + margin-left: 8px !important +} + +.p-xs { + padding: 8px !important +} + +.pt-xs, +.py-xs { + padding-top: 8px !important +} + +.pr-xs, +.px-xs { + padding-right: 8px !important +} + +.pb-xs, +.py-xs { + padding-bottom: 8px !important +} + +.pl-xs, +.px-xs { + padding-left: 8px !important +} + +.m-sm { + margin: 12px !important +} + +.mt-sm, +.my-sm { + margin-top: 12px !important +} + +.mr-sm, +.mx-sm { + margin-right: 12px !important +} + +.mb-sm, +.my-sm { + margin-bottom: 12px !important +} + +.ml-sm, +.mx-sm { + margin-left: 12px !important +} + +.p-sm { + padding: 12px !important +} + +.pt-sm, +.py-sm { + padding-top: 12px !important +} + +.pr-sm, +.px-sm { + padding-right: 12px !important +} + +.pb-sm, +.py-sm { + padding-bottom: 12px !important +} + +.pl-sm, +.px-sm { + padding-left: 12px !important +} + +.m-md { + margin: 16px !important +} + +.mt-md, +.my-md { + margin-top: 16px !important +} + +.mr-md, +.mx-md { + margin-right: 16px !important +} + +.mb-md, +.my-md { + margin-bottom: 16px !important +} + +.ml-md, +.mx-md { + margin-left: 16px !important +} + +.p-md { + padding: 16px !important +} + +.pt-md, +.py-md { + padding-top: 16px !important +} + +.pr-md, +.px-md { + padding-right: 16px !important +} + +.pb-md, +.py-md { + padding-bottom: 16px !important +} + +.pl-md, +.px-md { + padding-left: 16px !important +} + +.m-lg { + margin: 24px !important +} + +.mt-lg, +.my-lg { + margin-top: 24px !important +} + +.mr-lg, +.mx-lg { + margin-right: 24px !important +} + +.mb-lg, +.my-lg { + margin-bottom: 24px !important +} + +.ml-lg, +.mx-lg { + margin-left: 24px !important +} + +.p-lg { + padding: 24px !important +} + +.pt-lg, +.py-lg { + padding-top: 24px !important +} + +.pr-lg, +.px-lg { + padding-right: 24px !important +} + +.pb-lg, +.py-lg { + padding-bottom: 24px !important +} + +.pl-lg, +.px-lg { + padding-left: 24px !important +} + +.m-xl { + margin: 32px !important +} + +.mt-xl, +.my-xl { + margin-top: 32px !important +} + +.mr-xl, +.mx-xl { + margin-right: 32px !important +} + +.mb-xl, +.my-xl { + margin-bottom: 32px !important +} + +.ml-xl, +.mx-xl { + margin-left: 32px !important +} + +.p-xl { + padding: 32px !important +} + +.pt-xl, +.py-xl { + padding-top: 32px !important +} + +.pr-xl, +.px-xl { + padding-right: 32px !important +} + +.pb-xl, +.py-xl { + padding-bottom: 32px !important +} + +.pl-xl, +.px-xl { + padding-left: 32px !important +} + +.m-auto { + margin: auto !important +} + +.mt-auto, +.my-auto { + margin-top: auto !important +} + +.mr-auto, +.mx-auto { + margin-right: auto !important +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important +} + +.ml-auto, +.mx-auto { + margin-left: auto !important +} + +.text-justify { + text-align: justify !important +} + +.text-nowrap { + white-space: nowrap !important +} + +.text-align-left { + text-align: left !important +} + +.text-align-right { + text-align: right !important +} + +.text-align-center { + text-align: center !important +} + +.text-lowercase { + text-transform: lowercase !important +} + +.text-uppercase { + text-transform: uppercase !important +} + +.text-capitalize { + text-transform: capitalize !important +} + +.font-weight-light { + font-weight: 300 !important +} + +.font-weight-normal { + font-weight: 400 !important +} + +.font-weight-bold { + font-weight: 700 !important +} + +.font-italic { + font-style: italic !important +} + +.text-white { + color: #fff !important +} + +.visible { + visibility: visible +} + +.invisible { + visibility: hidden +} + +.d-flex { + display: flex +} + +.d-inline-flex { + display: inline-flex +} + +.d-block { + display: block +} + +.d-inline-block { + display: inline-block +} + +.d-inline { + display: inline +} + +.flex-column { + flex-direction: column !important +} + +.flex-row-reverse { + flex-direction: row-reverse !important +} + +.flex-column-reverse { + flex-direction: column-reverse !important +} + +.flex-wrap { + flex-wrap: wrap !important +} + +.flex-nowrap { + flex-wrap: nowrap !important +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important +} + +.flex-fill { + flex: 1 1 auto !important +} + +.flex-grow-0 { + flex-grow: 0 !important +} + +.flex-grow-1 { + flex-grow: 1 !important +} + +.flex-shrink-0 { + flex-shrink: 0 !important +} + +.flex-shrink-1 { + flex-shrink: 1 !important +} + +.justify-content-start { + justify-content: flex-start !important +} + +.justify-content-end { + justify-content: flex-end !important +} + +.justify-content-center { + justify-content: center !important +} + +.justify-content-between { + justify-content: space-between !important +} + +.justify-content-around { + justify-content: space-around !important +} + +.align-items-start { + align-items: flex-start !important +} + +.align-items-end { + align-items: flex-end !important +} + +.align-items-center { + align-items: center !important +} + +.align-items-baseline { + align-items: baseline !important +} + +.align-items-stretch { + align-items: stretch !important +} + +.align-content-start { + align-content: flex-start !important +} + +.align-content-end { + align-content: flex-end !important +} + +.align-content-center { + align-content: center !important +} + +.align-content-between { + align-content: space-between !important +} + +.align-content-around { + align-content: space-around !important +} + +.align-content-stretch { + align-content: stretch !important +} + +.align-self-auto { + align-self: auto !important +} + +.align-self-start { + align-self: flex-start !important +} + +.align-self-end { + align-self: flex-end !important +} + +.align-self-center { + align-self: center !important +} + +.align-self-baseline { + align-self: baseline !important +} + +.align-self-stretch { + align-self: stretch !important +} + +.fm-utils-absolute-all { + top: 0; + bottom: 0; + position: absolute; + right: 0; + left: 0 +} + +.fm-utils-flex-column { + flex-direction: column !important; + overflow: hidden +} + +.fm-utils-fill-flex-column, +.fm-utils-fill-flex-row { + flex-shrink: 1; + display: flex !important; + overflow: hidden +} + +.fm-utils-fill-flex-column { + flex-grow: 1; + flex-basis: 0; + flex-direction: column !important +} + +.fm-utils-flex-row { + display: flex !important; + overflow: hidden; + flex-wrap: nowrap +} + +.fm-utils-flex-row-wrap { + display: flex !important; + flex-direction: row !important; + overflow: hidden; + flex-wrap: wrap !important +} + +.fm-utils-fill-flex-row { + flex-grow: 1; + flex-basis: 0; + flex-direction: row !important; + flex-wrap: nowrap !important +} + +.fm-utils-fill-flex-row-wrap { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + display: flex !important; + flex-direction: row !important; + overflow: hidden; + flex-wrap: wrap !important +} + +.fm-utils-fill { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-utils-fill-auto { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow-x: hidden; + overflow-y: auto +} + +.fm-utils-overflow-xhya { + overflow-x: hidden !important; + overflow-y: auto !important +} + +.fm-utils-overflow-xayh { + overflow-y: hidden !important; + overflow-x: auto !important +} + +.fm-utils-overflow-xaya { + overflow: auto !important +} + +.fm-utils-overflow-hidden { + overflow: hidden !important +} + +.fm-utils-overflow-auto { + overflow: auto !important +} + +.fm-overflow-x-auto { + overflow-x: auto !important +} + +.fm-overflow-x-hidden, +.fm-overflow-y-auto, +.fm-overflow-y-hidden { + overflow-x: hidden !important +} + +.fm-overflow-y-auto { + overflow-y: auto !important +} + +.fm-overflow-y-hidden { + overflow-y: hidden !important +} + +.fm-overflow-hidden { + overflow: hidden !important +} + +.fm-utils-text-break { + white-space: normal !important; + word-break: break-all !important +} + +.fm-utils-display-none { + display: none !important +} + +.fm-multi-ellipsis-l2, +.fm-multi-ellipsis-l3 { + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis +} + +.fm-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis +} + +.fm-multi-ellipsis-l2 { + -webkit-line-clamp: 2 +} + +.fm-multi-ellipsis-l3 { + -webkit-line-clamp: 3 +} + +.fm-float-button-wrapper { + position: absolute; + right: 16px; + bottom: 50px +} + +.fm-listview-error { + background: #fff; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .12) +} + +.fm-error-cell { + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 16px; + height: 32px +} + +.fm-error-cell:not(:last-child)::after { + content: ''; + height: 1px; + position: absolute; + background-color: #f1f1f1; + display: block; + z-index: 1; + bottom: 0; + left: 16px; + right: 0; + transform: translateY(.5) +} + +.fm-error-text { + font-size: 13px; + color: #f24645; + line-height: 22px +} + +.fm-error-icon { + background: #F24645; + color: #fff; + border-radius: 100%; + margin-right: 4px +} + +.fm-without-last-child .fm-bottom-line { + border-bottom: 1px solid var(--fm-border-color); + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-without-last-child .fm-bottom-line { + border-bottom: none + } + + html:not([data-scale]) .fm-without-last-child .fm-bottom-line::after { + content: ''; + position: absolute; + background-color: var(--fm-border-color); + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-single-header { + height: 32px; + display: flex; + align-items: center; + padding: 0 0 0 16px; + background: #F8F9FB +} + +.fm-tmpl-single-header h6 { + color: #999; + font-size: 15px; + font-weight: 400; + margin: 0 +} + +.fm-tmpl-singlelist-with-iconarea { + background: #fff; + overflow: hidden +} + +.fm-tmpl-singlelist-with-iconarea .singlelist--item { + align-items: center; + padding: 0 0 0 16px; + display: flex +} + +.fm-tmpl-singlelist-with-iconarea .singlelist--item:last-child .singlelist--item-title-wrapper { + border-bottom: none +} + +.fm-tmpl-singlelist-with-iconarea .singlelist--item .item-img-round--wrapper .item-img-round--img { + width: 26px; + height: 26px; + border-radius: 13px +} + +.fm-tmpl-singlelist-with-iconarea .singlelist--item .item-img-round--wrapper .item-img-round--img .fm-icon { + line-height: 26px +} + +.fm-tmpl-singlelist-with-iconarea .singlelist--item-title-wrapper { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + color: #333; + font-size: 16px; + line-height: 22px; + padding: 11px 0 10px; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-singlelist-with-iconarea .singlelist--item-title-wrapper { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-singlelist-with-iconarea .singlelist--item-title-wrapper::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.item-img-round--wrapper { + margin: 0 10px 0 0 +} + +.item-img-round--wrapper .item-img-round--img { + width: 30px; + height: 30px; + border-radius: 15px; + text-align: center; + color: #fff +} + +.item-img-round--wrapper .item-img-round--img .fm-icon { + font-size: 18px; + line-height: 30px +} + +.item-img-round--wrapper .fm-bg-yellow { + background: #FBB902 +} + +.item-img-round--wrapper .fm-bg-orange { + background: #FF9800 +} + +.item-img-round--wrapper .fm-bg-blue { + background: #4D9AFF +} + +.item-img-round--wrapper .fm-bg-lightblue { + background: #5ACBCD +} + +.item-img-round--wrapper .fm-bg-purple { + background: #817EFF +} + +.item-img-round--wrapper .fm-bg-darkgreen { + background: #51BD78 +} + +.fm-tmpl-header-with-img { + display: flex; + align-items: center +} + +.fm-tmpl-header-with-img h5 { + font-size: 16px; + color: #333; + margin: 0; + font-weight: 400 +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper { + margin: 0 8px 0 0 +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper .header-with-img--img { + width: 20px; + height: 20px; + border-radius: 10px; + line-height: 20px; + text-align: center; + color: #fff; + background-image: linear-gradient(180deg, #64CDFB 1%, #3A90FF 100%) +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper .header-with-img--img .fm-icon { + font-size: 12px +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper .fm-bg-blue { + color: #fff; + background-image: linear-gradient(180deg, #64CDFB 1%, #3A90FF 100%) +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper .fm-bg-orange { + color: #fff; + background-image: linear-gradient(180deg, #FFB951 15%, #FF9800 100%) +} + +.fm-tmpl-header-with-img .header-with-img--img-wrapper .fm-bg-green { + color: #fff; + background-image: linear-gradient(180deg, #7ACC8D 15%, #51BD78 100%) +} + +.fm-cmp-collapse-style::after { + display: none +} + +.fm-cmp-collapse-style .van-collapse-item__title { + align-items: center +} + +.fm-cmp-collapse-style .van-collapse-item__content { + padding: 0 +} + +.fm-cmp-collapse-style.van-collapse { + margin: 0 0 12px +} + +.fm-cmp-collapse-style.van-collapse:last-child { + margin-bottom: 0 +} + +.fm-tmpl-collapse-sub::after { + border-bottom: 0 +} + +.fm-tmpl-collapse-sub-header { + display: flex; + flex-direction: column-reverse +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title .expand, +.fm-tmpl-collapse-sub-header .van-collapse-item__title--expanded .collapse { + display: none +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title { + color: #888; + flex-direction: row-reverse; + justify-content: center +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title h6 { + color: #888; + font-size: 13px; + font-weight: 400 +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title .collapse-icon { + margin: 0 8px; + transition: transform .3s +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title--expanded .expand { + display: inline-block +} + +.fm-tmpl-collapse-sub-header .van-collapse-item__title--expanded .collapse-icon { + transform: rotate(180deg) +} + +.fm-btn-block-wrapper { + height: 42px; + background: #fff; + display: flex; + align-items: center +} + +.fm-btn-block-wrapper .fm-button { + font-size: 14px !important; + height: 100% +} + +.fm-btn-with-icon .fm-btn-text { + margin: 0 8px +} + +.fm-btn-with-icon .fm-btn-icon { + font-size: 14px +} + +.fm-tmpl-list-with-img-detail.fm-tmpl-list-with-border { + margin-bottom: 12px +} + +.fm-tmpl-list-with-img-detail.fm-tmpl-list-with-border .img-detail--item { + margin-bottom: 0; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-list-with-img-detail.fm-tmpl-list-with-border .img-detail--item { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-list-with-img-detail.fm-tmpl-list-with-border .img-detail--item::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-round-bg { + margin: 4px auto 0; + width: 36px; + height: 36px; + background: #3A90FF; + border-radius: 20px; + line-height: 36px; + font-size: 13px; + text-align: center; + overflow: hidden; + white-space: nowrap +} + +.fm-round-bg-text { + color: #FFF +} + +.fm-tmpl-list-with-img-detail .img-detail--item { + padding: 12px 16px; + background: #fff; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-list-with-img-detail .img-detail--item { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-list-with-img-detail .img-detail--item::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--item-content { + display: flex; + position: relative +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--status { + position: absolute; + right: 0; + top: 23px +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--content { + position: relative; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0 +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--header { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0 0 6px +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--header .title { + line-height: 22px; + font-weight: 400; + font-size: 16px; + color: #333 +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--header .time { + line-height: 18px; + color: #999; + font-size: 13px +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--info { + line-height: 18px; + color: #999; + font-size: 13px; + margin: 0 0 4px +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--info>.gutter { + margin: 0 14px 0 0 +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--actions { + padding: 18px 0 0; + text-align: right +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--actions .fm-button { + margin-left: 13px +} + +.fm-tmpl-list-with-img-detail .img-detail--item .img-detail--actions .fm-button:first-child { + margin-left: 0 +} + +.fm-tmpl-result { + display: flex; + flex-direction: column; + padding-top: 40px; + align-items: center +} + +.fm-tmpl-result-header .fm-result-title { + display: flex; + flex-direction: row; + font-size: 20px; + color: #333 +} + +.fm-tmpl-result-header .fm-result-title .fm-result-title-number { + color: #FF9800 +} + +.fm-tmpl-result-content { + max-width: 84%; + padding-top: 30px; + padding-bottom: 30px; + text-align: center +} + +.fm-tmpl-result-content .fm-result-img { + width: 140px; + height: 140px; + margin: 0 auto +} + +.fm-tmpl-result-content .fm-result-img img { + display: block; + width: 140px; + height: 140px +} + +.fm-tmpl-result-content .fm-result-text { + padding-top: 30px; + padding-bottom: 10px; + font-size: 16px; + color: #333; + text-align: center +} + +.fm-tmpl-result-content .fm-result-tip { + line-height: 22px; + font-size: 16px; + color: #888; + text-align: center +} + +.fm-tmpl-result-footer { + width: 140px; + margin: 0 auto +} + +.fm-tmpl-result-footer .fm-result-btn { + margin-bottom: 16px +} + +.fm-tmpl-result-footer .fm-result-btn:last-child { + margin-bottom: 0 +} + +.fm-tabbar-style { + border-top: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tabbar-style { + border-top: none + } + + html:not([data-scale]) .fm-tabbar-style::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } +} + +.fm-tabbar-style .show-fixed-width { + padding: 0 17px; + flex-shrink: 0; + flex-grow: 0; + flex-basis: auto +} + +.fm-tabbar-style .show-fixed-width+.show-left-width { + padding: 7px 16px 7px 0 +} + +.fm-tabbar-style .show-fixed-width .van-tabbar-item__icon .fm-icon { + font-size: 19px +} + +.fm-tabbar-style .show-fixed-width .van-tabbar-item__text { + font-size: 12px; + transform: scale(.8333) +} + +.fm-tabbar-style .show-left-width { + padding: 7px 16px +} + +.fm-tabbar-style .show-left-width .fm-button { + height: 100% +} + +.fm-tmpl-detail-header { + padding-left: 16px; + background-color: #fff +} + +.fm-tmpl-detail-header-inner { + display: flex; + flex-direction: row; + align-items: center; + padding: 16px 16px 16px 0; + border-bottom: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-detail-header-inner { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-detail-header-inner::after { + content: ''; + position: absolute; + background-color: #DDD; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-approve-flow-wrapper .fm-approve-flow-item .fm-approve-flow-item-header-icon .header-icon::before, +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar .avatar-icon::before { + content: "\e6b4" +} + +.fm-tmpl-detail-header-inner .detail-header--avatar { + width: 40px; + margin-right: 10px; + border-radius: 50%; + overflow: hidden +} + +.fm-tmpl-detail-header-inner .detail-header--avatar img { + display: block; + width: 40px; + height: 40px +} + +.fm-tmpl-detail-header-inner .detail-header--content { + flex: 1 +} + +.fm-tmpl-detail-header-inner .detail-header--content-title { + margin-bottom: 3px; + font-size: 15px; + color: #333 +} + +.fm-tmpl-detail-header-inner .detail-header--content-subtitle { + font-size: 13px; + color: #888 +} + +.fm-static-input-list { + padding: 16px 0 16px 16px; + background-color: #fff; + margin: 0 0 8px +} + +.fm-static-input-list .fm-listview-item:last-child .fm-static-input-info { + margin-bottom: 0 +} + +.fm-static-input-info { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 8px; + line-height: 20px +} + +.fm-static-input-info .input-info--label { + width: 92px; + font-size: 14px; + color: #999; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.fm-static-input-info .input-info--text { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + padding-left: 8px; + font-size: 14px; + color: #333 +} + +.fm-static-input-info .input-info--accessory { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap +} + +.fm-static-input-info .input-info--accessory-item { + flex-shrink: 0; + width: 28px; + height: 28px; + margin-right: 12px; + border-radius: 3px; + overflow: hidden +} + +.fm-static-input-info .input-info--accessory-item img { + display: block; + width: 28px +} + +.fm-static-input-info .input-info--accessory-item:last-child { + margin-right: 0 +} + +.fm-approve-flow-wrapper { + padding: 12px 16px; + background-color: #fff +} + +.fm-approve-flow-wrapper .fm-approve-flow-item { + padding-left: 7px +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header { + position: relative; + border-left: 1px dashed #D4D4D4 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 28px +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon { + position: absolute; + left: -8px; + top: 0; + z-index: 100 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon .fm-icon { + background-color: #fff; + font-size: 15px; + color: #34AAFF; + border-radius: 50% +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon img { + background: #fff +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-content { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + line-height: 21px; + font-size: 15px; + color: #4C4C4C; + font-weight: 700 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-right { + flex-shrink: 0; + padding-left: 6px +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-right .fm-icon { + color: #979797 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-header-state { + margin-top: 6px; + padding-left: 28px; + font-size: 13px; + color: #FF9002 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content { + display: flex; + flex-direction: row; + align-items: flex-start; + padding: 12px 0 30px 28px; + border-left: 1px dashed #D4D4D4 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + display: flex; + flex-direction: row; + align-items: flex-start +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + width: 36px; + height: 36px +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar-img { + display: block; + width: 36px; + height: 36px; + border-radius: 50% +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar-icon { + position: absolute; + right: 4px; + bottom: -4px; + font-size: 14px; + color: #34AAFF; + background-color: #fff; + border-radius: 50% +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-text { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + padding: 0 6px 0 9px +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-text-title { + font-size: 13px; + color: rgba(51, 51, 51, .65) +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-main-text-subtitle { + margin-top: 2px; + line-height: 20px; + font-size: 14px; + color: #333 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item-content .fm-approve-flow-item-date { + font-size: 13px; + color: rgba(51, 51, 51, .65) +} + +.fm-approve-flow-wrapper .fm-approve-flow-item.fm-approve-flow-item-approved .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar-icon, +.fm-approve-flow-wrapper .fm-approve-flow-item.fm-approve-flow-item-approved .fm-approve-flow-item-header .fm-approve-flow-item-header-icon .fm-icon, +.fm-approve-flow-wrapper .fm-approve-flow-item.fm-approve-flow-item-approved .fm-approve-flow-item-header .fm-approve-flow-item-header-state { + color: #1AD0C8 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item.fm-approve-flow-item-approved .fm-approve-flow-item-content .fm-approve-flow-item-main-avatar .avatar-icon::before, +.fm-approve-flow-wrapper .fm-approve-flow-item.fm-approve-flow-item-approved .fm-approve-flow-item-header .fm-approve-flow-item-header-icon .header-icon::before { + content: "\e6b3" +} + +.fm-approve-flow-wrapper .fm-approve-flow-item:last-child .fm-approve-flow-item-header { + border-left: 0 +} + +.fm-approve-flow-wrapper .fm-approve-flow-item:last-child .fm-approve-flow-item-header::before { + display: none !important +} + +.fm-approve-flow-wrapper .fm-approve-flow-item:last-child .fm-approve-flow-item-content { + padding-bottom: 12px; + border-left: none +} + +.fm-approve-nopass, +.fm-approve-pass { + position: fixed; + top: 48px; + right: 14px; + width: 110px; + height: 110px; + z-index: 1000 +} + +.fm-approve--detail-header { + padding-left: 16px; + background-color: #fff +} + +.fm-approve--detail-header-inner { + display: flex; + flex-direction: row; + align-items: center; + padding: 17px 16px 17px 0; + border-bottom: 1px solid #DDD; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-approve--detail-header-inner { + border-bottom: none + } + + html:not([data-scale]) .fm-approve--detail-header-inner::after { + content: ''; + position: absolute; + background-color: #DDD; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-approve--detail-header-inner .detail-header--avatar { + width: 40px; + margin-right: 10px; + border-radius: 50%; + overflow: hidden +} + +.fm-approve--detail-header-inner .detail-header--avatar img { + display: block; + width: 40px; + height: 40px +} + +.fm-approve--detail-header-inner .detail-header---info { + flex: 1 +} + +.fm-approve--detail-header-inner .detail-header---info-title { + margin-bottom: 3px; + font-size: 15px; + color: #333 +} + +.fm-approve--detail-header-inner .detail-header---info-subtitle { + font-size: 13px; + color: #888 +} + +.fm-apply-list-wrapper { + padding: 0 16px 16px; + background-color: #fff; + margin: 0 0 12px +} + +.fm-apply-list-item { + display: flex; + flex-direction: row; + align-items: flex-start; + margin-bottom: 8px; + line-height: 20px +} + +.fm-apply-list-item-label { + width: 92px; + font-size: 14px; + color: #999; + text-align: right; + word-break: break-all +} + +.fm-apply-list-item-text { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + padding-left: 14px; + font-size: 14px; + color: #333; + word-break: break-all +} + +.fm-apply-list-item-accessory { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap +} + +.fm-apply-list-item-accessory-item { + flex-shrink: 0; + width: 28px; + height: 28px; + margin-right: 12px; + border-radius: 3px; + overflow: hidden +} + +.fm-apply-list-item-accessory-item img { + display: block; + width: 28px +} + +.fm-apply-list-item-accessory-item:last-child { + margin-right: 0 +} + +.fm-apply-list-item:last-child { + margin-bottom: 0 +} + +.fm-apply-panel-title, +.fm-apply-plate-title { + height: 28px; + line-height: 28px; + padding-left: 10px; + margin-bottom: 0; + background: #F6F6F6; + border-radius: 2px +} + +.fm-apply-panel-action, +.fm-apply-plate-action { + padding: 0 6px; + margin: 0 0 0 auto; + color: #D8D8D8 +} + +.fm-apply-panel-action:hover, +.fm-apply-plate-action:hover { + background: #3A90FF; + color: #fff +} + +.fm-apply-panel { + padding-top: 0 +} + +.fm-apply-panel .fm-apply-list { + padding-top: 10px; + padding-bottom: 14px +} + +.fm-apply-panel .fm-apply-list+.fm-apply-list { + border-top: 1px solid #E8E8E8 +} + +.fm-apply-panel-list { + padding: 0 16px; + background-color: #fff; + margin: 0; + border-bottom: 1px solid #E8E8E8 +} + +.fm-apply-panel-list:last-child { + border-bottom: none +} + +.fm-apply-panel-list .panel-list--header { + height: 42px; + display: flex; + align-items: center +} + +.fm-apply-panel-list .panel-list--header .panel-list--header-title { + font-size: 15px; + line-height: 21px; + color: #333; + padding: 0 0 0 10px; + position: relative +} + +.fm-apply-panel-list .panel-list--header .panel-list--header-title::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + width: 3px; + height: 14px; + margin: -7px 0 0; + background: #55BBF6 +} + +.fm-apply-details { + margin: 0 0 14px; + background: #fff +} + +.fm-apply-main { + border-bottom: 1px solid #E8E8E8 +} + +.fm-avatar-with-state { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + width: 36px; + height: 36px +} + +.fm-avatar-with-state--img { + display: block; + width: 36px; + height: 36px; + border-radius: 50% +} + +.fm-avatar-with-state--icon { + position: absolute; + right: 4px; + bottom: -4px; + font-size: 14px; + color: #34AAFF; + background-color: #fff; + border-radius: 50% +} + +.fm-avatar-with-state .avatar-icon::before { + content: "\e6b3" +} + +.fm-avatar-with-state .fm-round-bg { + background: rgba(77, 154, 255, .6) +} + +.fm-avatar-with-state.fm-state-running .avatar-icon::before { + content: "\e6b4" +} + +.fm-feature-select-person { + display: flex; + flex-direction: row; + flex-wrap: wrap; + padding: 0 0 14px +} + +.fm-feature-select-person .select-person--item { + position: relative; + display: flex; + align-items: center; + margin: 0 16px 0 0 +} + +.fm-feature-select-person .select-person--item .fm-avatar-with-state { + width: 48px; + height: 48px +} + +.fm-feature-select-person .select-person--item .fm-avatar-with-state .fm-avatar-with-state--img { + width: 48px; + height: 48px; + border-radius: 24px +} + +.fm-feature-select-person .select-person--item .fm-avatar-with-state .fm-avatar-with-state--icon { + right: 0; + top: 0; + cursor: pointer +} + +.fm-feature-select-person .select-person--item .fm-avatar-with-state .fm-avatar-with-state--icon::before { + content: "\e016" +} + +.fm-feature-select-person .select-person--item .fm-avatar-with-state .fm-avatar-with-state--icon:hover { + background: #F24645; + color: #fff +} + +.fm-feature-select-person .select-person--item .fm-round-bg { + width: 48px; + height: 48px; + border-radius: 24px; + line-height: 48px +} + +.fm-feature-select-person .select-person--icon { + margin: 0 0 0 3px; + color: #A6A6A6 +} + +.fm-feature-select-person .select-person--icon::before { + content: "→" +} + +.fm-tmpl-search-container { + position: relative; + padding: 7px 16px; + display: flex; + flex-direction: row; + align-items: center; + background: #fff +} + +.fm-tmpl-search-container .fm-tmpl-search-type { + flex-shrink: 0; + margin: 0 10px 0 0 +} + +.fm-tmpl-search-container .fm-tmpl-search-type.fm-state-active { + color: #3A90FF +} + +.fm-tmpl-search-container .fm-tmpl-search-inner { + flex: 1 1 0 +} + +.fm-tmpl-search-container .fm-tmpl-search-inner .van-search { + padding: 0 +} + +.fm-tmpl-search-container .fm-tmpl-search-tree-select { + position: absolute; + left: 0; + right: 0; + top: 100%; + z-index: 10 +} + +.fm-page-listview { + display: flex; + flex-direction: column +} + +.fm-page-listview .fm-page-main { + padding-bottom: 0; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-extend, +.fm-page-listview .fm-page-main .fm-tmpl-search-container { + flex-shrink: 0 +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container { + display: flex; + flex-direction: column; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-list-footer { + display: flex; + flex-direction: row; + align-items: center; + height: 54px; + padding: 0 16px; + background: #fff; + box-shadow: 0 -2px 8px 0 rgba(81, 120, 159, .12) +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-list-footer .fm-tmpl-list-footer-btn { + flex: 1; + text-align: center +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-search-tree-overlay { + position: absolute; + left: 0; + bottom: 0; + right: 0; + top: 0; + z-index: 9; + background-color: rgba(0, 0, 0, .4) +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-add-btn { + position: absolute; + right: 16px; + bottom: 50px +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-add-btn-inner { + width: 48px; + height: 48px; + text-align: center; + line-height: 48px; + border-radius: 50%; + background-image: linear-gradient(-45deg, #65A7FF 0, #3A90FF 100%); + box-shadow: 0 2px 5px 0 rgba(124, 163, 254, .57) +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-tmpl-add-btn-inner .fm-icon { + color: #fff; + font-size: 16px +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .van-pull-refresh { + display: flex; + flex-direction: column; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .van-pull-refresh .van-pull-refresh__track { + display: flex; + flex-direction: column; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0 +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-container .fm-listview-wrapper .van-pull-refresh { + overflow: inherit +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-add .fm-tmpl-add-btn { + bottom: 16px +} + +.fm-page-listview .fm-page-main .fm-tmpl-list-add .fm-listview-container.fm-listview-container-fill .fm-listview-main { + padding-bottom: 70px +} + +.fm-page-listview .fm-page-main .fm-tmpl-tabs { + flex: 1; + display: flex; + flex-direction: column +} + +.fm-page-listview .fm-page-main .fm-tmpl-tabs .fm-tab-bar, +.fm-page-listview .fm-page-main .fm-tmpl-tabs .van-tabs__wrap { + flex-shrink: 0 +} + +.fm-page-listview .fm-page-main .fm-tmpl-tabs .fm-tabs-content, +.fm-page-listview .fm-page-main .fm-tmpl-tabs .fm-tabs-content .fm-tab-pane, +.fm-page-listview .fm-page-main .fm-tmpl-tabs .van-tabs__content { + display: flex; + flex-direction: column; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-page-listview .fm-page-main .fm-tmpl-tabs .van-tabs__content .van-tab__pane { + display: flex; + flex-direction: column; + flex: 1 +} + +.fm-page-listview .fm-page-main .fm-tmpl-tabs .fm-tmpl-tabs-content { + display: flex; + flex-direction: column; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-page-card .fm-page-footer, +.fm-tmpl-list-extend { + flex-shrink: 0 +} + +.fm-btn-link { + color: #3A90FF +} + +.fm-page-card { + display: flex; + flex-direction: column +} + +.fm-page-card .fm-page-main { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: auto +} + +.fm-page-card .fm-page-main .fm-page-card-btns { + padding: 30px 16px 0 +} + +.fm-tmpl-struct-wrapper { + flex-shrink: 0; + margin-top: 12px +} + +.fm-tmpl-section-header, +.fm-tmpl-section-header .fm-toolbar { + align-items: center; + display: flex +} + +.fm-tmpl-struct-wrapper .fm-tmpl-section { + margin-top: 12px +} + +.fm-tmpl-struct-wrapper .fm-tmpl-section:first-child { + margin-top: 0 +} + +.fm-tmpl-section { + background-color: #fff +} + +.fm-tmpl-section-header { + justify-content: space-between; + padding: 11px 16px 10px +} + +.fm-tmpl-section-header .fm-title { + position: relative; + padding-left: 16px +} + +.fm-tmpl-section-header .fm-title::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + width: 3px; + height: 14px; + margin: -7px 0 0; + background: #3A90FF +} + +.fm-tmpl-listview-product .tmpl-product-title-collect .collect-text, +.fm-tmpl-section-header .fm-toolbar-item-text { + margin-left: 4px +} + +.fm-tmpl-section-header .fm-title-text { + font-size: 15px; + line-height: 21px; + color: #333 +} + +.fm-tmpl-section-header .fm-toolbar-item { + display: flex; + align-items: center; + padding-left: 16px; + font-size: 15px; + color: #3A90FF +} + +.fm-tmpl-section-header .fm-toolbar-item-icon { + font-size: 16px +} + +.fm-tmpl-section-content { + padding: 0 16px +} + +.fm-tmpl-button-wrapper { + padding: 30px 16px 0; + flex-shrink: 0 +} + +.fm-tmpl-button-wrapper .fm-tmpl-btns { + display: flex; + align-items: center +} + +.fm-tmpl-button-wrapper .fm-tmpl-btns .fm-button { + flex: 1; + margin-right: 11px +} + +.fm-tmpl-button-wrapper .fm-tmpl-btns.fm-button:last-child { + margin-right: 0 +} + +.fm-tmpl-section-btn { + display: flex; + flex-direction: row; + align-items: center; + padding: 0 16px; + border-top: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-section-btn { + border-top: none + } + + html:not([data-scale]) .fm-tmpl-section-btn::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } +} + +.fm-tmpl-section-btn .fm-button { + flex: 1; + position: relative +} + +.fm-tmpl-section-btn .fm-button::after { + position: absolute; + right: 0; + top: 50%; + width: 1px; + height: 16px; + margin-top: -8px; + background: #ddd; + transform: scaleX(.5); + content: '' +} + +.fm-tmpl-section-btn .fm-button:last-child::after { + display: none +} + +.fm-card-tmpl-header { + height: 36px; + line-height: 36px; + background-color: #f9f9fb; + padding-left: 16px +} + +.fm-edit-input-list { + position: relative +} + +.fm-banner-warpper { + position: relative; + background: url(imgs/questionnaire-header.png) center/cover no-repeat; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + flex-shrink: 0 +} + +.fm-banner-warpper .fm-banner-title, +.fm-banner-warpper .fm-banner-title-sub { + color: #fff; + text-shadow: 0 2px 8px rgba(0, 26, 123, .52) +} + +.fm-banner-warpper .fm-banner-title { + font-size: 24px; + line-height: 33px +} + +.fm-banner-warpper .fm-banner-title-sub { + font-size: 12px; + line-height: 17px; + padding-top: 4px +} + +@media screen and (max-width:375px) { + .fm-banner-warpper { + height: 98px + } +} + +@media screen and (min-width:375px) and (max-width:414px) { + .fm-banner-warpper { + height: 116px + } +} + +@media screen and (min-width:414px) { + .fm-banner-warpper { + height: 128px + } +} + +.fm-stamp-wrapper { + width: 68px; + height: 68px; + position: absolute; + right: 16px; + top: 12px; + background: url(imgs/questionnaire-submitted.png) center/contain no-repeat; + z-index: 9 +} + +.fm-card-uploader-content { + padding: 10px 16px +} + +.fm-page-header-staff { + background: linear-gradient(90deg, #2899F6 0, #3E76F9 50%, #4384F8 100%) +} + +.fm-page-header-staff .fm-navbar { + background: 0 0 +} + +.fm-page-header-staff .fm-navbar .fm-navbar-left-arrow, +.fm-page-header-staff .fm-navbar .fm-navbar-title { + color: #fff +} + +.fm-navbar-right-text { + color: #333; + font-size: 16px +} + +.fm-input-wrapper:not(:last-child) .van-cell::after { + display: block +} + +.fm-inner-cell .van-checkbox__label::after, +.fm-inner-cell .van-radio__label::after, +.fm-input-wrapper:last-child .van-cell::after { + display: none +} + +.fm-radio-readonly .fm-inner-cell .van-radio .van-radio__icon .van-icon { + background-color: #fff +} + +.fm-radio-readonly .fm-inner-cell .van-radio .van-radio__icon--checked .van-icon { + background-color: #1989fa; + border-color: #1989fa +} + +.fm-form-item-wrapper { + position: relative; +} + +html:not([data-scale]) .fm-input-wrapper:not(:last-child) .fm-cell:not(.fm-no-hairline)::after, +html:not([data-scale]) .fm-form-item-wrapper:not(:last-child):not(.fm-no-hairline)::after, +html:not([data-scale]) .fm-form-designer-item-wrapper:not(:last-child) .fm-form-item-wrapper:not(.fm-no-hairline)::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + transform-origin: 50% 100%; +} + +.fm-input-wrapper:not(:last-child) .fm-cell::after, +.fm-form-item-wrapper:not(:last-child)::after, +.fm-form-designer-item-wrapper:not(:last-child) .fm-form-item-wrapper::after { + left: 16px !important; +} + +.fm-input-label-tips { + display: flex; + align-items: center; + padding-left: 4px +} + +.fm-input-label-tips-content { + font-size: 14px; + color: #333; + line-height: 20px; + padding: 6px 16px +} + +.fm-tmpl-listview-timeline { + margin-left: 5px +} + +.fm-tmpl-listview-timeline .fm-tmpl-timeline-text { + position: relative; + padding-left: 22px; + padding-bottom: 2px; + line-height: 20px; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-timeline .fm-tmpl-timeline-text::after { + position: absolute; + left: -5px; + top: 5px; + width: 10px; + height: 10px; + background-color: #ddd; + border-radius: 50%; + content: '' +} + +.fm-tmpl-listview-timeline .fm-tmpl-timeline-text::before { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 1px; + background-color: #ddd; + content: '' +} + +.fm-tmpl-listview-timeline .fm-tmpl-timeline-date { + padding-bottom: 20px; + padding-left: 22px; + font-size: 12px; + color: #999; + border-left: 1px solid #ddd +} + +.fm-tmpl-listview-timeline.fm-tmpl-listview-timeline-first .fm-tmpl-timeline-text:before { + top: 5px +} + +.fm-tmpl-listview-timeline.fm-tmpl-listview-timeline-last .fm-tmpl-timeline-text:before { + height: 5px +} + +.fm-tmpl-listview-timeline.fm-tmpl-listview-timeline-last .fm-tmpl-timeline-date { + border-color: transparent +} + +.fm-tmpl-listview-goods { + padding-left: 16px; + display: flex; + padding-top: 10px +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-img { + flex-shrink: 0; + width: 86px; + height: 86px; + margin-right: 10px; + overflow: hidden +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-img img { + display: block; + width: 86px; + height: 86px +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden; + padding-right: 16px; + padding-bottom: 10px; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-input-wrapper:not(:last-child) .fm-cell:not(.fm-no-hairline)::after { + transform: scaleY(.5) + } + + html:not([data-scale]) .fm-tmpl-listview-goods .fm-tmpl-goods-content { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-goods .fm-tmpl-goods-content::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-name { + position: relative; + min-height: 40px; + padding-right: 28px; + margin-bottom: 4px; + line-height: 20px; + font-size: 16px; + color: #666 +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-name .fm-tmpl-goods-add { + position: absolute; + right: 0; + top: 30px; + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; + background-color: #ececec; + border-radius: 50% +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-name .fm-tmpl-goods-add .fm-icon { + font-size: 12px; + color: #999 +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-price { + display: flex; + align-items: flex-end; + line-height: 22px; + margin-bottom: 3px; + color: #fa6400 +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-price-prefix { + font-size: 12px +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-price-text { + font-size: 16px +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-shop { + display: flex; + align-items: center; + line-height: 16px; + font-size: 12px; + color: #888 +} + +.fm-tmpl-listview-goods .fm-tmpl-goods-content .fm-tmpl-goods-shop .fm-icon { + margin-right: 3px; + font-size: 12px +} + +.fm-tmpl-listview-order { + padding-left: 16px +} + +.fm-tmpl-listview-order-inner { + padding: 12px 16px 12px 0; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-order-inner { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-order-inner::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-name { + margin-bottom: 3px; + line-height: 21px; + font-size: 15px; + color: #333 +} + +.fm-tmpl-listview-order .order-line-item { + display: flex; + flex-direction: row; + align-items: center +} + +.fm-tmpl-listview-order .order-line-item-left { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-tmpl-listview-order .order-line-item-right { + flex-shrink: 0 +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-number { + line-height: 20px; + margin-bottom: 10px +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-number .order-number-text { + font-size: 14px; + color: #888 +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-msg { + line-height: 18px; + font-size: 13px +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-msg .order-msg-date { + color: #888 +} + +.fm-tmpl-listview-order .fm-tmpl-listview-order-msg .order-msg-price { + color: #ff7300 +} + +.fm-tmpl-listview-shop { + padding: 0 8px 10px; + background: #f9fafb +} + +.fm-tmpl-listview-shop-inner { + background: #fff +} + +.fm-tmpl-listview-shop-header { + padding: 10px 10px 18px; + display: flex; + flex-direction: row +} + +.fm-tmpl-listview-shop-header .shop-header-img { + flex-shrink: 0; + width: 46px; + height: 46px; + margin-right: 10px +} + +.fm-tmpl-listview-shop-header .shop-header-img img { + display: block; + width: 100%; + height: 100% +} + +.fm-tmpl-listview-shop-header .shop-header-msg { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-tmpl-listview-shop-header .shop-header-msg .shop-header-name { + display: flex; + justify-content: space-between; + margin-bottom: 6px +} + +.fm-tmpl-listview-shop-header .shop-header-msg .shop-header-name-text { + padding-right: 6px; + line-height: 22px; + font-size: 16px; + color: #333 +} + +.fm-tmpl-listview-shop .shop-content-item, +.fm-tmpl-listview-shop-header .shop-header-msg .shop-header-site { + line-height: 18px; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-shop-header .shop-header-msg .shop-header-name-status { + flex-shrink: 0 +} + +.fm-tmpl-listview-shop .shop-content-item { + margin-bottom: 8px; + padding: 0 10px +} + +.fm-tmpl-listview-shop-footer { + border-top: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-shop-footer { + border-top: none + } + + html:not([data-scale]) .fm-tmpl-listview-shop-footer::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } + + .fm-tmpl-listview-shop-footer .shop-footer-btns .shop-footer-btn-item::after { + transform: scaleX(.5) + } +} + +.fm-tmpl-listview-shop-footer .shop-footer-btns { + display: flex; + flex-direction: row; + align-items: center +} + +.fm-tmpl-listview-shop-footer .shop-footer-btns .shop-footer-btn-item { + position: relative; + flex: 1; + height: 44px; + padding: 0 6px; + line-height: 44px; + font-size: 12px; + color: #999; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.fm-tmpl-listview-shop-footer .shop-footer-btns .shop-footer-btn-item .fm-icon { + font-size: 14px; + margin-right: 4px +} + +.fm-tmpl-listview-shop-footer .shop-footer-btns .shop-footer-btn-item::after { + position: absolute; + right: 0; + top: 50%; + width: 1px; + height: 22px; + margin-top: -11px; + background-color: #ddd; + content: '' +} + +.fm-tmpl-listview-shop-footer .shop-footer-btns .shop-footer-btn-item:last-child::after { + display: none +} + +.fm-tmpl-listview-shop-first { + padding-top: 10px +} + +.fm-tmpl-listview-menu { + padding-bottom: 10px; + background: #f9fafb +} + +.fm-tmpl-listview-menu-inner { + padding: 10px 16px 0; + background-color: #fff +} + +.fm-tmpl-listview-menu-text { + margin-bottom: 10px; + line-height: 20px; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-menu-content .menu-list { + display: flex; + align-items: center; + flex-wrap: wrap +} + +.fm-tmpl-listview-menu-content .menu-list-item { + flex: 0 0 25%; + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 10px +} + +.fm-tmpl-listview-menu-content .menu-list-item-icon { + width: 46px; + height: 46px; + margin-bottom: 6px; + line-height: 46px; + text-align: center; + color: #fff; + border-radius: 16px; + background-color: #40a9ff +} + +.fm-tmpl-listview-menu-content .menu-list-item-icon .fm-icon { + font-size: 26px +} + +.fm-tmpl-listview-menu-content .menu-list-item-text { + line-height: 20px; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-menu-last { + padding-bottom: 0 +} + +.fm-tmpl-listview-menus.fm-listview-content { + display: flex; + align-items: center; + flex-wrap: wrap +} + +.fm-tmpl-listview-menus .fm-listview-item { + flex: 0 0 33.3333% +} + +.fm-tmpl-listview-menus-item { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 16px +} + +.fm-tmpl-listview-menus-item .menu-list-item-icon { + width: 46px; + height: 46px; + margin-bottom: 6px; + line-height: 46px; + text-align: center; + color: #fff; + border-radius: 16px; + background-color: #40a9ff +} + +.fm-tmpl-listview-menus-item .menu-list-item-icon .fm-icon { + font-size: 26px +} + +.fm-tmpl-listview-menus-item .menu-list-item-text { + line-height: 20px; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-basic { + display: flex; + align-items: flex-start; + padding: 0 16px; + margin-bottom: 8px; + font-size: 14px; + line-height: 20px +} + +.fm-tmpl-listview-basic .basic-lable { + flex-shrink: 0; + width: 82px; + margin-right: 14px; + color: #999; + text-align: right +} + +.fm-tmpl-listview-basic .basic-text { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden; + color: #333 +} + +.fm-tmpl-listview-basic-last { + margin-bottom: 0 +} + +.fm-tmpl-listview-list { + padding-left: 16px +} + +.fm-tmpl-listview-list .fm-tmpl-listview-list-inner { + display: flex; + justify-content: space-between; + height: 44px; + padding-right: 16px; + font-size: 15px; + color: #333; + line-height: 44px; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-list .fm-tmpl-listview-list-inner { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-list .fm-tmpl-listview-list-inner::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-list .fm-tmpl-listview-list-inner .list-text { + color: #FBB902 +} + +.fm-tmpl-listview-list-last .fm-tmpl-listview-list-inner { + border-bottom: 0 +} + +.fm-tmpl-listview-list-last .fm-tmpl-listview-list-inner::after { + display: none !important +} + +.fm-tmpl-listview-sign { + padding: 0 16px; + background: #fff +} + +.fm-tmpl-listview-sign .fm-tmpl-listview-sign-inner { + margin-left: 12px +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-text { + position: relative; + padding-left: 18px +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-text .fm-tmpl-sign-circle { + position: absolute; + left: -8px; + top: 2px; + width: 18px; + height: 18px; + border-radius: 50%; + background-color: rgba(54, 165, 246, .2) +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-text .text { + line-height: 22px; + font-size: 16px; + color: #333; + font-weight: 600 +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-text::after { + position: absolute; + left: -5px; + top: 5px; + width: 6px; + height: 6px; + border: 3px solid #fff; + background-color: #36a5f6; + border-radius: 50%; + content: ''; + box-sizing: content-box +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-text::before { + position: absolute; + left: -.5px; + top: 0; + bottom: 0; + width: 1px; + border: 1px dashed #ddd; + background-color: transparent; + content: ''; + transform: scaleX(.5) +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content { + padding: 10px 0 10px 18px; + border-left: 1px dashed #ddd +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-inner { + padding: 10px 12px; + background: #f4f7f9 +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-name { + display: flex; + align-items: center; + padding-bottom: 6px; + line-height: 20px +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-name .fm-icon { + margin-right: 6px; + font-size: 16px; + color: #36a5f6 +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-name .name-text { + font-size: 15px; + color: #333 +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-label { + padding-bottom: 10px; + font-size: 14px; + color: #999 +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-imgs { + display: flex; + align-items: center; + flex-wrap: wrap +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-imgs .fm-tmpl-sign-content-img { + width: 60px; + height: 60px; + margin-right: 10px; + margin-bottom: 10px; + overflow: hidden +} + +.fm-tmpl-listview-sign .fm-tmpl-sign-content-imgs .fm-tmpl-sign-content-img img { + display: block; + width: 100%; + height: 100%; + -o-object-fit: scale-down; + object-fit: scale-down +} + +.fm-tmpl-listview-sign.fm-tmpl-listview-sign-last { + padding-bottom: 12px +} + +.fm-tmpl-listview-sign.fm-tmpl-listview-sign-last .fm-tmpl-sign-content { + border-left: none +} + +.fm-tmpl-listview-sign.fm-tmpl-listview-sign-last .fm-tmpl-sign-text::before { + height: 6px +} + +.fm-tmpl-listview-sign.fm-tmpl-listview-sign-first { + padding-top: 12px +} + +.fm-tmpl-listview-sign.fm-tmpl-listview-sign-first .fm-tmpl-sign-text::before { + top: 6px +} + +.fm-tmpl-listview-bill { + padding-left: 12px +} + +.fm-tmpl-listview-bill-content { + display: flex +} + +.fm-tmpl-listview-bill-content .bill-img-round-wrapper { + padding-top: 12px; + margin-right: 10px +} + +.fm-tmpl-listview-bill-content .bill-img-round-wrapper .bill-img-round-img { + width: 30px; + height: 30px; + border-radius: 50%; + text-align: center; + color: #fff; + background: #3a90ff +} + +.fm-tmpl-listview-bill-content .bill-img-round-wrapper .bill-img-round-img .fm-icon { + font-size: 18px; + line-height: 30px +} + +.fm-tmpl-listview-bill-content .bill-detail-content { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + padding: 12px 16px 8px 0; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-bill-content .bill-detail-content { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-bill-content .bill-detail-content::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-header { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0 0 6px +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-header .title { + line-height: 22px; + font-weight: 400; + font-size: 16px; + color: #333 +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-header .time { + line-height: 18px; + color: #999; + font-size: 13px +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-info { + display: flex; + margin-bottom: 4px +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-info-text { + display: flex; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + align-items: flex-start; + line-height: 18px; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-info-text .title { + flex-shrink: 0 +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-info-text .text-orange { + color: #FF9800 +} + +.fm-tmpl-listview-bill-content .bill-detail-content .bill-detail-info-status { + padding-left: 6px; + margin-top: -2px +} + +.fm-tmpl-listview-client { + padding: 0 8px 10px; + background: #f9fafb +} + +.fm-tmpl-listview-client-inner { + background: #fff +} + +.fm-tmpl-listview-client-header { + padding: 10px 10px 18px; + display: flex; + flex-direction: row +} + +.fm-tmpl-listview-client-header .client-header-icon { + flex-shrink: 0; + width: 46px; + height: 46px; + line-height: 46px; + margin-right: 10px; + text-align: center; + background-color: #3a90ff; + border-radius: 6px +} + +.fm-tmpl-listview-client-header .client-header-icon .fm-icon { + font-size: 24px; + color: #fff +} + +.fm-tmpl-listview-client-header .client-header-msg { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + overflow: hidden +} + +.fm-tmpl-listview-client-header .client-header-msg .client-header-name { + display: flex; + justify-content: space-between; + margin-bottom: 6px +} + +.fm-tmpl-listview-client-header .client-header-msg .client-header-name-status, +.fm-tmpl-listview-liaison .liaison-header-tag { + flex-shrink: 0 +} + +.fm-tmpl-listview-client-header .client-header-msg .client-header-name-text { + padding-right: 6px; + line-height: 22px; + font-size: 16px; + color: #333 +} + +.fm-tmpl-listview-client-header .client-header-msg .client-header-name-time { + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-client-header .client-header-msg .client-header-site { + line-height: 18px; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-client-content .client-content-info { + display: flex; + align-items: center +} + +.fm-tmpl-listview-client-content .text-orange { + font-size: 14px; + color: #FF9800 +} + +.fm-tmpl-listview-client .client-content-item { + display: flex; + align-items: center; + flex: 1; + margin-bottom: 8px; + padding: 0 10px; + line-height: 18px; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-client .client-content-item .fm-icon { + font-size: 14px; + margin-right: 2px +} + +.fm-tmpl-listview-client-first { + padding-top: 10px +} + +.fm-tmpl-listview-client.fm-tmpl-listview-client-simple .fm-tmpl-listview-client-header { + padding-bottom: 10px +} + +.fm-tmpl-listview-client.fm-tmpl-listview-client-simple .fm-tmpl-listview-client-header .client-header-msg .client-header-name { + margin-bottom: 0 +} + +.fm-tmpl-listview-client .text-success { + color: #5CC171 +} + +.fm-tmpl-listview-client .text-warning { + color: #FF9800 +} + +.fm-tmpl-listview-client .text-danger { + color: #F24645 +} + +.fm-tmpl-listview-client .text-submit { + color: #5AC1C3 +} + +.fm-tmpl-listview-client .text-info { + color: #4D9AFF +} + +.fm-tmpl-extend-card { + padding: 12px 16px +} + +.fm-tmpl-extend-card-inner { + position: relative; + background-image: linear-gradient(152deg, #53bdfd 0, #287cf3 97%); + box-shadow: 0 2px 4px 0 rgba(57, 66, 100, .04); + border-radius: 10px; + overflow: hidden +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list .fm-tmpl-extend-card-item { + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + color: #fff +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list .fm-tmpl-extend-card-item .extend-card-item-text { + display: flex; + align-items: baseline +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list .fm-tmpl-extend-card-item .extend-card-item-text .item-text { + display: block; + font-size: 24px; + line-height: 32px +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list .fm-tmpl-extend-card-item .extend-card-item-text .item-text-tip { + font-size: 12px +} + +.fm-tmpl-extend-card-inner .fm-tmpl-extend-card-list .fm-tmpl-extend-card-item .extend-card-item-text .card-item-title { + font-size: 14px +} + +.fm-tmpl-extend-card-inner::before { + right: -7%; + top: 20%; + width: 80%; + height: 340%; + border-radius: 50%; + opacity: .23; + background-image: linear-gradient(180deg, #63ccfa 0, #36a5f6 100%); + z-index: 1 +} + +.fm-tmpl-extend-card-inner::after { + right: -37%; + bottom: -10%; + width: 60%; + height: 240%; + border-radius: 50%; + opacity: .15; + background-image: linear-gradient(134deg, #3addd5 0, #24c2d8 100%); + z-index: 0 +} + +.fm-tmpl-listview-liaison { + padding-left: 16px; + margin-top: 10px; + background-color: #fff +} + +.fm-tmpl-listview-liaison .liaison-header { + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 12px 16px 12px 0; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-liaison .liaison-header { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-liaison .liaison-header::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-liaison .liaison-header-title { + flex: 1 1 0; + padding-right: 16px; + font-size: 16px; + color: #333; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis +} + +.fm-tmpl-listview-liaison .liaison-content { + padding: 10px 0 +} + +.fm-tmpl-listview-liaison .liaison-content-info { + display: flex; + flex-direction: row; + align-items: center; + line-height: 18px; + color: #999; + font-size: 13px; + margin: 0 0 6px +} + +.fm-tmpl-listview-booklist .booklist-btns .fm-button, +.fm-tmpl-listview-liaison .liaison-actions .fm-button { + margin-left: 13px +} + +.fm-tmpl-listview-liaison .liaison-content-info-title { + flex-shrink: 0; + width: 100px; + padding-right: 10px +} + +.fm-tmpl-listview-liaison .liaison-content-info-text { + flex: 1 1 0; + color: #333 +} + +.fm-tmpl-listview-liaison .liaison-actions { + padding: 0 16px 10px; + text-align: right +} + +.fm-tmpl-listview-liaison .liaison-actions .fm-button:first-child { + margin-left: 0 +} + +.fm-tmpl-listview-approve { + padding: 10px 0 10px 16px; + background-color: #fff +} + +.fm-tmpl-listview-approve .fm-approve-flow-item { + padding-left: 7px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header { + border-left: 1px dashed #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-approve .fm-approve-flow-item-header { + border-left: none + } + + html:not([data-scale]) .fm-tmpl-listview-approve .fm-approve-flow-item-header::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 1PX; + height: 100%; + transform-origin: 100% 50%; + transform: scaleX(.5) + } +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 20px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon { + position: absolute; + left: -7px; + top: 0; + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + width: 15px; + height: 15px; + background-color: rgba(58, 144, 255, .4); + border-radius: 50% +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon-inner { + width: 7px; + height: 7px; + background-color: #3a90ff; + border-radius: 50% +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-content { + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0; + line-height: 21px; + font-size: 15px; + color: #4c4c4c; + font-weight: 700 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-right { + flex-shrink: 0; + padding-left: 6px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-right .fm-icon { + color: #979797 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content { + padding: 12px 0 30px 20px; + border-left: 1px dashed #d4d4d4; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-approve .fm-approve-flow-item-content { + border-left: none + } + + html:not([data-scale]) .fm-tmpl-listview-approve .fm-approve-flow-item-content::before { + content: ''; + position: absolute; + background-color: #d4d4d4; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 1PX; + height: 100%; + transform-origin: 100% 50%; + transform: scaleX(.5) + } +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list { + display: flex; + flex-direction: row; + align-items: flex-start; + margin-bottom: 14px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list:last-child { + margin-bottom: 0 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-avatar { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + width: 36px; + height: 36px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-avatar-img { + display: block; + width: 36px; + height: 36px; + border-radius: 50% +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content { + flex: 1 1 0; + margin-left: 10px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-main { + display: flex; + align-items: center; + justify-content: space-between; + height: 36px +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-last .fm-approve-flow-item-content::before, +.fm-tmpl-listview-approve .fm-approve-flow-item-last .fm-approve-flow-item-header::before { + display: none !important +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left, +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left .item-list-content-name { + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left .item-list-content-status { + margin-left: 8px; + color: #3a90ff +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left .item-list-content-status-success { + color: #5cc171 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left .item-list-content-status-apply { + color: #3a90ff +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-left .item-list-content-status-running { + color: #ff9800 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-date { + flex-shrink: 0; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-list-content .item-list-content-message { + line-height: 20px; + font-size: 14px; + color: #333 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-content .fm-approve-flow-item-date { + font-size: 13px; + color: rgba(51, 51, 51, .65) +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-running .fm-approve-flow-item .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon { + background-color: rgba(255, 152, 0, .4) +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-running .fm-approve-flow-item .fm-approve-flow-item-header-inner .fm-approve-flow-item-header-icon .fm-approve-flow-item-header-icon-inner { + background-color: #ff9800 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-last .fm-approve-flow-item-header { + border-left: 0 +} + +.fm-tmpl-listview-approve .fm-approve-flow-item-last .fm-approve-flow-item-content { + padding-bottom: 12px; + border-left: 0 +} + +.fm-tmpl-listview-product-header { + padding: 12px 14px; + line-height: 20px; + font-size: 14px; + color: #3a90ff +} + +.fm-tmpl-listview-product-item .fm-listview-item .fm-listview-item-content { + transform: none +} + +.fm-tmpl-listview-product { + padding: 12px 16px 0 +} + +.fm-tmpl-listview-product .fm-tmpl-listview-product-inner { + padding-bottom: 12px; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-product .fm-tmpl-listview-product-inner { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-product .fm-tmpl-listview-product-inner::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-product .tmpl-product-title { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px +} + +.fm-tmpl-listview-product .tmpl-product-title .tmpl-product-title-collect { + flex-shrink: 0 +} + +.fm-tmpl-listview-product .tmpl-product-title-text { + font-size: 17px; + color: #333 +} + +.fm-tmpl-listview-product .tmpl-product-title-collect { + flex-shrink: 0; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-product .tmpl-product-title-collect.tmpl-product-title-collected .fm-icon { + color: #ff9800 +} + +.fm-tmpl-listview-product .tmpl-product-content { + position: relative; + padding-right: 40px +} + +.fm-tmpl-listview-product .tmpl-product-content-item { + display: flex; + align-items: center; + margin-bottom: 10px; + font-size: 14px; + color: #666 +} + +.fm-tmpl-listview-product .tmpl-product-content .tmpl-product-add-btn { + position: absolute; + right: 0; + bottom: 0 +} + +.fm-tmpl-listview-product .tmpl-product-content .tmpl-product-add-btn .fm-button-add { + width: 30px; + height: 30px +} + +.fm-tmpl-listview-product .tmpl-product-content .tmpl-product-add-btn .fm-button-add .fm-icon { + font-size: 14px +} + +.fm-tmpl-listview-product .tmpl-product-footer { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 6px +} + +.fm-tmpl-listview-product .tmpl-product-footer .tmpl-product-price { + margin-right: 10px; + font-size: 17px; + color: red; + font-weight: 600 +} + +.fm-tmpl-listview-product .tmpl-product-footer .fm-popover .fm-popover-inner { + border-radius: 10px; + box-shadow: none +} + +.fm-tmpl-listview-product .tmpl-product-footer .fm-popover .fm-popover-arrow, +.fm-tmpl-listview-product .tmpl-product-footer .fm-popover .fm-popover-inner { + border: 1px solid #ddd +} + +.fm-tmpl-listview-product .tmpl-product-footer .fm-popover .fm-popover-inner-wrapper { + padding: 0 +} + +.fm-tmpl-listview-product .tmpl-product-footer .fm-popover .fm-popover-inner-wrapper .fm-popover-item { + min-width: 50px; + height: 46px; + line-height: 46px; + text-align: center; + font-size: 16px; + color: #666 +} + +.fm-tmpl-listview-product .tmpl-product-footer .fm-overlay { + background: 0 0 +} + +.fm-tmpl-listview-product .tmpl-product-footer .tmpl-product-unit { + padding: 3px 6px; + border-radius: 6px; + background-color: rgba(58, 144, 255, .2); + font-size: 14px; + color: #333 +} + +.fm-tmpl-listview-product .tmpl-product-footer .tmpl-product-unit-text { + margin-right: 4px +} + +.fm-tmpl-listview-product .tmpl-product-footer .tmpl-product-unit .fm-icon { + font-size: 12px; + color: #666 +} + +.fm-tmpl-listview-product .tmpl-product-footer .tmpl-product-footer-right { + flex-shrink: 0; + font-size: 12px; + color: #666 +} + +.fm-tmpl-listview-product.fm-tmpl-listview-product-first { + padding-top: 0 +} + +.fm-card-tmpl-booklist-header { + padding: 11px 16px; + line-height: 22px; + font-size: 16px; + color: #333; + font-weight: 600 +} + +.fm-tmpl-listview-booklist { + padding: 0 16px; + color: #333; + border-bottom: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-booklist { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-booklist::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-booklist-last { + border-bottom: 0 +} + +.fm-tmpl-listview-booklist-last::after { + display: none !important +} + +.fm-tmpl-listview-booklist .booklist-header { + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + padding: 12px 0 6px; + line-height: 22px; + font-size: 16px +} + +.fm-tmpl-listview-booklist .booklist-header-price { + flex-shrink: 0; + color: #fa6400 +} + +.fm-tmpl-listview-booklist .booklist-main { + padding-bottom: 8px +} + +.fm-tmpl-listview-booklist .booklist-main-item { + line-height: 18px; + padding-bottom: 4px; + font-size: 13px; + color: #999 +} + +.fm-tmpl-listview-booklist .booklist-btns { + padding: 8px 0 6px; + text-align: right +} + +.fm-tmpl-dialog-plan, +.fm-tmpl-dialog-type { + border-radius: 5px !important +} + +.fm-tmpl-dialog-plan .fm-dialog-footer, +.fm-tmpl-dialog-type .fm-dialog-footer { + border-top: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + + html:not([data-scale]) .fm-tmpl-dialog-plan .fm-dialog-footer, + html:not([data-scale]) .fm-tmpl-dialog-type .fm-dialog-footer { + border-top: none + } + + html:not([data-scale]) .fm-tmpl-dialog-plan .fm-dialog-footer::before, + html:not([data-scale]) .fm-tmpl-dialog-type .fm-dialog-footer::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } +} + +.fm-tmpl-dialog-plan .fm-dialog-footer .fm-button, +.fm-tmpl-dialog-type .fm-dialog-footer .fm-button { + font-size: 14px; + color: #666 +} + +.fm-tmpl-dialog-type-content { + padding: 20px +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list { + display: flex; + align-items: center; + justify-content: center +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item { + flex: 1 +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item .type-list-item-icon { + width: 60px; + height: 60px; + margin: 0 auto; + line-height: 60px; + text-align: center; + border: 1px solid #3D91FF; + border-radius: 50% +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-dialog-type-content .fm-dialog-type-list-item .type-list-item-icon { + position: relative; + border: none + } + + html:not([data-scale]) .fm-tmpl-dialog-type-content .fm-dialog-type-list-item .type-list-item-icon::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 200%; + height: 200%; + border: 1px solid #3D91FF; + border-radius: 100%; + transform-origin: 0 0; + transform: scale(.5); + box-sizing: border-box; + pointer-events: none + } +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item .type-list-item-icon .fm-icon { + font-size: 26px; + color: #3D91FF +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item .type-list-item-text { + margin-top: 12px; + font-size: 16px; + text-align: center; + color: #666 +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item:active .type-list-item-icon { + background-color: #3D91FF +} + +.fm-tmpl-dialog-type-content .fm-dialog-type-list-item:active .type-list-item-icon .fm-icon { + color: #fff +} + +.fm-tmpl-dialog-plan-content { + padding: 20px 30px +} + +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item { + display: flex; + justify-content: center; + height: 40px; + line-height: 40px; + margin-bottom: 16px; + align-items: center; + color: #666; + border: 1px solid #ddd; + border-radius: 4px +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-dialog-plan-content .fm-dialog-plan-item { + position: relative; + border: none + } + + html:not([data-scale]) .fm-tmpl-dialog-plan-content .fm-dialog-plan-item::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 200%; + height: 200%; + border: 1px solid #ddd; + border-radius: 8px; + transform-origin: 0 0; + transform: scale(.5); + box-sizing: border-box; + pointer-events: none + } +} + +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item .plan-item-icon { + margin-right: 14px +} + +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item .fm-icon { + color: #666 +} + +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item:active, +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item:active .fm-icon { + color: #3D91FF +} + +.fm-tmpl-dialog-plan-content .fm-dialog-plan-item:active::before { + border-color: #3D91FF !important +} + +.fm-title { + position: relative; + padding-left: 16px +} + +.fm-title::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + width: 5px; + height: 16px; + margin: -8px 0 0; + background: #3A90FF +} + +.fm-title-text { + font-size: 16px; + line-height: 21px; + color: #333 +} + +.fm-tmpl-search-action { + position: relative +} + +.fm-tmpl-search-action .fm-icon { + font-size: 20px; + color: #666 +} + +.fm-tmpl-search-action-badge { + position: absolute; + top: 0; + right: 0; + min-width: 16px; + padding: 0 3px; + margin-top: 4px; + color: #fff; + font-weight: 500; + font-size: 12px; + line-height: 14px; + text-align: center; + background-color: #ee0a24; + border: 1px solid #fff; + border-radius: 16px; + transform: translate(50%, -50%); + transform-origin: 100% +} + +.fm-list-view-swipe-toolbar { + display: flex; + align-items: center; + justify-content: center; + padding: 0 12px; + height: 100%; + background-color: #f24645; + font-size: 16px; + color: #fff +} + +.fm-static-text-common { + padding: 12px 16px; + background-color: #fff; + margin-bottom: 10px; + font-size: 13px; + line-height: 1.42; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + text-align: left; + white-space: pre-wrap; + word-wrap: break-word +} + +.fm-static-text-common p { + margin-top: 0; + margin-bottom: 0; +} + +.fm-static-text-common p:not(:last-child) { + padding-bottom: 18px +} + +.fm-tmpl-listview-common { + font-size: 16px; + color: #333; + padding: 12px 16px 12px 0; + margin-left: 16px; + border-bottom: 1px solid #ddd; + position: relative +} + +.fm-tmpl-listview-common .fm-tmpl-row { + display: flex; + justify-content: space-between +} + +.fm-tmpl-listview-common .fm-tmpl-row:not(:last-child) { + padding-bottom: 8px +} + +.fm-tmpl-listview-common .fm-tmpl-col { + display: flex; + align-items: flex-start +} + +.fm-tmpl-listview-common .fm-tmpl-title { + line-height: 22px +} + +.fm-tmpl-listview-common .fm-tmpl-price { + font-size: 18px; + line-height: 22px; + color: #fa6400 +} + +.fm-tmpl-listview-common .fm-tmpl-label { + font-size: 14px; + line-height: 20px; + display: flex; + overflow: hidden +} + +.fm-tmpl-listview-common .fm-tmpl-label .fm-tmpl-label-title { + color: #999; + width: 92px +} + +.fm-tmpl-listview-common .fm-tmpl-label .fm-tmpl-label-text { + flex: 1; + overflow: hidden; + text-overflow: ellipsis +} + +.fm-tmpl-listview-common .fm-tmpl-col-1 { + flex: 1; + white-space: nowrap; + overflow: hidden +} + +.fm-tmpl-listview-common .fm-tmpl-col-1:not(:last-child) { + padding-right: 10px +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-common { + border-bottom: none + } + + html:not([data-scale]) .fm-tmpl-listview-common::after { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: auto; + right: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 100%; + transform: scaleY(.5) + } +} + +.fm-tmpl-listview-cell .fm-tmpl-row:not(:last-child) { + padding-bottom: 3px +} + +.fm-tmpl-listview-cell .fm-tmpl-label { + font-size: 13px; + line-height: 18px; + color: #999 +} + +.fm-tmpl-listview-cell .fm-tmpl-label .fm-tmpl-label-title { + width: auto +} + +.fm-tmpl-listview-card { + margin: 10px 12px 10px; + padding: 0; + border-radius: 8px; + background: #fff; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(81, 120, 159, .12) +} + +.fm-tmpl-listview-card .fm-tmpl-listview-content { + padding: 16px +} + +.fm-tmpl-listview-card .fm-tmpl-listview-content .fm-tmpl-label { + color: #666 +} + +.fm-tmpl-listview-card .fm-tmpl-listview-common-footer { + border-top: 1px solid #ddd; + position: relative +} + +@media (-webkit-min-device-pixel-ratio:2), +(min-resolution:2dppx) { + html:not([data-scale]) .fm-tmpl-listview-card .fm-tmpl-listview-common-footer { + border-top: none + } + + html:not([data-scale]) .fm-tmpl-listview-card .fm-tmpl-listview-common-footer::before { + content: ''; + position: absolute; + background-color: #ddd; + display: block; + z-index: 1; + top: 0; + right: auto; + bottom: auto; + left: 0; + width: 100%; + height: 1PX; + transform-origin: 50% 50%; + transform: scaleY(.5) + } +} + +.fm-listview-item:last-child .fm-tmpl-listview-card { + margin-bottom: 10px +} + +.fm-common-text { + display: inline; + color: #666; + word-break: break-all; +} + +.fm-common-label { + display: inline-block; + white-space: nowrap; +} + +.fm-common-content {} + +.fm-common-title { + display: inline; + color: #333; + word-break: break-all; + font-weight: 500; +} + + +.fm-title-sm { + font-size: 15px; + line-height: 22px; +} + +.fm-title-md { + font-size: 16px; + line-height: 24px; +} + +.fm-title-lg { + font-size: 17px; + line-height: 26px; +} + +.fm-title-xl { + font-size: 22px; + line-height: 32px; +} + +.fm-text-xs { + font-size: 12px; + line-height: 20px +} + +.fm-text-sm { + font-size: 13px; + line-height: 20px +} + +.fm-text-md { + font-size: 14px; + line-height: 22px +} + +.fm-text-lg { + font-size: 15px; + line-height: 22px +} + +.fm-text-xl { + font-size: 16px; + line-height: 24px +} + +.layout-bordered { + border-bottom: 1px solid #E6E6E6; +} + +.layout-bordered .layout-bordered { + border-bottom: none; +} + +.fm-listview-item:last-child .layout-bordered { + border-bottom: none; +} diff --git a/packages/designer/public/assets/farris-mobile-ui-vue.css b/packages/designer/public/assets/farris-mobile-ui-vue.css new file mode 100644 index 0000000000000000000000000000000000000000..7f49e0efccb747357c99f68d877353b1cd3aa25e --- /dev/null +++ b/packages/designer/public/assets/farris-mobile-ui-vue.css @@ -0,0 +1 @@ +@charset "UTF-8";:root{--fm-black: #000;--fm-white: #fff;--fm-gray-1: #f2f3f5;--fm-gray-2: #eee;--fm-gray-3: #ddd;--fm-gray-4: #ccc;--fm-gray-5: #999;--fm-gray-6: #666;--fm-gray-7: #333;--fm-red: #F24645;--fm-red-light: #f9e8e8;--fm-blue: #3A90FF;--fm-blue-2: #65a7ff;--fm-blue-light: #ecf2fe;--fm-green: #5CC171;--fm-green-2: #5AC1C3;--fm-green-light: #e9f5ed;--fm-orange: #FF9800;--fm-orange-2: #FA6400;--fm-orange-3: #FFB400;--fm-orange-light: #faf0e1;--fm-primary-color: var(--fm-blue);--fm-success-color: var(--fm-green);--fm-danger-color: var(--fm-red);--fm-warning-color: var(--fm-orange);--fm-submit-color: var(--fm-green-2);--fm-primary-color-light: var(--fm-blue-light);--fm-success-color-light: var(--fm-green-light);--fm-danger-color-light: var(--fm-red-light);--fm-warning-color-light: var(--fm-orange-light);--fm-text-color: var(--fm-gray-7);--fm-text-color-light: var(--fm-gray-5);--fm-active-color: var(--fm-gray-1);--fm-disabled-color: var(--fm-gray-4);--fm-readonly-color: var(--fm-gray-6);--fm-active-opacity: .7;--fm-readonly-opacity: .6;--fm-disabled-opacity: .5;--fm-background: var(--fm-gray-1);--fm-background-white: var(--fm-white);--fm-box-shadow-color: var(--fm-gray-1);--fm-padding-base: 4px;--fm-padding-xs: 8px;--fm-padding-sm: 12px;--fm-padding-md: 16px;--fm-padding-lg: 24px;--fm-padding-xl: 32px;--fm-padding-horizontal-xs: 0 var(--fm-padding-xs);--fm-padding-horizontal-sm: 0 var(--fm-padding-sm);--fm-padding-horizontal-md: 0 var(--fm-padding-md);--fm-padding-horizontal-lg: 0 var(--fm-padding-lg);--fm-margin-base: 4px;--fm-margin-xs: 8px;--fm-margin-sm: 12px;--fm-margin-md: 16px;--fm-margin-lg: 24px;--fm-margin-xl: 32px;--fm-margin-horizontal-xs: 0 var(--fm-margin-xs);--fm-margin-horizontal-sm: 0 var(--fm-margin-sm);--fm-margin-horizontal-md: 0 var(--fm-margin-md);--fm-margin-horizontal-lg: 0 var(--fm-margin-lg);--fm-font-bold-light: 500;--fm-font-bold: 600;--fm-font-size: 16px;--fm-line-height: 1.2;--fm-font-size-xs: 10px;--fm-font-size-sm: 12px;--fm-font-size-md: 14px;--fm-font-size-lg: 16px;--fm-gradient-blue: linear-gradient(-45deg,var(--fm-blue-2) 0%, var(--fm-blue) 100%);--fm-gradient-orange: linear-gradient(-45deg,var(--fm-orange) 0%, var(--fm-orange-2) 100%);--fm-base-font: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Segoe UI, Arial, Roboto, "PingFang SC", "miui", "Hiragino Sans GB", "Microsoft Yahei", sans-serif;--fm-price-font: avenir-heavy, "PingFang SC", helvetica neue, arial, sans-serif;--fm-duration-base: .3s;--fm-duration-fast: .2s;--fm-ease-out: ease-out;--fm-ease-in: ease-in;--fm-noborder: none;--fm-radius-sm: 2px;--fm-radius-md: 4px;--fm-radius-lg: 8px;--fm-radius-max: 999px;--fm-zindex-1: 9;--fm-zindex-2: 10;--fm-zindex-3: 99;--fm-zindex-4: 100;--fm-zindex-5: 999;--fm-zindex-6: 1000}*,*:before,*:after{box-sizing:border-box}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin:0}ul[role=list],ol[role=list]{list-style:none}html:focus-within{scroll-behavior:smooth}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5;font-family:-apple-system,Noto Sans,Helvetica Neue,Helvetica,Nimbus Sans L,Arial,Liberation Sans,PingFang SC,Hiragino Sans GB,Noto Sans CJK SC,Source Han Sans SC,Source Han Sans CN,Microsoft YaHei,Wenquanyi Micro Hei,WenQuanYi Zen Hei,ST Heiti,SimHei,WenQuanYi Zen Hei Sharp,sans-serif}a:not([class]){text-decoration-skip-ink:auto}img,picture{max-width:100%;display:block}input,button,textarea,select{font:inherit}@font-face{font-family:farrisMobile;font-style:normal;font-weight:400;src:url(data:font/ttf;base64,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AADmFAAAACUAAOYVAADmFQAAACYAAOYWAADmFgAAACcAAOYXAADmFwAAACgAAOYYAADmGAAAACkAAOYZAADmGQAAAHYAAOYaAADmGgAAAHUAAOYbAADmGwAAAHQAAOYcAADmHAAAAHMAAOYdAADmHQAAACoAAOYeAADmHgAAACsAAOYfAADmHwAAAHAAAOYgAADmIAAAAHEAAOYhAADmIQAAAHIAAOYiAADmIgAAAG8AAOYjAADmIwAAACwAAOYkAADmJAAAAGUAAOYlAADmJQAAAGYAAOYmAADmJgAAAGcAAOYnAADmJwAAAGgAAOYoAADmKAAAAGkAAOYpAADmKQAAAGoAAOYqAADmKgAAAGsAAOYrAADmKwAAAGwAAOYsAADmLAAAAG0AAOYtAADmLQAAAG4AAOYuAADmLgAAAGMAAOYvAADmLwAAAGQAAOYwAADmMAAAAGIAAOYyAADmMgAAADQAAOYzAADmMwAAAC0AAOY0AADmNAAAAC4AAOY2AADmNgAAAC8AAOY3AADmNwAAADAAAOY5AADmOQAAADEAAOY6AADmOgAAADIAAOZVAADmVQAAADUAAOZWAADmVgAAADoAAOZXAADmVwAAADcAAOZYAADmWAAAADgAAOZZAADmWQAAAD0AAOZaAADmWgAAAF4AAOZbAADmWwAAAF8AAOZcAADmXAAAAGAAAOZdAADmXQAAAGEAAOZeAADmXgAAADYAAOZfAADmXwAAADsAAOZgAADmYAAAADwAAOZhAADmYQAAADkAAOZiAADmYgAAAD4AAOZjAADmYwAAAD8AAOZkAADmZAAAAEAAAOZlAADmZQAAAEEAAOZmAADmZgAAAEIAAOZnAADmZwAAAEMAAOZoAADmaAAAAEQAAOZpAADmaQAAAEUAAOZqAADmagAAAEYAAOZrAADmawAAAEcAAOZsAADmbAAAAEgAAOZtAADmbQAAAEkAAOZuAADmbgAAAEoAAOZvAADmbwAAAEsAAOZwAADmcAAAAEwAAOZxAADmcQAAAE0AAOZyAADmcgAAAE4AAOZzAADmcwAAAE8AAOZ0AADmdAAAAFAAAOZ1AADmdQAAAFEAAOZ2AADmdgAAAFIAAOZ3AADmdwAAAFMAAOZ4AADmeAAAAFQAAOZ5AADmeQAAAFUAAOZ6AADmegAAAFYAAOZ7AADmewAAAFcAAOZ8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AV8BYAFhAWIBYwFkAWUBZgFnAWgBaQFqAWsBbAFtAW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+AAlzLW1vcmUtbzEIcy1kZWxldGUIcy1iYWNrLW8Gcy1zY2FuEHMtb3JnYW5pemF0aW9uLW8Jcy1ncm91cC1vCXMtZmlsdGVyMQlzLWNsZWFyLW8Ocy1pbGx1c3RyYXRlLW8Icy1tb21lbnQIcy1zaG9wLW8Kcy1tb21lbnQtbwZzLXNob3AKcy1yZXZva2UtbwpzLXN1Ym1pdC1vB3MtYXBwLW8Gcy1ib29rBXMtYXBwBHMtbXkJcy1jb21tZW50C3MtY29tbWVudC1vCHMtYm9vay1vBnMtbXktbwxzLWxvY2F0aW9uLW8Kcy1sb2NhdGlvbgZzLW5ld3MIcy1uZXdzLW8Jcy1TZW5kaW5nCnMtSW1wb3J0LW8Icy1FZGl0LW8Icy1RUmNvZGULcy1CcmllZmNhc2URcy1Ob3RpZmljYXRpb25vZmYIcy1QZW5jaWwIcy1TdGFyLW8Jcy1CYXJDb2RlD3MtU2FsZU1lc3NhZ2UtbwxzLUxpc3R2aWV3LW8Lcy1QaWN0dXJlLW8Ocy1TYXZlRmlsbGV0LW8Ocy1TaG9wcGluZ2NhcnQJcy1QZW5kaW5nDnMtRXhwYW5kdmlldy1vCHMtTG9jay1vCXMtU2VydmljZQpzLVdhbGxldC1vEHMtU2hvcHBpbmdjYXJ0LW8Lcy1TZXR0aW5nLW8Ncy1VbmZvbGRSZWMtbwlzLVByb2ZpbGUGTGluay1vDVVzZXJTZXR0aW5nLW8Jcy1hZ3JlZS1vDHMtYXJyb3ctZG93bgdzLWFkZC1vB3MtYW5uZXgMcy1hcnJvdy1sZWZ0CnMtYXJyb3ctdXAScy1jaGVja2JveC1jaGVja2VkCnMtY2hlY2tib3gHcy1hcnJvdwpzLWV4Y2hhbmdlB3MtY2xlYXIJcy1jaGVja2VkB3MtZXllLW8Lcy1jbG9zZS1leWUEcy1hdAxzLWZlZWRiYWNrLW8Pcy1mb2xkLWNpcmNsZS1vB3MtY3Jvc3MHcy1taW51cwZzLWZpbGUPcy1mb2xkLXRyaWFuZ2xlCHMtZmlsdGVyCXMtZm9yd29yZAZzLXBsdXMJcy1maWxlZGVsCHMtZm9sZC1vCXMtaW1hZ2UtbwhzLW1vcmUtbw5zLXJlZGlvLWNpcmNsZQpzLXJlamVjdC1vCXMtc3VjY2VzcwlzLXJlZnJlc2gGcy1zdGFyDXMtcHJvY2Vzc2Zsb3cRcy11bmZvbGQtY2lyY2xlLW8Icy1yZXdpbmQKcy11bmZvbGQtbwtzLXdhcm5pbmctbxFzLXVuZm9sZC10cmlhbmdsZQlzLXByaW50LW8Kcy1zZWFyY2gtbwhBaXJwbGFuZQVUcmFpbgNCdXMEVGF4aQxvdmVydGltZW1lYWwTZm0taS10cmFmZmljZGV0YWlscw9mbS1pLXRyYWZmaWNzdWITZm0taS1hY2NvbW1vZGF0aW9uMQ1mbS1pLWJ1c2luZXNzC2ZtLWktYnVkZ2V0CWZtLWktZ2lmdBFmbS1pLWNhbmNlbGxhdGlvbgxmbS1pLWludm9pY2UJZm0taS1saXN0CmZtLWktbWVhbHMIZm0taS1wYXkMZm0taS1zdWJzaWR5B3Nob3V6aGUTZm0taS1jb3N0YWxsb2NhdGlvbgxmbS1pLXBheW1lbnQOZm0taS1JdGluZXJhcnkOZm0taS1tb3JleGUwMmQPZm0taS1pbWFnZXhlMDJlEGZtLWktcmVqZWN0eGUwMmYPZm0taS1hZ3JlZXhlMDMxDWZtLWktY2FyZGZvbGQPZm0taS1jYXJkdW5mb2xkEWZtLWktdHJhZmZpY290aGVyD2ZtLWktYm90dG9tc2F2ZRBmbS1pLXRyYWZmaWNib2F0D2ZtLWktdHJhZmZpY2NhchFmbS1pLXRyYWZmaWNwbGFuZRFmbS1pLXRyYWZmaWN0cmFpbg9mbS1pLXRyYWZmaWNidXMMZm0taS1hZGRncmF5CmZtLWktY2xvc2UIZm0taS1hZGQJZm0taS1tb3JlCmZtLWktY2hlY2sPZm0taS1iYWNrY2lyY2xlCmZtLWktYWdyZWUMZm0taS1sb2FkaW5nDGZtLWktZmlsZWRlbAlmbS1pLWZpbGUQZm0taS1wcm9jZXNzZmxvdwxmbS1pLXJlZHN0YXIQZm0taS1yaWdodGNpcmNsZQ9mbS1pLXRpbWVjaXJjbGUOZm0taS1zY3JlZW5pbmcMZm0taS11bmNoZWNrDmZtLWktb3BlcmF0aW9uE2ZtLWktYXBwcm92YWxhbW91bnQLZm0taS1hZ3JlZWQOZm0taS1pbnByb2Nlc3MNZm0taS1mZWVkYmFjawpmbS1pLXByaW50DmZtLWktaW1wb3J0YW50GmZtLWktYW1vdW50b2ZyZWltYnVyc2VtZW50FGZtLWktc2FmZXR5YXNzaXN0YW50C2ZtLWktcmVtaW5kDWZtLWktZXllb3BwZW4NZm0taS1leWVjbG9zZRBmbS1pLVBob3RvZ3JhcGh5D2ZtLWktcGhvdG9ncmFwaA9mbS1pLWFkZHBpY3R1cmUTZm0taS10b3Bfb3RoZXItZmFjZQ5mbS1pLXRvcF9vdGhlcgtmbS1pLWRlbGV0ZQ1mbS1pLW5leHRwYWdlDmZtLWktYWRkYnV0dG9uFmZtLWktd2FpdGZvcnByb2Nlc3NpbmcTZm0taS13YXJuaW5nbWVzc2FnZRJmbS1pLWZhaWx1cmVwcm9tcHQUZm0taS1zdWNjZXNzZnVsaGludHMKZm0taS1vdGhlcgxmbS1pLXJldHJhY3QOZm0taS1kcm9wLWRvd24LZm0taS1jYW5jZWwLZm0taS1zZWFyY2gTZm0taS1tdWx0aXBsZWNob2ljZRFmbS1pLXNpbmdsZWNob2ljZQ9mbS1pLW1pY3JvcGhvbmUXZm0taS1hcnJvdy1jaGV2cm9uLWxlZnQPZm0taS1oZWxwY2VudGVyDmZtLWktc3dlZXBjb2RlDmZtLWktZ3JvdXBjaGF0DmZtLWktYWRkZnJpZW5kC2ZtLWktdG9wX215EGZtLWktdG9wX215LWZhY2UPZm0taS10b3BfZnJpZW5kFGZtLWktdG9wX2ZyaWVuZC1mYWNlFWZtLWktdG9wX3B1YmxpY3ByYWlzZRpmbS1pLXRvcF9wdWJsaWNwcmFpc2UtZmFjZQ1mbS1pLXRvcF9ob21lEmZtLWktdG9wX2hvbWUtZmFjZQAAAAA=) format("truetype")}@keyframes fm-fade-in{0%{opacity:0}to{opacity:1}}@keyframes fm-fade-out{0%{opacity:1}to{opacity:0}}.fm-fade-enter-active{animation:.3s fm-fade-in both ease-out}.fm-fade-leave-active{animation:.3s fm-fade-out both ease-in}.fm-slide-up-enter-from,.fm-slide-up-leave-to{transform:translate3d(0,100%,0)}.fm-slide-down-enter-from,.fm-slide-down-leave-to{transform:translate3d(0,-100%,0)}.fm-slide-left-enter-from,.fm-slide-left-leave-to{transform:translate3d(-100%,0,0)}.fm-slide-right-enter-from,.fm-slide-right-leave-to{transform:translate3d(100%,0,0)}.fm-slide-up-enter-active,.fm-slide-down-enter-active,.fm-slide-left-enter-active,.fm-slide-right-enter-active{transition-timing-function:ease-out}.fm-slide-up-leave-active,.fm-slide-down-leave-active,.fm-slide-left-leave-active,.fm-slide-right-leave-active{transition-timing-function:ease-in}.fm-slide-in-enter-active,.fm-slide-in-leave-active,.fm-slide-out-enter-active,.fm-slide-out-leave-active{will-change:transform;transition:all .3s;height:100%;width:100%;top:0;position:absolute;backface-visibility:hidden;perspective:1000}.fm-slide-in-leave-to,.fm-slide-out-enter-from{transform:translate(-100%);opacity:0}.fm-slide-in-enter-from,.fm-slide-out-leave-to{transform:translate(100%);opacity:0}@keyframes fm-drop-down-in{0%{height:0;opacity:0}to{opacity:1}}@keyframes fm-drop-down-out{0%{opacity:1}to{height:0;opacity:0}}.fm-drop-down-enter-active{animation:.3s fm-drop-down-in both ease-out}.fm-drop-down-leave-active{animation:.3s fm-drop-down-out both ease-in}@keyframes fm-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}:root{--fm-button-height: 42px;--fm-button-padding: 0 14px;--fm-button-radius: 2px;--fm-button-border-width: 1px;--fm-button-color: var(--fm-white);--fm-button-line-height: var(--fm-line-height);--fm-button-font-size: var(--fm-font-size);--fm-button-plain-background: var(--fm-white);--fm-button-lg-height: 46px;--fm-button-lg-font-size: 18px;--fm-button-md-height: 38px;--fm-button-md-font-size: 14px;--fm-button-sm-height: 34px;--fm-button-sm-padding: 0 8px;--fm-button-sm-font-size: 12px;--fm-button-xs-height: 28px;--fm-button-xs-font-size: 10px;--fm-button-secondary-color: var(--fm-blue-light)}.fm-button{position:relative;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;text-align:center;margin:0;border:none;transition:opacity .2s;color:var(--fm-button-color);height:var(--fm-button-height);padding:var(--fm-button-padding);font-size:var(--fm-button-font-size);line-height:var(--fm-button-line-height);border-radius:var(--fm-button-radius)}.fm-button--primary,.fm-button--info{background:var(--fm-primary-color)}.fm-button--secondary{color:var(--fm-primary-color);background:var(--fm-button-secondary-color)}.fm-button--danger{background-color:var(--fm-danger-color)}.fm-button--warning{background-color:var(--fm-warning-color)}.fm-button--success{background-color:var(--fm-success-color)}.fm-button--plain{box-shadow:none;background:var(--fm-button-plain-background)}.fm-button--plain.fm-button--primary,.fm-button--plain.fm-button--info{color:var(--fm-primary-color);border:var(--fm-button-border-width) solid var(--fm-primary-color)}.fm-button--plain.fm-button--success{color:var(--fm-success-color);border:var(--fm-button-border-width) solid var(--fm-success-color)}.fm-button--plain.fm-button--danger{color:var(--fm-danger-color);border:var(--fm-button-border-width) solid var(--fm-danger-color)}.fm-button--plain.fm-button--warning{color:var(--fm-button-warning-color);border:var(--fm-button-border-width) solid var(--fm-button-warning-color)}.fm-button--noborder{border:none!important}.fm-button--large{height:var(--fm-button-lg-height);font-size:var(--fm-button-lg-font-size)}.fm-button--normal{height:var(--fm-button-md-height);font-size:var(--fm-button-md-font-size)}.fm-button--small{height:var(--fm-button-sm-height);padding:var(--fm-button-sm-padding);font-size:var(--fm-button-sm-font-size)}.fm-button--mini{height:var(--fm-button-xs-height);padding:var(--fm-button-sm-padding);font-size:var(--fm-button-xs-font-size)}.fm-button--block{display:flex;width:100%}.fm-button--disabled{cursor:not-allowed;opacity:var(--fm-disabled-opacity)}.fm-button--loading:before,.fm-button--disabled:before{display:none}.fm-button--round{border-radius:var(--fm-radius-max)}.fm-button--square{border-radius:0}.fm-button__loading{display:inline-block;width:20px;max-width:100%;height:20px;max-height:100%;vertical-align:middle;animation:fm-rotate 2s linear infinite}.fm-button__loading circle{animation:fm-circular 1.5s ease-in-out infinite;stroke:currentColor;stroke-width:4;stroke-linecap:round}.fm-button__loading-icon-circular{color:#fff}.fm-button__loading-text{margin-left:6px}.fm-button__icon:not(:last-child){margin-right:6px}.fm-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" "}.fm-button:active:before{opacity:.1}.fm-button-edit__tags{min-height:24px;flex:1;display:flex;overflow:auto}.fm-button-edit__tag:not(:last-child){margin-right:6px}.fm-button-group{display:flex;padding:8px 16px}.fm-button-group__item{display:flex;flex:1}:root{--fm-cell-padding: 10px 16px;--fm-cell-margin: 5px;--fm-cell-line-height: 24px;--fm-cell-font-size: var(--fm-font-size);--fm-cell-background: var(--fm-background-white);--fm-cell-color: var(--fm-text-color);--fm-cell-label-font-size: 12px;--fm-cell-label-line-height: 18px;--fm-cell-label-color: var(--fm-text-color-light);--fm-cell-required-color: var(--fm-danger-color)}.fm-cell{width:100%;padding:var(--fm-cell-padding);background-color:var(--fm-cell-background);color:var(--fm-cell-color);font-size:var(--fm-cell-font-size);line-height:var(--fm-cell-line-height);position:relative;display:flex;overflow:hidden}.fm-cell-bottom-border,.fm-cell:not(:last-child){border-bottom:1px solid #ddd;position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-cell-bottom-border,html:not([data-scale]) .fm-cell:not(:last-child){border-bottom:none}html:not([data-scale]) .fm-cell-bottom-border:after,html:not([data-scale]) .fm-cell:not(:last-child):after{content:"";position:absolute;background-color:#ddd;display:block;z-index:1;inset:auto auto 0 0;width:100%;height:1px;transform-origin:50% 100%;transform:scaleY(.5)}}.fm-cell-bottom-border:after,.fm-cell:not(:last-child):after{left:16px!important}.fm-cell.fm-cell-all-width:not(:last-child):after{left:0!important}.fm-cell--clickable{cursor:pointer}.fm-cell--clickable:active{background-color:var(--fm-active-color)}.fm-cell--required .fm-cell-title{position:relative}.fm-cell--required .fm-cell-title .fm-cell-title-text:after{padding-left:2px;color:var(--fm-cell-required-color);font-size:12px;content:"*"}.fm-cell__title,.fm-cell__value{flex:1;font-size:inherit}.fm-cell__title{display:inline-block;overflow:hidden}.fm-cell__title-text{display:flex;word-break:break-all}.fm-cell__title-text span{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fm-cell__right{display:flex;overflow:hidden;flex-direction:column}.fm-cell__right-content{display:flex;flex:1}.fm-cell__right--fill{flex:1}.fm-cell__value{position:relative;overflow:hidden;text-align:right;vertical-align:middle;word-wrap:break-word}.fm-cell__value--alone{text-align:left}.fm-cell__label{margin-top:var(--fm-cell-margin);color:var(--fm-cell-label-color);font-size:var(--fm-cell-label-font-size);line-height:var(--fm-cell-label-line-height)}.fm-cell--center{align-items:center}.fm-cell__extra,.fm-cell__left-icon,.fm-cell__right-icon{min-width:1em;font-size:var(--fm-cell-font-size);line-height:var(--fm-cell-line-height);display:flex;align-items:center}.fm-cell__left-icon{margin-right:var(--fm-cell-margin)}.fm-cell__extra,.fm-cell__right-icon{margin-left:var(--fm-cell-margin)}.fm-cell--noborder .fm-cell:after{display:none!important}.fm-cell--card{padding-left:0;padding-right:0}.fm-checkbox-group{display:flex;overflow:visible;text-align:left;flex-wrap:wrap}.fm-checkbox-group--vertical{flex-direction:column}.fm-checkbox-group--vertical .fm-checkbox:not(:last-child){margin-bottom:8px}.fm-checkbox{margin-top:4px;margin-bottom:4px}:root{--fm-checker-color: var(--fm-text-color);--fm-checker-font-size: var(--fm-font-size);--fm-checker-icon-color: var(--fm-text-color-light);--fm-checker-icon-background: var(--fm-background-white);--fm-checker-icon-radius: var(--fm-radius-md);--fm-checker-checked-icon-color: var(--fm-primary-color);--fm-checker-button-background: var(--fm-gray-2);--fm-checker-disabled-color: var(--fm-disabled-color);--fm-checker-disabled-icon-color: var(--fm-gray-1)}.fm-checker{display:flex;align-items:center;color:var(--fm-checker-color);font-size:var(--fm-checker-font-size)}.fm-checker__icon{display:inline-block;align-items:center}.fm-checker__icon .fm-icon{display:block;height:20px;width:20px;line-height:18px;font-size:14px;text-align:center;border-radius:var(--fm-checker-icon-radius);border:1px solid var(--fm-checker-icon-color);color:var(--fm-checker-icon-background);background-color:var(--fm-checker-icon-background)}.fm-checker__label{margin-left:8px;margin-right:8px;display:inline-block;line-height:20px}.fm-checker:first-child .fm-checker_button{margin-left:0}.fm-checker--round .fm-checker__icon .fm-icon{border-radius:100%}.fm-checker--button .fm-checker__label{font-size:13px;text-align:center;border-radius:14px;line-height:28px;padding:0 12px;min-width:60px;margin-right:0;color:var(--fm-checker-color);background:var(--fm-checker-button-background)}.fm-checker--checked .fm-checker__icon .fm-icon{color:var(--fm-checker-icon-background);border-color:var(--fm-checker-checked-icon-color);background-color:var(--fm-checker-checked-icon-color)}.fm-checker--checked.fm-checker--button .fm-checker__label{color:var(--fm-checker-icon-background);border-color:var(--fm-checker-color);background-color:var(--fm-checker-checked-icon-color)}.fm-checker--readonly{opacity:var(--fm-readonly-opacity)}.fm-checker--disabled{color:var(--fm-checker-disabled-color)}.fm-checker--disabled .fm-checker__icon .fm-icon{border-color:var(--fm-checker-disabled-color);background-color:var(--fm-checker-disabled-icon-color);color:var(--fm-checker-disabled-icon-color)}.fm-checker--disabled.fm-checker--checked .fm-checker__icon .fm-icon{background-color:var(--fm-checker-disabled-color);border-color:var(--fm-checker-disabled-color)}:root{--fm-icon-font-size: 14px;--fm-icon-color: inherit}.fm-icon{font-family:farrisMobile!important;font-size:var(--fm-icon-font-size);font-style:normal;color:var(--fm-icon-color);display:inline-block;width:1em;height:1em;font-weight:400;line-height:1;vertical-align:middle;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fm-icon:before{display:inline-block}.fm-icon-filter:before{content:"\e697"}.fm-icon-cardfold:before{content:"\e6b7"}.fm-icon-cardunfold:before{content:"\e6b8"}.fm-icon-trafficother:before{content:"\e6b9"}.fm-icon-bottomsave:before{content:"\e6ba"}.fm-icon-trafficboat:before{content:"\e6bb"}.fm-icon-trafficcar:before{content:"\e6bc"}.fm-icon-trafficplane:before{content:"\e6bd"}.fm-icon-traffictrain:before{content:"\e6be"}.fm-icon-trafficbus:before{content:"\e6bf"}.fm-icon-addgray:before{content:"\e6a7"}.fm-icon-close:before{content:"\e6a8"}.fm-icon-add-line:before{content:"\e6a9"}.fm-icon-more:before{content:"\e6aa"}.fm-icon-check:before{content:"\e6ab"}.fm-icon-backcircle:before{content:"\e6ac"}.fm-icon-agree:before{content:"\e6ad"}.fm-icon-loading:before{content:"\e6ae"}.fm-icon-filedel:before{content:"\e6af"}.fm-icon-file:before{content:"\e6b0"}.fm-icon-processflow:before{content:"\e6b1"}.fm-icon-redstar:before{content:"\e6b2"}.fm-icon-rightcircle:before{content:"\e6b3"}.fm-icon-timecircle:before{content:"\e6b4"}.fm-icon-screening:before{content:"\e6b5"}.fm-icon-uncheck:before{content:"\e6b6"}.fm-icon-operation:before{content:"\e02c"}.fm-icon-approvalamount:before{content:"\e02b"}.fm-icon-agreed:before{content:"\e02a"}.fm-icon-inprocess:before{content:"\e029"}.fm-icon-feedback:before{content:"\e028"}.fm-icon-print:before{content:"\e027"}.fm-icon-important:before{content:"\e026"}.fm-icon-amountofreimbursement:before{content:"\e025"}.fm-icon-safetyassistant:before{content:"\e024"}.fm-icon-remind:before{content:"\e023"}.fm-icon-eyeoppen:before{content:"\e022"}.fm-icon-eyeclose:before{content:"\e01e"}.fm-icon-photography:before{content:"\e021"}.fm-icon-photograph:before{content:"\e020"}.fm-icon-addpicture:before{content:"\e01f"}.fm-icon-top_other-face:before{content:"\e01d"}.fm-icon-top_other:before{content:"\e01c"}.fm-icon-delete:before{content:"\e01b"}.fm-icon-nextpage:before{content:"\e01a"}.fm-icon-addbutton:before{content:"\e019"}.fm-icon-waitforprocessing:before{content:"\e018"}.fm-icon-warningmessage:before{content:"\e017"}.fm-icon-failureprompt:before{content:"\e016"}.fm-icon-successfulhints:before{content:"\e015"}.fm-icon-other:before{content:"\e014"}.fm-icon-retract:before{content:"\e013"}.fm-icon-drop-down:before{content:"\e012"}.fm-icon-cancel:before{content:"\e011"}.fm-icon-search:before{content:"\e010"}.fm-icon-multiplechoice:before{content:"\e00f"}.fm-icon-singlechoice:before{content:"\e00e"}.fm-icon-microphone:before{content:"\e00d"}.fm-icon-arrow-chevron-left:before{content:"\e00c"}.fm-icon-helpcenter:before{content:"\e00b"}.fm-icon-sweepcode:before{content:"\e00a"}.fm-icon-groupchat:before{content:"\e009"}.fm-icon-addfriend:before{content:"\e008"}.fm-icon-top_my:before{content:"\e007"}.fm-icon-top_my-face:before{content:"\e006"}.fm-icon-top_friend:before{content:"\e005"}.fm-icon-top_friend-face:before{content:"\e004"}.fm-icon-top_publicpraise:before{content:"\e003"}.fm-icon-top_publicpraise-face:before{content:"\e002"}.fm-icon-top_home:before{content:"\e001"}.fm-icon-top_home-face:before{content:"\e000"}.fm-icon-s-agree-o:before{content:"\e655"}.fm-icon-s-arrow-down:before{content:"\e656"}.fm-icon-s-add-o:before{content:"\e657"}.fm-icon-s-annex:before{content:"\e658"}.fm-icon-s-arrow:before{content:"\e659"}.fm-icon-s-arrow-up:before{content:"\e65e"}.fm-icon-s-checkbox-checked:before{content:"\e65f"}.fm-icon-s-checkbox:before{content:"\e660"}.fm-icon-s-arrow-left:before{content:"\e661"}.fm-icon-s-exchange:before{content:"\e662"}.fm-icon-s-clear:before{content:"\e663"}.fm-icon-s-checked:before{content:"\e664"}.fm-icon-s-eye-o:before{content:"\e665"}.fm-icon-s-close-eye:before{content:"\e666"}.fm-icon-s-at:before{content:"\e667"}.fm-icon-s-feedback-o:before{content:"\e668"}.fm-icon-s-fold-circle-o:before{content:"\e669"}.fm-icon-s-cross:before{content:"\e66a"}.fm-icon-s-minus:before{content:"\e66b"}.fm-icon-s-file:before{content:"\e66c"}.fm-icon-s-fold-triangle:before{content:"\e66d"}.fm-icon-s-filter:before{content:"\e66e"}.fm-icon-s-forword:before{content:"\e66f"}.fm-icon-s-plus:before{content:"\e670"}.fm-icon-s-filedel:before{content:"\e671"}.fm-icon-s-fold-o:before{content:"\e672"}.fm-icon-s-image-o:before{content:"\e673"}.fm-icon-s-more-o:before{content:"\e674"}.fm-icon-s-redio-circle:before{content:"\e675"}.fm-icon-s-reject-o:before{content:"\e676"}.fm-icon-s-success:before{content:"\e677"}.fm-icon-s-refresh:before{content:"\e678"}.fm-icon-s-star:before{content:"\e679"}.fm-icon-s-processflow:before{content:"\e67a"}.fm-icon-s-unfold-circle-o:before{content:"\e67b"}.fm-icon-s-rewind:before{content:"\e67c"}.fm-icon-s-unfold-o:before{content:"\e67d"}.fm-icon-s-save-o:before{content:"\e67e"}.fm-icon-s-warning-o:before{content:"\e67f"}.fm-icon-s-unfold-triangle:before{content:"\e680"}.fm-icon-s-print-o:before{content:"\e681"}.fm-icon-s-search-o:before{content:"\e682"}.fm-icon-s-news:before{content:"\e683"}.fm-icon-s-news-o:before{content:"\e684"}.fm-icon-s-shop:before{content:"\e68c"}.fm-icon-s-sending:before{content:"\e60b"}.fm-icon-s-import-o:before{content:"\e60c"}.fm-icon-s-edit-o:before{content:"\e60d"}.fm-icon-s-qrcode:before{content:"\e60e"}.fm-icon-s-briefcase:before{content:"\e60f"}.fm-icon-s-notificationoff:before{content:"\e610"}.fm-icon-s-pencil:before{content:"\e611"}.fm-icon-s-star-o:before{content:"\e612"}.fm-icon-s-barcode:before{content:"\e613"}.fm-icon-s-salemessage-o:before{content:"\e614"}.fm-icon-s-listview-o:before{content:"\e615"}.fm-icon-s-picture-o:before{content:"\e616"}.fm-icon-s-savefillet-o:before{content:"\e617"}.fm-icon-s-shoppingcart:before{content:"\e618"}.fm-icon-s-pending:before{content:"\e61d"}.fm-icon-s-expandview-o:before{content:"\e61e"}.fm-icon-s-lock-o:before{content:"\e623"}.fm-icon-s-my:before{content:"\e692"}.fm-icon-s-service:before{content:"\e633"}.fm-icon-s-wallet-o:before{content:"\e634"}.fm-icon-s-shoppingcart-o:before{content:"\e636"}.fm-icon-s-setting-o:before{content:"\e637"}.fm-icon-s-my-o:before{content:"\e696"}.fm-icon-s-unfoldrec-o:before{content:"\e639"}.fm-icon-s-profile:before{content:"\e63a"}.fm-icon-s-link-o:before{content:"\e609"}.fm-icon-s-usersetting-o:before{content:"\e632"}.fm-icon-s-shop-o:before{content:"\e68a"}.fm-icon-s-list:before{content:"\e62a"}.fm-icon-s-location-o:before{content:"\e685"}.fm-icon-s-location:before{content:"\e686"}.fm-icon-s-moment:before{content:"\e689"}.fm-icon-s-moment-o:before{content:"\e68b"}.fm-icon-s-revoke-o:before{content:"\e687"}.fm-icon-s-submit-o:before{content:"\e688"}.fm-icon-s-app-o:before{content:"\e68f"}.fm-icon-s-app:before{content:"\e691"}.fm-icon-s-book-o:before{content:"\e695"}.fm-icon-s-book:before{content:"\e690"}.fm-icon-s-comment:before{content:"\e693"}.fm-icon-s-comment-o:before{content:"\e694"}.fm-icon-s-illustrate-o:before{content:"\e68d"}.fm-icon-s-clear-o:before{content:"\e68e"}.fm-icon-friend:before{content:"\e005"}.fm-icon-scan:before{content:"\e69a"}.fm-icon-back:before{content:"\e69b"}.fm-icon-menu:before{content:"\e69d"}:root{--fm-navbar-background: var(--fm-background-white);--fm-navbar-color: var(--fm-text-color);--fm-navbar-height: 44px;--fm-navbar-title-size: 17px;--fm-navbar-side-size: 16px;--fm-navbar-arrow-size: 18px}.fm-navbar{position:relative;z-index:9;display:flex;align-items:center;line-height:1.5;text-align:center;user-select:none;height:var(--fm-navbar-height);color:var(--fm-navbar-color);background-color:var(--fm-navbar-background)}.fm-navbar.fm-navbar-fixed{position:fixed;top:0;left:0;width:100%}.fm-navbar.fm-navbar-border-bottom{border-bottom:1px solid #eee;position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-navbar.fm-navbar-border-bottom{border-bottom:none}html:not([data-scale]) .fm-navbar.fm-navbar-border-bottom:after{content:"";position:absolute;background-color:#eee;display:block;z-index:1;inset:auto auto 0 0;width:100%;height:1px;transform-origin:50% 100%;transform:scaleY(.5)}}.fm-navbar-title{max-width:60%;margin:0 auto;font-weight:500;font-size:var(--fm-navbar-title-size);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fm-navbar-left,.fm-navbar-right{position:absolute;top:0;bottom:0;display:flex;align-items:center;max-width:30%;padding:0 16px;font-size:var(--fm-navbar-side-size);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:pointer}.fm-navbar-left{left:0}.fm-navbar-left:active{opacity:var(--fm-active-opacity)}.fm-navbar-left.fm-navbar-left-padding{padding-left:14px}.fm-navbar-right{right:0}.fm-navbar-right .fm-navbar-text:active{opacity:var(--fm-active-opacity)}.fm-navbar .fm-navbar-left-arrow{min-width:1em;margin-right:4px;font-size:var(--fm-navbar-arrow-size)}:root{--fm-input-group-size: var(--fm-font-size);--fm-input-group-color: var(--fm-text-color);--fm-input-group-sub-size: 13px;--fm-input-group-padding: 10px 16px;--fm-input-group-sub-color: var(--fm-text-color-light);--fm-input-group-border-color: var(--fm-gray-2)}.fm-input-group{display:flex;flex-direction:column;background-color:var(--fm-white)}.fm-input-group--padding{padding:var(--fm-input-group-padding)}.fm-input-group__body{flex:1;display:flex;align-items:center;min-height:24px}.fm-input-group__body--border{border:1px solid var(--fm-input-group-border-color);padding:4px 8px;border-radius:4px}.fm-input-group__control{display:flex;width:100%;min-width:0;margin:0;padding:0;border:0;resize:none;line-height:inherit;background-color:transparent;color:var(--fm-input-group-color);font-size:var(--fm-input-group-size);outline:none}.fm-input-group__control::placeholder{color:var(--fm-input-group-sub-color)}.fm-input-group__control:disabled{opacity:1;cursor:not-allowed;color:var(--fm-disabled-color);-webkit-text-fill-color:currentColor}.fm-input-group__control::-webkit-search-cancel-button{display:none}.fm-input-group__control--readonly{cursor:default;color:var(--fm-readonly-color)}.fm-input-group__control--left{justify-content:flex-start;text-align:left}.fm-input-group__control--center{justify-content:center;text-align:center}.fm-input-group__control--right{justify-content:flex-end;text-align:right}.fm-input-group__clear{cursor:pointer;margin-right:-8px;padding:4px 8px;color:var(--fm-input-group-sub-color);flex-shrink:0;box-sizing:content-box}.fm-input-group__left-icon{margin:auto 4px auto 0}.fm-input-group__right-icon{margin:auto 0 auto 4px}.fm-input-group__word-limit{margin-top:4px;line-height:18px;text-align:right;font-size:var(--fm-input-group-sub-size);color:var(--fm-input-group-sub-color)}.fm-radio-group{display:flex;overflow:visible;text-align:left;flex-wrap:wrap}.fm-radio-group--vertical{flex-direction:column}.fm-radio-group--vertical .fm-radio:not(:last-child){margin-bottom:8px}.fm-radio{margin-top:4px;margin-bottom:4px}:root,:host{--fm-rate-icon-size: 20px;--fm-rate-icon-gutter: var(--fm-padding-base);--fm-rate-icon-void-color: var(--fm-gray-4);--fm-rate-icon-full-color: var(--fm-orange-3);--fm-rate-icon-disabled-color: var(--fm-gray-4)}.fm-rate{display:inline-flex;cursor:pointer;user-select:none;flex-wrap:wrap}.fm-rate__item{position:relative}.fm-rate__item:not(:last-child){padding-right:var(--fm-rate-icon-gutter)}.fm-rate__icon{display:block;width:1em;color:var(--fm-rate-icon-void-color);font-size:var(--fm-rate-icon-size)}.fm-rate__icon--half{position:absolute;top:0;left:0;overflow:hidden;pointer-events:none;color:var(--fm-rate-icon-full-color)}.fm-rate__icon--full{color:var(--fm-rate-icon-full-color)}.fm-rate__icon--disabled{color:var(--fm-rate-icon-disabled-color)}.fm-rate--disabled{cursor:not-allowed}.fm-rate--readonly{cursor:default}:root{--fm-form-item-size: var(--fm-font-size);--fm-form-item-color: var(--fm-text-color);--fm-form-item-label-width: 105px;--fm-form-item-sub-size: 13px}.fm-form-item{font-size:var(--fm-form-item-size);color:var(--fm-form-item-color)}.fm-form-item--vertical{flex-direction:column}.fm-form-item--vertical .fm-form-item__label{margin-bottom:4px}.fm-form-item__label{display:flex;flex:none;align-items:flex-start;text-align:left;width:var(--fm-form-item-label-width);margin-right:4px}.fm-form-item__label--left{justify-content:flex-start}.fm-form-item__label--center{justify-content:center}.fm-form-item__label--right{justify-content:flex-end}.fm-form-item__label--required{position:relative}.fm-form-item__label--required .fm-cell__title-text:after{padding-left:2px;color:var(--fm-cell-required-color);font-size:12px;content:"*"}.fm-form-item__content{display:flex}.fm-form-item__content .fm-input-group{padding:0;flex:1}.fm-form-item__content--left{justify-content:flex-start}.fm-form-item__content--left input.fm-input-group__control{justify-content:flex-start;text-align:left}.fm-form-item__content--center{justify-content:center}.fm-form-item__content--center input.fm-input-group__control{justify-content:flex-center;text-align:center}.fm-form-item__content--right{justify-content:flex-end}.fm-form-item__content--right input.fm-input-group__control{justify-content:flex-end;text-align:right}.fm-form-item__error-message{color:var(--fm-danger-color);font-size:var(--fm-form-item-sub-size)}.fm-form-item__error-message--left{text-align:left}.fm-form-item__error-message--center{text-align:center}.fm-form-item__error-message--right{text-align:right}.fm-form{display:flex;flex-direction:column}.fm-form .farris-component.can-move{padding:0!important}.fm-input-wrapper:not(:last-child) .fm-cell:not(.fm-no-hairline):after,.fm-form-item-wrapper:not(:last-child):not(.fm-no-hairline):after,.fm-form-designer-item-wrapper:not(:last-child) .fm-form-item-wrapper:not(.fm-no-hairline):after{transform:scaleY(.5)}:root{--fm-overlay-background: rgba(0, 0, 0, .4);--fm-overlay-zindex: 98}.fm-overlay{width:100%;position:fixed;top:0;left:0;z-index:var(--fm-overlay-zindex);background-color:var(--fm-overlay-background);bottom:0}@supports ((bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom))) and (-webkit-overflow-scrolling: touch){.fm-overlay{bottom:constant(safe-area-inset-bottom);bottom:env(safe-area-inset-bottom)}}:root{--fm-popup-background: var(--fm-white);--fm-popup-zindex: var(--fm-zindex-3);--fm-popup-radius: 16px}.fm-popup{position:fixed;max-height:100%;overflow-y:auto;background-color:var(--fm-popup-background);transition:all var(--fm-duration-base);z-index:var(--fm-popup-zindex)}.fm-popup--center{top:50%;left:50%;transform:translate(-50%,-50%)}.fm-popup--center.fm-popup--round{border-radius:var(--fm-popup-radius)}.fm-popup--top,.fm-popup--bottom{left:0;right:0}.fm-popup--top{top:0}.fm-popup--top.fm-popup--round{border-radius:0 0 var(--fm-popup-radius) var(--fm-popup-radius)}.fm-popup--bottom{bottom:0}@supports ((bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom))) and (-webkit-overflow-scrolling: touch){.fm-popup--bottom{bottom:constant(safe-area-inset-bottom);bottom:env(safe-area-inset-bottom)}}.fm-popup--bottom.fm-popup--round{border-radius:var(--fm-popup-radius) var(--fm-popup-radius) 0 0}.fm-popup--left,.fm-popup--right{top:0;bottom:0}@supports ((bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom))) and (-webkit-overflow-scrolling: touch){.fm-popup--left,.fm-popup--right{bottom:constant(safe-area-inset-bottom);bottom:env(safe-area-inset-bottom)}}.fm-popup--left{left:0}.fm-popup--left.fm-popup--round{border-radius:0 var(--fm-popup-radius) var(--fm-popup-radius) 0}.fm-popup--right{right:0}.fm-popup--right.fm-popup--round{border-radius:var(--fm-popup-radius) 0 0 var(--fm-popup-radius)}:root{--fm-switch-background: var(--fm-text-color-light);--fm-switch-on-color: var(--fm-primary-color)}.fm-switch{position:relative;cursor:pointer;display:inline-block;transition:background-color var(--fm-duration-base);background-color:var(--fm-switch-background)}.fm-switch--disabled{cursor:not-allowed;opacity:var(--fm-disabled-opacity)}.fm-switch--readonly{cursor:default;opacity:var(--fm-readonly-opacity)}.fm-switch--loading{cursor:default}.fm-switch--on{background-color:var(--fm-switch-on-color)}.fm-switch--on .fm-switch__loadding{color:var(--fm-switch-on-color)}.fm-switch__node{display:flex;align-items:center;justify-content:center;position:absolute;top:1px;left:1px;z-index:1;width:28px;height:28px;border-radius:100%;background-color:var(--fm-white);transition:transform var(--fm-duration-base) cubic-bezier(.3,1.05,.4,1.05)}:root{--fm-toast-zindex: var(--fm-zindex-5);--fm-toast-color: var(--fm-white);--fm-toast-font-size: 16px;--fm-toast-background: var(--fm-gray-7);--fm-toast-icon-font-size: 48px}.fm-toast{position:fixed;top:50%;left:50%;display:-webkit-box;display:-webkit-flex;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:content-box;max-width:70%;padding:16px;line-height:20px;white-space:pre-wrap;text-align:center;word-wrap:break-word;border-radius:7px;transform:translate(-50%,-50%);color:var(--fm-toast-color);z-index:var(--fm-toast-zindex);font-size:var(--fm-toast-font-size);background-color:var(--fm-toast-background)}.fm-toast--top{top:50px;transform:translate(-50%)}.fm-toast--bottom{top:auto;bottom:50px}.fm-toast--info,.fm-toast--success,.fm-toast--warning,.fm-toast--error{width:88px;min-height:88px}.fm-toast__icon-wrapper{margin-bottom:8px}.fm-toast--default{padding:8px 16px}.fm-toast--loading{min-width:84px;min-height:84px}.fm-toast--loading-icon{position:relative;display:inline-block;width:30px;height:30px;margin-bottom:8px;vertical-align:middle;animation:fm-rotate 2s linear infinite}.fm-toast--loading-icon circle{animation:fm-circular 1.5s ease-in-out infinite;stroke:currentColor;stroke-width:4;stroke-linecap:round}:root{--fm-notify-color: var(--fm-white);--fm-notify-zindex: var(--fm-zindex-5);--fm-notify-info-background: var(--fm-primary-color);--fm-notify-success-background: var(--fm-success-color);--fm-notify-warning-background: var(--fm-warning-color);--fm-notify-error-background: var(--fm-danger-color)}.fm-notify{position:fixed;left:0;top:0;z-index:var(--fm-notify-zindex);display:flex;align-items:center;justify-content:center;width:100%;max-height:100%;padding:8px 16px;box-sizing:border-box;color:var(--fm-notify-color);font-size:14px;line-height:20px;white-space:pre-wrap;text-align:center;word-wrap:break-word;overflow-y:auto}.fm-notify--info{background-color:var(--fm-notify-info-background)}.fm-notify--success{background-color:var(--fm-notify-success-background)}.fm-notify--warning{background-color:var(--fm-notify-warning-background)}.fm-notify--error{background-color:var(--fm-notify-error-background)}:root{--fm-dialog-background: var(--fm-background-2);--fm-dialog-padding-top: 24px;--fm-dialog-padding-left: 16px;--fm-dialog-header-font-size: 17px;--fm-dialog-header-line-height: 24px;--fm-dialog-content-font-size: 15px;--fm-dialog-content-line-height: 20px;--fm-dialog-footer-height: 50px;--fm-border-color: var(--fm-gray-4)}@media screen and (min-width: 375px){.fm-dialog{width:320px}}@media screen and (min-width: 280px) and (max-width: 375px){.fm-dialog{width:240px}}.fm-dialog{display:flex;flex-direction:column;background-color:var(--fm-dialog-background);overflow:hidden}.fm-dialog__header{padding-top:var(--fm-dialog-padding-top);padding-left:var(--fm-dialog-header-padding-left);padding-right:var(--fm-dialog-header-padding-left);font-weight:var(--fm-font-bold-light);font-size:var(--fm-dialog-header-font-size);color:var(--fm-text-color);line-height:var(--fm-dialog-header-line-height);text-align:center}.fm-dialog__content{max-height:70vh;overflow-y:auto}.fm-dialog__content__message{padding:var(--fm-dialog-padding-top) var(--fm-dialog-padding-left);font-size:var(--fm-dialog-content-font-size);line-height:var(--fm-dialog-content-line-height);white-space:pre-wrap;text-align:center;word-wrap:break-word}.fm-dialog__content__message--has-title{padding-top:11px;color:var(--fm-text-color-light)}.fm-dialog__content--prompt{padding:14px}.fm-dialog__content--prompt__input{display:block}.fm-dialog__footer{display:flex;flex-direction:row;align-items:center;border-top:1px solid var(--fm-border-color);position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-dialog__footer{border-top:none}html:not([data-scale]) .fm-dialog__footer:before{content:"";position:absolute;background-color:var(--fm-border-color);display:block;z-index:1;inset:0 auto auto 0;width:100%;height:1px;transform-origin:50% 50%;transform:scaleY(.5)}}.fm-dialog__footer .fm-button{border:0;height:var(--fm-dialog-footer-height);border-right:1px solid var(--fm-border-color);position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-dialog__footer .fm-button{border-right:none}html:not([data-scale]) .fm-dialog__footer .fm-button:after{content:"";position:absolute;background-color:var(--fm-border-color);display:block;z-index:1;inset:0 0 auto auto;width:1px;height:100%;background:var(--fm-border-color);transform-origin:100% 50%;transform:scaleX(.5)}}.fm-dialog__footer .fm-button:last-child{border-right:0}.fm-dialog__footer .fm-button:last-child:after{display:none!important}.fm-dialog__footer .fm-button--default{color:var(--fm-text-color)}.fm-dialog__footer--is-column{flex-direction:column}.fm-dialog__footer--is-column__button{border-top:1px solid var(--fm-border-color);position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-dialog__footer--is-column__button{border-top:none}html:not([data-scale]) .fm-dialog__footer--is-column__button:before{content:"";position:absolute;background-color:var(--fm-border-color);display:block;z-index:1;inset:0 auto auto 0;width:100%;height:1px;transform-origin:50% 50%;transform:scaleY(.5)}}.fm-dialog__footer--is-column__button:first-child{border-top:0}.fm-dialog__footer--is-column__button:first-child:before{display:none!important}.fm-dialog.fm-dialog--relative{position:relative}.fm-dialog.fm-dialog--relative__header{padding-right:40px}.fm-dialog__close{position:absolute;right:16px;top:16px;width:22px;height:22px;line-height:22px;text-align:center}.fm-dialog__close .fm-icon{font-size:15px;color:var(--fm-text-color-2)}:root,:host{--fm-loading-color: var(--fm-gray-5);--fm-loading-text-font-size: 14px;--fm-loading-text-line-height: 1.4}.fm-loading{display:flex;align-items:center;position:relative;color:var(--fm-loading-color)}.fm-loading__text{color:var(--fm-loading-color);font-size:var(--fm-loading-text-font-size);line-height:var(--fm-loading-text-line-height);margin-left:var(--fm-margin-xs)}.fm-loading--vertical{flex-direction:column}.fm-loading--vertical .fm-loading__text{margin-top:var(--fm-margin-xs);margin-left:0}.fm-loading__circular{display:block;animation:fm-rotate 2s linear infinite}.fm-loading__circular circle{animation:fm-circular 1.5s ease-in-out infinite;stroke:currentColor;stroke-width:3;stroke-linecap:round}.fm-loading__spinner{display:block;position:relative;animation:fm-rotate 1s linear infinite;animation-timing-function:steps(12)}.fm-loading__line{position:absolute;top:0;left:0;width:100%;height:100%}.fm-loading__line-inner{display:block;width:2px;height:25%;margin:0 auto;background-color:currentColor;border-radius:40%}.fm-loading__ring{display:block;animation:fm-rotate .75s linear infinite;border:4px solid;border-right-color:transparent;border-radius:50%}@keyframes fm-circular{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40}to{stroke-dasharray:90,150;stroke-dashoffset:-120}}.fm-loading__line--1{transform:rotate(30deg);opacity:1}.fm-loading__line--2{transform:rotate(60deg);opacity:.9375}.fm-loading__line--3{transform:rotate(90deg);opacity:.875}.fm-loading__line--4{transform:rotate(120deg);opacity:.8125}.fm-loading__line--5{transform:rotate(150deg);opacity:.75}.fm-loading__line--6{transform:rotate(180deg);opacity:.6875}.fm-loading__line--7{transform:rotate(210deg);opacity:.625}.fm-loading__line--8{transform:rotate(240deg);opacity:.5625}.fm-loading__line--9{transform:rotate(270deg);opacity:.5}.fm-loading__line--10{transform:rotate(300deg);opacity:.4375}.fm-loading__line--11{transform:rotate(330deg);opacity:.375}.fm-loading__line--12{transform:rotate(360deg);opacity:.3125}:root,:host{--fm-pull-refresh-head-height: 50px;--fm-pull-refresh-head-font-size: var(--fm-font-size-md);--fm-pull-refresh-head-text-color: var(--fm-text-color-light);--fm-pull-refresh-animation-duration: .3s}.fm-pull-refresh{overflow:hidden}.fm-pull-refresh__track{position:relative;height:100%}.fm-pull-refresh__track--not-pulling{transition:transform ease var(--fm-pull-refresh-animation-duration)}.fm-pull-refresh__head{position:absolute;left:0;width:100%;height:var(--fm-pull-refresh-head-height);color:var(--fm-pull-refresh-head-text-color);font-size:var(--fm-pull-refresh-head-font-size);line-height:var(--fm-pull-refresh-head-height);text-align:center;transform:translateY(-100%);display:flex;justify-content:center;align-items:center;flex-direction:column;overflow:hidden}:root,:host{--fm-list-text-color: var(--fm-gray-5);--fm-list-text-font-size: var(--fm-font-size-md, 14px);--fm-list-text-line-height: 50px;--fm-list-loading-icon-size: 16px}.fm-list__loading,.fm-list__error,.fm-list__load-more,.fm-list__finished-info{color:var(--fm-list-text-color);font-size:var(--fm-list-text-font-size);line-height:var(--fm-list-text-line-height);text-align:center}.fm-list__loading-container{display:flex;height:var(--fm-list-text-line-height);justify-content:center;align-items:center}:root,:host{--fm-listview-checkbox-container-width: 40px;--fm-listview-toolbar-height: 42px;--fm-listview-split-line-color: rgb(230, 235, 235);--fm-listview-empty-text-color: var(--fm-gray-5);--fm-listview-empty-text-font-size: var(--fm-font-size-md, 14px);--fm-listview-empty-text-line-height: 50px}.fm-list-view--fill{height:100%;flex-grow:1;flex-shrink:1;display:flex;flex-direction:column;overflow:hidden}.fm-list-view--fill .fm-list-view__track{flex:1 1 0;overflow:auto;-webkit-overflow-scrolling:touch}.fm-list-view--fill .fm-pull-refresh{min-height:100%}.fm-list-view .fm-list{user-select:none;-webkit-user-select:none}.fm-list-view__item{display:flex;position:relative;overflow:hidden}.fm-list-view__item-checker{display:flex;position:absolute;height:100%;width:var(--fm-listview-checkbox-container-width);justify-content:center;align-items:center}.fm-list-view__item-content{flex:1;transform:translate(0)}.fm-list-view__content--split .fm-list-view__item:not(:last-child):not(.fm-list-view__item--child){border-bottom:1px solid var(--fm-listview-split-line-color)}.fm-list-view--multi-select .fm-list-view__item-content{transform:translate(var(--fm-listview-checkbox-container-width))}.fm-list-view__item--group{display:block}.fm-list-view__item-group-header{padding:10px 16px;line-height:20px;font-size:var(--fm-font-size-md);color:var(--fm-gray-5)}.fm-list-view__empty-message{display:block;color:var(--fm-listview-empty-text-color);font-size:var(--fm-listview-empty-text-font-size);line-height:var(--fm-listview-empty-text-line-height);text-align:center}.fm-list-view__item-text{padding:13px 20px;color:var(--fm-gray-7);font-size:var(--fm-font-size)}.fm-list-view__toolbar{display:flex;align-items:center;height:var(--fm-listview-toolbar-height)}.fm-list-view__toolbar-item{flex:1}:root,:host{--fm-swipe-cell-button-text-color: var(--fm-white);--fm-swipe-cell-button-bg-color: var(--fm-gray-4);--fm-swipe-cell-button-font-size: var(--fm-font-size);--fm-swipe-cell-button-icon-size: var(--fm-font-size);--fm-swipe-cell-button-padding: var(--fm-padding-md)}.fm-swipe-cell{position:relative;overflow:hidden}.fm-swipe-cell__wrapper{transition-timing-function:cubic-bezier(.18,.89,.32,1);transition-property:transform}.fm-swipe-cell__left,.fm-swipe-cell__right{position:absolute;top:0;height:100%;display:flex}.fm-swipe-cell__left{left:0;transform:translate3d(-100%,0,0);flex-direction:row-reverse}.fm-swipe-cell__right{right:0;transform:translate3d(100%,0,0)}.fm-swipe-cell__button{display:inline-flex;justify-content:center;align-items:center;height:100%;padding:0 var(--fm-swipe-cell-button-padding);color:var(--fm-swipe-cell-button-text-color);background-color:var(--fm-swipe-cell-button-bg-color)}.fm-swipe-cell__icon{font-size:var(--fm-swipe-cell-button-icon-size)}.fm-swipe-cell__text{font-size:var(--fm-swipe-cell-button-font-size)}.fm-swipe-cell__icon+.fm-swipe-cell__text:not(:empty){margin-left:6px}:root,:host{--fm-action-sheet-max-height: 80%;--fm-action-sheet-border-radius: 12px;--fm-action-sheet-description-color: var(--fm-gray-5);--fm-action-sheet-description-line-height: 22px;--fm-action-sheet-description-font-size: var(--fm-font-size-md);--fm-action-sheet-description-padding: 12px 16px;--fm-action-sheet-item-default-background: var(--fm-background-white);--fm-action-sheet-item-active-background: #f2f3f5;--fm-action-sheet-item-padding: 13px 16px;--fm-action-sheet-item-text-color: #1a1a1a;--fm-action-sheet-item-disabled-text-color: #bdbdbd;--fm-action-sheet-item-subtitle-color: var(--fm-gray-5);--fm-action-sheet-item-icon-size: 18px;--fm-action-sheet-item-icon-margin-right: 8px;--fm-action-sheet-item-title-font-size: var(--fm-font-size-lg);--fm-action-sheet-item-title-line-height: 24px;--fm-action-sheet-item-subtitle-font-size: var(--fm-font-size-sm);--fm-action-sheet-item-subtitle-line-height: 18px;--fm-action-sheet-item-subtitle-margin-top: 2px;--fm-action-sheet-footer-gap-color: #f5f5f5;--fm-action-sheet-divider-color: #e7e7e7;--fm-action-sheet-cancel-height: 48px;--fm-action-sheet-cancel-color: #1a1a1a;--fm-action-sheet-cancel-font-size: var(--fm-font-size-lg);--fm-action-sheet-cancel-font-weight: 500}.fm-action-sheet{display:flex;flex-direction:column;max-height:var(--fm-action-sheet-max-height);overflow:hidden;user-select:none}.fm-action-sheet--round{border-top-left-radius:var(--fm-action-sheet-border-radius);border-top-right-radius:var(--fm-action-sheet-border-radius)}.fm-action-sheet__description{flex-shrink:0;color:var(--fm-action-sheet-description-color);line-height:var(--fm-action-sheet-description-line-height);font-size:var(--fm-action-sheet-description-font-size);text-align:center;padding:var(--fm-action-sheet-description-padding);position:relative}.fm-action-sheet__description--left{text-align:left}.fm-action-sheet__content{flex:1 auto;overflow-y:auto;-webkit-overflow-scrolling:touch}.fm-action-sheet__item,.fm-action-sheet__cancel{background-color:var(--fm-action-sheet-item-default-background)}.fm-action-sheet__item:active,.fm-action-sheet__cancel:active{background-color:var(--fm-action-sheet-item-active-background)}.fm-action-sheet__item{display:flex;position:relative;flex-wrap:wrap;align-items:center;justify-content:center;text-align:center;padding:var(--fm-action-sheet-item-padding);color:var(--fm-action-sheet-item-text-color);cursor:pointer}.fm-action-sheet__item-icon{font-size:var(--fm-action-sheet-item-icon-size);margin-right:var(--fm-action-sheet-item-icon-margin-right)}.fm-action-sheet__item-title{font-size:var(--fm-action-sheet-item-title-font-size);line-height:var(--fm-action-sheet-item-title-line-height)}.fm-action-sheet__item-subtitle{font-size:var(--fm-action-sheet-item-subtitle-font-size);line-height:var(--fm-action-sheet-item-subtitle-line-height);width:100%;margin-top:var(--fm-action-sheet-item-subtitle-margin-top);color:var(--fm-action-sheet-item-subtitle-color);overflow-wrap:break-word}.fm-action-sheet__item--left{text-align:left;justify-content:flex-start}.fm-action-sheet__item--disabled{color:var(--fm-action-sheet-item-disabled-text-color);cursor:not-allowed}.fm-action-sheet__item--disabled:active{background-color:var(--fm-action-sheet-item-default-background)}.fm-action-sheet__description:after,.fm-action-sheet__item:after{content:"";display:block;position:absolute;height:1px;bottom:0;left:0;right:0;transform:scaleY(.5);background-color:var(--fm-action-sheet-divider-color)}.fm-action-sheet__footer-gap{height:8px;background-color:var(--fm-action-sheet-footer-gap-color)}.fm-action-sheet__cancel{display:flex;flex-direction:column;justify-content:center;align-items:center;height:var(--fm-action-sheet-cancel-height);cursor:pointer;color:var(--fm-action-sheet-cancel-color);font-size:var(--fm-action-sheet-cancel-font-size);font-weight:var(--fm-action-sheet-cancel-font-weight)}:root{--fm-tab-bar-item-color: var(--fm-text-color);--fm-tab-bar-item-active-color: var(--fm-primary-color);--fm-tab-bar-item-font-size: 16px}.fm-tab-bar-item{flex:1 0 auto;position:relative;display:inline-flex;align-items:center;justify-content:center;margin:0 12px;line-height:44px}.fm-tab-bar-item--actived{color:var(--fm-tab-bar-item-active-color)}.fm-tab-bar-item--disabled{color:var(--fm-disabled-color)}.fm-tab-bar-item--dot .fm-tab-bar-item__text:after{content:"";position:absolute;top:0;right:0;width:8px;height:8px;background-color:var(--fm-danger-color);border-radius:100%;transform:translate(100%,100%)}.fm-tab-bar-item__text{position:relative;display:flex;justify-content:center;min-width:40px}.fm-tab-bar-item__ink{position:absolute;bottom:0;left:0;right:0;height:4px;background-color:var(--fm-tab-bar-item-active-color);border-radius:2px}.fm-tab-bar-item__badge{position:absolute;top:2px;right:0;padding:0 4px;max-width:28px;font-weight:500;font-size:12px;line-height:14px;border-radius:7px;color:var(--fm-background-white);background-color:var(--fm-danger-color);transform:translate(50%)}.fm-tab-bar-item__icon{position:relative;display:flex;align-items:center;justify-content:center;padding-right:4px}:root{--fm-tab-bar-height: 44px;--fm-tab-bar-background: var(--fm-background-white);--fm-tab-bar-color: var(--fm-text-color);--fm-tab-bar-active-color: var(--fm-primary-color);--fm-tab-bar-font-size: 16px}.fm-tab-bar{position:relative;background:var(--fm-tab-bar-background);color:var(--fm-tab-bar-color);font-size:var(--fm-tab-bar-font-size)}.fm-tab-bar--bottom-line{border-bottom:1px solid #ddd;position:relative}@media (min-resolution: 1dppx){html:not([data-scale]) .fm-tab-bar--bottom-line{border-bottom:none}html:not([data-scale]) .fm-tab-bar--bottom-line:after{content:"";position:absolute;background-color:#ddd;display:block;z-index:1;inset:auto auto 0 0;width:100%;height:1px;transform-origin:50% 100%;transform:scaleY(.5)}}.fm-tab-bar__scroll-wrapper{position:relative;width:100%;overflow:hidden}.fm-tab-bar__list{display:flex;justify-content:space-between;min-width:100%;transition:all .3s cubic-bezier(.17,.89,.45,1)}.fm-tab-bar__ink{position:absolute;bottom:0;left:0;display:block;height:4px;background-color:var(--fm-tab-bar-active-color);transition:all var(--fm-duration-base);border-radius:2px}.fm-tab-bar__ink--disabled{background-color:var(--fm-disabled-color)}.fm-tabs{overflow:hidden}.fm-tabs__content{display:flex}.fm-tab{display:block;flex-shrink:0;width:100%;height:100%;overflow:auto;word-break:break-all}.fm-tab--collapse{height:0;overflow:visible}:root{--fm-tag-padding: 0 6px;--fm-tag-height: 18px;--fm-tag-font-size: 12px;--fm-tag-border-radius: 2px;--fm-tag-color: var(--fm-white)}.fm-tag{position:relative;display:inline-flex;align-items:center;white-space:nowrap;padding:0 4px;color:var(--fm-tag-color);font-size:var(--fm-tag-font-size);line-height:var(--fm-tag-height);border-radius:var(--fm-tag-border-radius)}.fm-tag--primary{background-color:var(--fm-primary-color)}.fm-tag--success{background-color:var(--fm-success-color)}.fm-tag--danger{background-color:var(--fm-danger-color)}.fm-tag--warning{background-color:var(--fm-warning-color)}.fm-tag--plain{background-color:var(--fm-white)}.fm-tag--plain.fm-tag--primary{border:1px solid var(--fm-primary-color);color:var(--fm-primary-color)}.fm-tag--plain.fm-tag--success{border:1px solid var(--fm-success-color);color:var(--fm-success-color)}.fm-tag--plain.fm-tag--warning{border:1px solid var(--fm-warning-color);color:var(--fm-warning-color)}.fm-tag--plain.fm-tag--danger{border:1px solid var(--fm-danger-color);color:var(--fm-danger-color)}.fm-tag--medium{padding:2px 6px}.fm-tag--large{padding:4px 8px;font-size:14px;border-radius:4px}.fm-tag--round{border-radius:100px}.fm-tag--mark{border-radius:0 100px 100px 0}.fm-tag__close{font-size:8px;margin-left:4px}.fm-tag--large .fm-tag__close{font-size:10px}:root{--fm-picker-background: var(--fm-white);--fm-picker-toolbar-height: 44px}.fm-picker{position:relative;background-color:var(--fm-picker-background);user-select:none}.fm-picker__toolbar{display:flex;justify-content:space-between;align-items:center;height:var(--fm-picker-toolbar-height)}.fm-picker__toolbar-left,.fm-picker__toolbar-right{padding:0 16px}.fm-picker__toolbar-title{font-weight:500;font-size:16px;max-width:50%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fm-picker__content{position:relative;display:flex;cursor:grab}.fm-picker__columns{display:flex;flex:1;overflow:hidden}.fm-picker__column{flex:1}.fm-picker__column-item{display:flex;align-items:center;justify-content:center;height:44px}.fm-picker__mask{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;background-image:linear-gradient(180deg,#ffffffe6,#fff6),linear-gradient(0deg,#ffffffe6,#fff6);background-repeat:no-repeat;background-position:top,bottom;transform:translateZ(0);pointer-events:none}.fm-picker__frame{position:absolute;top:50%;left:16px;right:16px;height:88px;z-index:2;pointer-events:none;border-width:1px 0;border-style:solid;border-color:#ebedf0;transform:translateY(-50%) scaleY(.5)}.fm-picker-group__header{text-align:left}.fm-picker-group__toolbar{display:flex;justify-content:space-between;align-items:center;height:var(--fm-picker-toolbar-height)}.fm-picker-group__toolbar-left,.fm-picker-group__toolbar-right{padding:0 16px}.fm-picker-group__toolbar-title{font-weight:500;font-size:16px;max-width:50%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fm-picker-group__tab-bar{display:inline-block}.fm-page-container{flex:1;display:flex;flex-direction:column;background:#f9fafb;overflow:hidden;-webkit-overflow-scrolling:auto;position:absolute;inset:0}.fm-page-container .drag-container{display:inherit;flex-direction:inherit;flex-shrink:1;flex-grow:1;flex-basis:0%;flex-wrap:inherit;justify-content:inherit;align-items:inherit;width:100%;overflow:inherit}.fm-page-body-container{flex-basis:0;flex-shrink:1;flex-grow:1;padding-bottom:12px;overflow:auto;display:flex;flex-direction:column}.fm-page-header-container{flex-shrink:0}.fm-page-footer-container{background-color:#fff}.fm-float-container{position:absolute!important;bottom:60px;right:30px} diff --git a/packages/designer/src/app-providers.ts b/packages/designer/src/app-providers.ts index b1e68e40518223b91df7ae60f821710e1d5c21fc..ffd9aed57029ec6f8cd4481c1ec81a94cf2e8c5a 100644 --- a/packages/designer/src/app-providers.ts +++ b/packages/designer/src/app-providers.ts @@ -6,9 +6,13 @@ import { MetadataPathToken, MetadataServiceToken } from "./components/types"; import { LookupFieldSelectorService, LookupSchemaService } from "./components/composition/schema-repository"; import { ControllerSelectorSchemaService } from "./components/composition/schema-repository/controller/controller-selector.service"; import { FormSelectorSchemaService } from "./components/composition/schema-repository/form/form-selector.service"; +import { useDesignerContext } from "./components/composition/designer-context/use-designer-context"; + +const designerContext = useDesignerContext(); export default { install(app: App): void { + app.provide('designerContext', designerContext); app.provide(F_MODAL_SERVICE_TOKEN, new FModalService(app)); app.provide('FLoadingService', FLoadingService); @@ -23,7 +27,7 @@ export default { app.provide(LookupSchemaRepositoryToken, new LookupSchemaService(metadataService)); app.provide(FieldSelectorRepositoryToken, new LookupFieldSelectorService(metadataService)); app.provide(F_NOTIFY_SERVICE_TOKEN, new FNotifyService()); - app.provide(ControllerSchemaRepositorySymbol, new ControllerSelectorSchemaService(metadataService)); + app.provide(ControllerSchemaRepositorySymbol, new ControllerSelectorSchemaService(metadataService,designerContext)); app.provide(FormSchemaRepositorySymbol, new FormSelectorSchemaService(metadataService)); app.directive('tooltip', FTooltipDirective); diff --git a/packages/designer/src/components/components/form-designer/form-designer.component.tsx b/packages/designer/src/components/components/form-designer/form-designer.component.tsx index c880dcd3bb5e306df3fc647525cd7d8cd2384c31..96f444f8839e37fe66a5bd09d654415122b92267 100644 --- a/packages/designer/src/components/components/form-designer/form-designer.component.tsx +++ b/packages/designer/src/components/components/form-designer/form-designer.component.tsx @@ -1,5 +1,5 @@ import { Ref, computed, defineComponent, inject, onMounted, provide, ref, nextTick } from "vue"; -import { ComponentSchema, DesignerComponentInstance, FDesignerCanvas, FTabs, FTabPage, propertyConfigSchemaMap, FSplitter, FSplitterPane, FDesignerToolbox, FPropertyPanel, FDesignerOutline } from "@farris/ui-vue/components"; +import { ComponentSchema, DesignerComponentInstance, FDesignerCanvas, FTabs, FTabPage, propertyConfigSchemaMapForDesigner, FSplitter, FSplitterPane, FDesignerToolbox, FPropertyPanel, FDesignerOutline } from "@farris/ui-vue/components"; import { FormDesignerProps, formDesignerProps } from "./form-designer.props"; import { useComponentSchemaService } from '../../composition/component-schema.service'; import MonacoEditor from '../monaco-editor/monaco-editor.component'; @@ -9,24 +9,26 @@ import { afterPropeControlPropertyChangedService } from "../../composition/contr import { UseDesignViewModel, UseFormSchema, UseSchemaService } from "../../types"; import FCustomClassEditor from './components/custom-class-editor/custom-class-editor.component'; import FExternalComponentPanpel from './components/external-component-panpel/external-component-panpel.component'; +import { UseDesignerContext } from "../../types/designer-context"; + export default defineComponent({ name: 'FFormDesigner', props: formDesignerProps, emits: [], setup(props: FormDesignerProps, context) { + const designerContext = inject('designerContext') as UseDesignerContext; const propertyPanelInstance = ref(); const schema = ref(props.schema); const componentSchema = schema.value.module ? ref(schema.value.module.components[0]) : ref(schema.value); - const componentId = ref(componentSchema['id'] || 'root-component'); + const componentId = ref(componentSchema.value['id'] || 'root-component'); const dragulaCompostion = ref(); const fillTabs = ref(true); const controlTreeRef = ref(); const entityTreeRef = ref(); const monacoEditorRef = ref(); const customClassEditorRef = ref(); - - + const { toolboxItems, componentsToRegister, designerMode} = designerContext; function onCanvasInitialized(dragula: any) { dragulaCompostion.value = dragula; } @@ -71,6 +73,9 @@ export default defineComponent({ if (changeObject.needRefreshEntityTree && entityTreeRef.value && entityTreeRef.value.refreshEntityTree) { entityTreeRef.value.refreshEntityTree(); } + if (changeObject.needChangeCanvas && canvasRef.value.changeCanvas) { + canvasRef.value.changeCanvas(); + } const afterPropeControlPropertyChanged = afterPropeControlPropertyChangedService(useFormSchema, designViewModelUtils, schemaUtil); afterPropeControlPropertyChanged.afterPropertyChanged(event); @@ -129,8 +134,25 @@ export default defineComponent({ }; }); - propertyConfigSchemaMap['Module'] = modulePropertyConfig; - function onOutlineChanged(selectionSchema: any) { + propertyConfigSchemaMapForDesigner['Module'] = modulePropertyConfig; + + /** + * 切换不同的页面 + * @param selectionNode + * @returns + */ + function changePageComponent(selectionNode: any) { + const isPageChanged = selectionNode.componentId && componentId.value !== selectionNode.componentId; + if (isPageChanged) { + componentId.value = selectionNode.componentId; + const selectPageComponent = useFormSchema.getComponentById(componentId.value); + componentSchema.value = selectPageComponent; + } + } + + function onOutlineChanged(selectionNode: any) { + const selectionSchema = selectionNode.rawSchema; + if (selectionSchema?.type === 'Module') { propertyName.value = 'Module'; propertyPanelInstance?.value?.updateDesignerItem(null, selectionSchema.id); @@ -148,6 +170,10 @@ export default defineComponent({ if (activeDesignerView.value === 'formDesignerCode' && selectionSchema) { monacoEditorRef.value?.setPosition(selectionSchema.id); } + + // 切换了页面 + changePageComponent(selectionNode); + } function reloadPropertyPanel() { @@ -193,7 +219,7 @@ export default defineComponent({ - + @@ -212,6 +238,8 @@ export default defineComponent({ onCanvasChanged={onCanvasChanged} componentId={componentId.value} onDragEnd={onCanvasDragEnd} + components={componentsToRegister} + canvasMode={designerMode} > {/* diff --git a/packages/designer/src/components/components/view-model-designer/method-manager/composition/use-view-model-list.ts b/packages/designer/src/components/components/view-model-designer/method-manager/composition/use-view-model-list.ts index a3f1cb54b89ea1de2de5e3b65b33c3e3eb752576..44633387a58c372a735684f96a477689d48a3ed4 100644 --- a/packages/designer/src/components/components/view-model-designer/method-manager/composition/use-view-model-list.ts +++ b/packages/designer/src/components/components/view-model-designer/method-manager/composition/use-view-model-list.ts @@ -1,6 +1,7 @@ import { inject } from 'vue'; import { ComponentType, FormViewModel, UseFormSchema } from '../../../../types'; import { useViewModelName } from './use-view-model-name'; +import { UseDesignerContext } from '../../../../../components/types/designer-context'; /** * 按照组件引用顺序构造视图模型列表 @@ -10,6 +11,8 @@ export function useViewModelNavigation() { const viewModelNameBuilder = useViewModelName(); let componentListInModalFrame: any[] = []; const useFormSchema = inject('useFormSchema') as UseFormSchema; + const designerContext = inject('designerContext') as UseDesignerContext; + const formSchema = useFormSchema.getFormSchema(); function getAllComponentIdsBySort(componentSchema: any, componentIdList: string[], isInModalFrame = false) { @@ -53,19 +56,24 @@ export function useViewModelNavigation() { * 按照组件引用的顺序排列ViewModel节点 */ function sortViewModels() { - const rootComponent = useFormSchema.getComponentById('root-component'); - if (!rootComponent) { + const pageComponents = designerContext.getPageComponents(useFormSchema); + + if (!pageComponents) { return []; } const componentIdList: string[] = []; - getAllComponentIdsBySort(rootComponent, componentIdList); + const sortedViewModels: FormViewModel[] = []; + + pageComponents.forEach(pageComponent => { + getAllComponentIdsBySort(pageComponent, componentIdList); + + const pageViewModel = useFormSchema.getViewModelById(pageComponent.viewModel); + if (pageViewModel) { + sortedViewModels.push(pageViewModel); + } + }) const components = formSchema.module.components.filter(component => component.componentType !== ComponentType.Frame); - const sortedViewModels: FormViewModel[] = []; - const rootViewModel = useFormSchema.getViewModelById(rootComponent.viewModel); - if (rootViewModel) { - sortedViewModels.push(rootViewModel); - } componentIdList.forEach(componentId => { const targetComponent = components.find(component => component.id === componentId); if (targetComponent) { diff --git a/packages/designer/src/components/composition/command/supported-controller.ts b/packages/designer/src/components/composition/command/supported-controller.ts index 31ee3b95cf0efb2da8326a28c73fc4d876a04270..760577e6e0aeaaba7a890bbfb07fed94301e8663 100644 --- a/packages/designer/src/components/composition/command/supported-controller.ts +++ b/packages/designer/src/components/composition/command/supported-controller.ts @@ -1,438 +1,16 @@ -const supportedControllers = { - "d7de1993-d500-44fd-9922-43c78d477aa3": [ - { - "id": "dba10520-f564-31a4-13ac-f07709402304", - "code": "LoadNavTree" - }, - { - "id": "b9241e0d-90d1-72e7-c9b6-8f08caaef8ad", - "code": "LoadSubList" - }, - { - "id": "ae60fedd-e0e7-ac7a-eaa9-430833dbefc7", - "code": "RouteToAdd" - }, - { - "id": "8b6f29b4-7326-f9f8-0625-3954a71f3595", - "code": "RouteToEdit" - }, - { - "id": "74cda30e-6abb-5269-64a4-0f43c189ed74", - "code": "RouteToView" - }, - { - "id": "4c183907-66c4-1b02-c8ab-aa13a4efc8f3", - "code": "Remove" - }, - { - "id": "294afc8c-bea9-658c-81f0-42982f8c7eb0", - "code": "Close" - } - ], - "8172a979-2c80-4637-ace7-b13074d3f393": [ - { - "id": "0c67fafb-3bb7-d0a5-d546-3dae63434212", - "code": "Load" - }, - { - "id": "05c445e5-4e18-f4e6-2dc8-997228dc36a7", - "code": "LoadAndAdd" - }, - { - "id": "052104fd-3f13-0738-058e-4945b5f95c27", - "code": "LoadAndView" - }, - { - "id": "2ecf6524-ffc0-ada5-2765-2103c597f880", - "code": "LoadAndEdit" - }, - { - "id": "363d6a62-afb8-6789-39ef-cae0a5c4ae9d", - "code": "Add" - }, - { - "id": "63bc76df-1626-eff7-ab55-03ed9b44750d", - "code": "Edit" - }, - { - "id": "bd081bfc-7ce8-979e-e54c-3b01fc8ffc96", - "code": "Cancel" - }, - { - "id": "c22ff5a0-cfeb-aab1-ac01-937cfcd80c6a", - "code": "Save" - }, - { - "id": "eeb436cf-6684-874f-3ca7-d42aec83730d", - "code": "Close" - }, - { - "id": "6f987222-ebe2-0f3c-1594-a12408b22801", - "code": "AddItem" - }, - { - "id": "0cdeddcc-8332-f13f-be96-b5eeac84a334", - "code": "RemoveItem" - }, - { - "id": "af181469-5bda-7c9f-e187-dc173cfd7356", - "code": "LoadAndCascadeAdd" - }, - { - "id": "89904e71-5b79-9caf-b9d6-77e878cc1552", - "code": "cascadeAdd" - } - ], - "26436aa8-88a7-4aee-bf0b-9843c1e8afbf": [ - { - "id": "f7dd2c84-7abd-d4bf-6b31-71d96035c034", - "code": "LoadNavList" - }, - { - "id": "e8e6433a-7c00-1773-0f0d-b4f9c3060e56", - "code": "LoadSubList" - }, - { - "id": "59858a08-f940-413c-4717-2c65212c9303", - "code": "RouteToAdd" - }, - { - "id": "b448888e-7200-e9d6-ec51-23257a61904f", - "code": "RouteToEdit" - }, - { - "id": "ea5e9181-70e6-5344-536f-e586f0f1c00a", - "code": "RouteToView" - }, - { - "id": "5d2c531e-f0f4-7330-e627-52745352117d", - "code": "Remove" - }, - { - "id": "0f69d3b4-a81e-b98f-d7a1-e18810dbc98f", - "code": "Close" - }, - { - "id": "c0a61c65-f3f2-95f3-2672-aa52d18ad047", - "code": "ChangePage" - } - ], - "eb07c2e4-7cc1-4d95-aad0-410823006d71": [ - { - "id": "acd815d6-a80a-e617-962f-37b445a15fb1", - "code": "execute" - } - ], - "70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72": [ - { - "id": "86c9f281-e5bc-5d5c-1b86-d1e17ab2e850", - "code": "Load" - }, - { - "id": "0430f234-634a-0b1d-878f-706d06c53948", - "code": "Remove" - }, - { - "id": "b7da52d1-761c-6263-08d4-30a0061c922c", - "code": "Add" - }, - { - "id": "1d2b8b9b-7a7d-f807-6e51-9ea6e945635a", - "code": "View" - }, - { - "id": "405ec4c7-21f6-bffb-a2d0-edbeb47a042c", - "code": "Edit" - }, - { - "id": "b5103abd-bd9c-2f56-9b56-68c94959f757", - "code": "Close" - }, - { - "id": "e86b4c09-d3d7-0f5a-1d03-17d4da6603e4", - "code": "RemoveRows" - }, - { - "id": "62d673bf-6219-a55b-1080-a4116ca1058c", - "code": "ChangePage" - }, - { - "id": "d7c77f23-fca6-8a90-8e20-8f84f5709663", - "code": "refresh" - } - ], - "d7ce1ba6-49c7-4a27-805f-f78f42e72725": [ - { - "id": "f80e026b-bd9b-002b-d2aa-52c44a633bec", - "code": "Load" - }, - { - "id": "8a19b303-4e75-c267-e42a-b56d059577a9", - "code": "Add" - }, - { - "id": "79aa9a7b-1189-8cba-dcad-2089d95aee72", - "code": "Edit" - }, - { - "id": "8253428a-0287-8390-0ea1-a31eefa1a057", - "code": "Save" - }, - { - "id": "6118693c-9d5c-f401-7101-8344744183f2", - "code": "Cancel" - }, - { - "id": "a82e6e67-ff48-05ce-a780-26a10b83253b", - "code": "Remove" - }, - { - "id": "8034cae9-ecd7-e6ab-22c2-0cdf7cfd536f", - "code": "Close" - }, - { - "id": "6bf1ed43-a493-f2dd-de19-77ebfb79916a", - "code": "ChangePage" - }, - { - "id": "dfd86e25-5cfa-313c-617a-8fd5e2eb8fc9", - "code": "RemoveRows" - } - ], - "45be24f9-c1f7-44f7-b447-fe2ada458a61": [ - { - "id": "17021da1-61a5-a90a-072c-6dda3bad01a7", - "code": "LoadList" - }, - { - "id": "5fb563aa-e860-b439-bf64-39c9cdc341db", - "code": "LoadCard" - }, - { - "id": "90603e99-8f81-968e-ca25-a6017fd874d5", - "code": "Add" - }, - { - "id": "87d3f0aa-f087-c806-466f-cda147730eb0", - "code": "Edit" - }, - { - "id": "fa100da6-83a0-e552-2aa9-415c8c27c3dd", - "code": "Save" - }, - { - "id": "1a373dee-261d-0824-9c99-a158eb376864", - "code": "Cancel" - }, - { - "id": "f9f05646-5c0d-c5d3-5218-d9acf49ebe16", - "code": "Close" - }, - { - "id": "250cd2a2-9995-4c01-64aa-5029afba08ca", - "code": "AddItem" - }, - { - "id": "a2c06958-29b1-0582-5f3e-c3cfcc741f8f", - "code": "RemoveItem" - }, - { - "id": "1425afaa-d91a-9e64-39cd-c4a0bb98e336", - "code": "ChangePage" - }, - { - "id": "1cde1e30-3c4e-2695-e2b6-7a0229368a58", - "code": "Remove" - } - ], - "7c48ef46-339c-42d4-8365-a21236c63044": [ - { - "id": "e573d6a2-8261-9ad4-c9f1-2e59af53302d", - "code": "loadList" - }, - { - "id": "d1054fa5-d18e-c22c-ed3f-2f13b4692702", - "code": "loadCard" - }, - { - "id": "6b9556d9-f510-2484-07b8-e1e190f03169", - "code": "add" - }, - { - "id": "ca451c36-4ab8-5576-545f-0bd13c1cb320", - "code": "edit" - }, - { - "id": "dbc290b7-8f64-1ce3-862f-d63e4c6db956", - "code": "save" - }, - { - "id": "5c3f88c9-52b2-bddb-b4ab-a975ec0e48d7", - "code": "cancel" - }, - { - "id": "3e722416-f1e4-d795-0194-0b876adfa253", - "code": "close" - }, - { - "id": "aae5dda3-7941-6d19-dab5-c4126d20e457", - "code": "remove" - }, - { - "id": "40302ced-33be-8d2f-9c4b-023b90351206", - "code": "changePage" - } - ], - "8fe977a1-2b32-4f0f-a6b3-2657c4d03574": [ - { - "id": "0970ba99-fe9f-c08c-81bb-60841ca94b8f", - "code": "LoadTree" - }, - { - "id": "ecd91cda-e8c0-bc59-b454-78b4027b9f9b", - "code": "LoadCard" - }, - { - "id": "57f3d943-2daf-39aa-5087-58efe7708d38", - "code": "AddSibling" - }, - { - "id": "e470716b-a104-5637-357f-ae6fa92cba05", - "code": "AddChild" - }, - { - "id": "963ed4ff-b425-d832-e887-3968feae44b4", - "code": "Remove" - }, - { - "id": "aeb647c7-8a0a-e02b-9c7a-8fd785da4b63", - "code": "Edit" - }, - { - "id": "531835dc-7c8a-5f52-7912-2c69744f8496", - "code": "Save" - }, - { - "id": "0a2a4b5c-3624-9d55-417e-10247271b556", - "code": "Cancel" - }, - { - "id": "21b0c3af-3caf-b11d-2360-d9af20016501", - "code": "AddItem" - }, - { - "id": "113f1d77-65a4-63bf-3973-80dd15f294d1", - "code": "RemoveItem" - }, - { - "id": "52334335-4e0f-dc9d-2bff-fb09cd479dcf", - "code": "Close" - } - ], - "54bddc89-5f7e-4b91-9c45-80dd6606cfe9": [ - { - "id": "92cd8b0e-4d95-3976-f0aa-c4a4cde1a60b", - "code": "Filter" - } - ], - "26e6016a-ef26-4682-bcdb-84114e934696": [{ - id: "062fa90d-76c1-8e99-5931-9aa0fa60e25d", - code: "openDialog" - }, { - id: "70582221-f092-9809-85ff-17c01b0f4ee9", - code: "openApp" - } - ], - "9280ec35-9194-4c8c-9020-37329f064876": [{ - id: "eab03d67-c390-2e2e-e252-99446062d76f", - code: "getSlimBillCreationProcessEntityExById" - }, { - id: "42079fe1-c0ff-7457-ba94-c9cb38975d5a", - code: "getFormSettingsById" - }, { - id: "cdf4352a-fd35-ff71-963e-10b3c079bd0f", - code: "executeBillCreationProcess" - }, { - id: "30ddac60-12cc-a3c0-ca68-3bde93247313", - code: "createEntityDatas" - }, { - id: "9d72dad6-2f5d-dd60-b064-16d0f993e9a2", - code: "updateEntityDatas" - }, { - id: "1a57e83b-8c27-246d-aa23-6bcfe6dce064", - code: "pushTaskCenter" - }, { - id: "93358329-127c-a470-6893-74f3c30ef3b8", - code: "getCreationResultById" - }, { - id: "27f7cfd4-a916-d2db-4b08-f05d1d28e7a9", - code: "addFormBillCreationProcessExecutorResult" - } - ], - "9bb60b70-6653-430f-a88a-768cc8204f85": [{ - id: "694a8da6-181a-76bf-17e3-ebc638c1e3be", - code: "pushByCreationProcessId" - }, { - id: "65f76fe3-ca5b-8aed-85ad-4a922d699012", - code: "openBillCreationProcessSelector4Push" - }, { - id: "ef5be4c9-9e0b-ad6d-be04-d8512a36439d", - code: "openBillCreationProcessSelector4SpecificPush" - }, { - id: "106c22a1-9972-1de7-381c-f2f19f543ecb", - code: "openTargetApp" - }, { - id: "082b705e-f43b-3ab2-257f-0d990ae82709", - code: "pushBySourceCmId" - }, { - id: "91963fe4-cb21-2eb9-0e7d-c7731d723837", - code: "pushBySourceCmIdAndTargetCmId" - } - ], - "eae0e38a-9456-4186-af17-f8113b369989": [{ - id: "57e67070-efa9-8988-5bf0-c8b5d5eb9618", - code: "bifLoad" - }, { - id: "9437aa86-1100-0f60-cded-016116c190bb", - code: "referByCreationProcessId" - }, { - id: "81f7d111-903a-180b-5157-d8c4271c47e3", - code: "openBillCreationProcessSelector4Pull" - }, { - id: "1f012cd9-483a-b93b-eee4-5256e1579d08", - code: "openBillCreationProcessSelector4SpecificPull" - }, { - id: "2a1f1c6d-569d-e1d6-04da-798b1df3ddc9", - code: "openSourceDataSelector4Pull" - }, { - id: "fc0be3b1-0273-1c84-a872-69bb1362b15e", - code: "getCreationResult" - }, { - id: "dd847401-5e8c-c0e0-7465-5cb2c50652c2", - code: "referByTargetCmId" - }, { - id: "64a9ce2a-4586-cf2f-22d2-8338b67119e0", - code: "referBySourceCmIdAndTargetCmId" - } - ], - "824361ac-8baf-4742-8843-ddab5182a342": [{ - id: "7a71f224-0465-4bda-b507-6bee22a44c00", - code: "startProcess" - }, { - id: "852cac4c-2689-42bb-a5c4-71bb16b327c0", - code: "viewProcessInstance" - } - ] -}; +import { useDesignerContext } from "../designer-context/use-designer-context"; + +export function getAllSupportedControllers() { + const designerContext = useDesignerContext(); + return designerContext.supportedControllers; +} export function getSupportedControllerMethods(controllerId, commandList) { if (!controllerId || !commandList) { return []; } + const supportedControllers = getAllSupportedControllers(); const supportedCommands = supportedControllers[controllerId] || []; const supportedCommandIds = supportedCommands.map(command => command.id); return commandList.filter(command => supportedCommandIds.includes(command.Id)); } -export function getAllSupportedControllers() { - return supportedControllers; -} diff --git a/packages/designer/src/components/composition/command/supported-controllers/mobile-supported-controller.json b/packages/designer/src/components/composition/command/supported-controllers/mobile-supported-controller.json new file mode 100644 index 0000000000000000000000000000000000000000..e1c6d867ea6f6b6125b59f666eaad1f08e8bf33c --- /dev/null +++ b/packages/designer/src/components/composition/command/supported-controllers/mobile-supported-controller.json @@ -0,0 +1,282 @@ +{ + "9ef56595-7cb7-4bbe-8f64-c6efcb7b1f9d": [ + { + "id": "faa47af6-1354-5139-2849-2f676b4e0c19", + "code": "Create" + }, + { + "id": "2df293ac-eab4-065c-38be-16d1427281e3", + "code": "CreateByPath" + }, + { + "id": "77ab0b98-2cc1-dcbc-6e21-16552efeea88", + "code": "Append" + } + ], + "0a68799b-48c6-4c9f-b0d7-140683c62b58": [ + { + "id": "06351c11-ec4b-f7b0-d9b4-e8bca9202b86", + "code": "LoadForList" + }, + { + "id": "cb7f4216-0eb4-26a0-80b5-a38448e393c1", + "code": "LoadForCard" + }, + { + "id": "67edc617-d63a-b4f5-cdc7-4adba1b6e48b", + "code": "LoadAndAddForCard" + }, + { + "id": "33e538a8-717d-00ad-4cb6-a575f4b151c7", + "code": "LoadAndEditForCard" + }, + { + "id": "d868341e-5eff-2a65-ba96-8b4fe5b243d7", + "code": "LoadAndViewForCard" + }, + { + "id": "afc70350-24fc-9879-9505-689f57575ec2", + "code": "LoadAndAddForChildCard" + }, + { + "id": "4a7b5ccb-f61a-ac4f-e308-c00f6b52860b", + "code": "LoadAndEditForChildCard" + }, + { + "id": "9272925f-38d0-d814-2161-605f75240169", + "code": "LoadAndViewForChildCard" + } + ], + "4ed10691-451e-4dd2-821a-0d2421e7c334": [ + { + "id": "ff453ad8-cd6a-2f01-4e94-d0d382f6f429", + "code": "View" + }, + { + "id": "1a6adc1d-bd2e-b8c3-1e01-c4c6e0803659", + "code": "ViewByPath" + } + ], + "05592163-fd45-474e-b0ab-61d7dc02e5c0": [ + { + "id": "d5b847bd-ceb3-1b27-ed7f-b6b1e38088cd", + "code": "Cancel" + } + ], + "f863c66a-bf93-4d1f-9f99-bcd76009609d": [ + { + "id": "129fb301-123d-6011-755d-c1aad5bf1dd3", + "code": "SaveForCard" + }, + { + "id": "2ade863f-4b38-7d2b-ca9f-87f1e18d8692", + "code": "SaveForChildCard" + }, + { + "id": "f7ebeab7-0481-041a-2cc4-d524840c6468", + "code": "SaveAndGoBackForChildCard" + }, + { + "id": "7eab8d99-4698-c0d4-4d2b-08bf724ed439", + "code": "Save" + }, + { + "id": "55eb3067-d220-56dd-41b3-2228db302ae0", + "code": "SaveAndValidateDataForCard" + } + ], + "f458e095-a3c6-43e8-a95b-fc886f6f619e": [ + { + "id": "b0dfb230-7548-c4c7-66db-370cf5e98ee8", + "code": "Edit" + }, + { + "id": "aaf37f29-c5a4-5571-473c-1e8a252d0782", + "code": "EditByPath" + } + ], + "dab6b7f1-f56f-490a-879c-3d74232cd3ba": [ + { + "id": "eca45728-53c9-ca70-14ca-ec8eb468ee44", + "code": "RemoveById" + }, + { + "id": "6036c9c0-1ee6-ab06-e311-78f5becca6b4", + "code": "RemoveByIds" + }, + { + "id": "a35467a1-4ca7-5655-cd2a-18ce42a3097a", + "code": "RemoveByPathAndId" + } + ], + "eae5387b-042d-45bf-93fa-f2c8085e9e5d": [ + { + "id": "f7bd5f2f-abc8-9fd4-35df-a9199b47a434", + "code": "Update" + } + ], + "910661bd-963a-4287-aa32-441c95b8720f": [ + { + "id": "973bb999-b8dc-0ff5-0ba1-5cd7b816eba9", + "code": "Navigate" + }, + { + "id": "4dd30b6a-f0d7-0799-7c04-593e5b71fd7b", + "code": "NavigateForRtc" + }, + { + "id": "9dca239c-9153-70f9-e522-5ba2c384aa4f", + "code": "GoBack" + }, + { + "id": "632f46ae-620e-3bb7-a75e-c43473624c49", + "code": "GoBackAndCheck" + }, + { + "id": "34c9cb64-0ea0-f483-2d51-c36ff0ee6cb2", + "code": "GoBackForChildCard" + }, + { + "id": "9740b808-9900-f494-516c-08e89640f5af", + "code": "CloseWindow" + }, + { + "id": "66371216-60d9-f2c3-734e-6b56b6e71d27", + "code": "NavigateAndCheck" + }, + { + "id": "b0d557ac-1ee8-8afe-73ea-006c43bd10d1", + "code": "NavigateForChildCard" + } + ], + "91cc23fb-2ecf-418b-9700-99469eab2e84": [ + { + "id": "0fcae913-ce17-a5ba-2d4a-99de7e92a4b4", + "code": "SubmitApprove" + }, + { + "id": "f1229a4f-ecfc-5eda-e870-e50a5fc69a96", + "code": "SaveAndSubmit" + }, + { + "id": "d59bbde0-d2a6-9e6b-0aa7-7a9a47472e48", + "code": "CancelSubmit" + }, + { + "id": "1eda006d-5b2d-e3ff-21a7-061eba33ac30", + "code": "SubmitWithBizDefKey" + }, + { + "id": "fd018acf-f6d0-2ef2-335f-a39c955f2c67", + "code": "CancelSubmitWithDataId" + }, + { + "id": "809b783b-38d3-e70a-64f4-95bc80955cc2", + "code": "BatchSubmitWithBizDefKey" + }, + { + "id": "2daf7893-a636-dd79-a26e-80fdd6a19b7c", + "code": "BatchCancelSubmitWithDataId" + }, + { + "id": "171df093-e755-59f1-319b-bd51cfb8a38f", + "code": "ChildSubmit" + }, + { + "id": "175197fd-6064-697c-d6ee-d90e9fe6ecc7", + "code": "ChildCancelSubmit" + }, + { + "id": "3abbaf6f-2644-2e2e-2bd6-2d04809ec594", + "code": "ChildBatchSubmit" + }, + { + "id": "50283e79-e71b-8429-98db-1fe2d919eb0c", + "code": "ChildBatchCancelSubmit" + } + ], + "ad4b014c-ff01-4bb0-8b3a-cb5e7dd2f8ea": [ + { + "id": "f1925f3d-e442-2010-f441-cb7c6d5c0e49", + "code": "uploadAndUpdateRow" + }, + { + "id": "cd84830a-e9aa-ccbf-7417-dac561df7828", + "code": "uploadAndBatchAddRows" + }, + { + "id": "32d549ab-9f9c-1427-7aaf-f3e9c50de517", + "code": "removeAttachmentRows" + }, + { + "id": "23ca8283-05ba-448e-809b-427ef90ffdc2", + "code": "updateAttachmentField" + }, + { + "id": "8c0c6bc3-1a4b-4f17-95e4-91a7b14f617c", + "code": "clearAttachmentField" + } + ], + "82cebb17-9f81-40be-86c3-389c5912bde7": [ + { + "id": "4d2d6302-6891-f7c2-116a-f29f059d1dd4", + "code": "ExecuteAction" + } + ], + "f8149a59-0133-49cb-8793-1eacbdc357bd": [ + { + "id": "e8938f1c-0e85-4a65-bf9f-f3e7a8e719b5", + "code": "AddComment" + }, + { + "id": "141eabe0-0792-6b62-18df-e51d1b4629fc", + "code": "QueryInitComments" + }, + { + "id": "37030d87-8eb1-cccd-c895-638b2b8bfca4", + "code": "SetReplyUser" + }, + { + "id": "d2ba691d-8121-166d-52d3-dbc365624313", + "code": "registerBeforeGetData" + } + ], + "2051ecc9-0c92-4d26-99b9-24361b2a2335": [ + { + "id": "d2124707-ecf8-b5df-5f71-acd81f981929", + "code": "SetLookupCustomData" + } + ], + "cf5e568a-5243-4539-94ea-e195eb4d6736": [ + { + "id": "e875be9f-07b8-b8ac-e20b-53e6b3e7894d", + "code": "LoadPage" + }, + { + "id": "98b8d9a5-dc18-77e8-7bdf-7ea191c6bc8d", + "code": "LoadPageForList" + }, + { + "id": "dd80df23-0cd7-b11c-1fa5-df8a8847b81b", + "code": "LoadPageForCard" + }, + { + "id": "54f3153f-e646-e185-b403-5467b9984a78", + "code": "LoadPageForChildCard" + }, + { + "id": "6441c6c5-4f8d-e53e-2db0-639b4c81e418", + "code": "LoadListPage" + }, + { + "id": "53827e22-6f6f-e0f3-e4a2-9ca3e6b8f568", + "code": "LoadCardPage" + } + ], + "efab0177-e16d-4d1f-9567-0bd1f607e53a": [ + { + "id": "63af6df0-163c-8e0e-1ed4-a9766f4921ae", + "code": "setFieldsTruncateConfig" + } + ] +} \ No newline at end of file diff --git a/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json b/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json new file mode 100644 index 0000000000000000000000000000000000000000..c38384f406a14d138f2a108bd26487d9c2d387fb --- /dev/null +++ b/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json @@ -0,0 +1,452 @@ +{ + "d7de1993-d500-44fd-9922-43c78d477aa3": [ + { + "id": "dba10520-f564-31a4-13ac-f07709402304", + "code": "LoadNavTree" + }, + { + "id": "b9241e0d-90d1-72e7-c9b6-8f08caaef8ad", + "code": "LoadSubList" + }, + { + "id": "ae60fedd-e0e7-ac7a-eaa9-430833dbefc7", + "code": "RouteToAdd" + }, + { + "id": "8b6f29b4-7326-f9f8-0625-3954a71f3595", + "code": "RouteToEdit" + }, + { + "id": "74cda30e-6abb-5269-64a4-0f43c189ed74", + "code": "RouteToView" + }, + { + "id": "4c183907-66c4-1b02-c8ab-aa13a4efc8f3", + "code": "Remove" + }, + { + "id": "294afc8c-bea9-658c-81f0-42982f8c7eb0", + "code": "Close" + } + ], + "8172a979-2c80-4637-ace7-b13074d3f393": [ + { + "id": "0c67fafb-3bb7-d0a5-d546-3dae63434212", + "code": "Load" + }, + { + "id": "05c445e5-4e18-f4e6-2dc8-997228dc36a7", + "code": "LoadAndAdd" + }, + { + "id": "052104fd-3f13-0738-058e-4945b5f95c27", + "code": "LoadAndView" + }, + { + "id": "2ecf6524-ffc0-ada5-2765-2103c597f880", + "code": "LoadAndEdit" + }, + { + "id": "363d6a62-afb8-6789-39ef-cae0a5c4ae9d", + "code": "Add" + }, + { + "id": "63bc76df-1626-eff7-ab55-03ed9b44750d", + "code": "Edit" + }, + { + "id": "bd081bfc-7ce8-979e-e54c-3b01fc8ffc96", + "code": "Cancel" + }, + { + "id": "c22ff5a0-cfeb-aab1-ac01-937cfcd80c6a", + "code": "Save" + }, + { + "id": "eeb436cf-6684-874f-3ca7-d42aec83730d", + "code": "Close" + }, + { + "id": "6f987222-ebe2-0f3c-1594-a12408b22801", + "code": "AddItem" + }, + { + "id": "0cdeddcc-8332-f13f-be96-b5eeac84a334", + "code": "RemoveItem" + }, + { + "id": "af181469-5bda-7c9f-e187-dc173cfd7356", + "code": "LoadAndCascadeAdd" + }, + { + "id": "89904e71-5b79-9caf-b9d6-77e878cc1552", + "code": "cascadeAdd" + } + ], + "26436aa8-88a7-4aee-bf0b-9843c1e8afbf": [ + { + "id": "f7dd2c84-7abd-d4bf-6b31-71d96035c034", + "code": "LoadNavList" + }, + { + "id": "e8e6433a-7c00-1773-0f0d-b4f9c3060e56", + "code": "LoadSubList" + }, + { + "id": "59858a08-f940-413c-4717-2c65212c9303", + "code": "RouteToAdd" + }, + { + "id": "b448888e-7200-e9d6-ec51-23257a61904f", + "code": "RouteToEdit" + }, + { + "id": "ea5e9181-70e6-5344-536f-e586f0f1c00a", + "code": "RouteToView" + }, + { + "id": "5d2c531e-f0f4-7330-e627-52745352117d", + "code": "Remove" + }, + { + "id": "0f69d3b4-a81e-b98f-d7a1-e18810dbc98f", + "code": "Close" + }, + { + "id": "c0a61c65-f3f2-95f3-2672-aa52d18ad047", + "code": "ChangePage" + } + ], + "eb07c2e4-7cc1-4d95-aad0-410823006d71": [ + { + "id": "acd815d6-a80a-e617-962f-37b445a15fb1", + "code": "execute" + } + ], + "70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72": [ + { + "id": "86c9f281-e5bc-5d5c-1b86-d1e17ab2e850", + "code": "Load" + }, + { + "id": "0430f234-634a-0b1d-878f-706d06c53948", + "code": "Remove" + }, + { + "id": "b7da52d1-761c-6263-08d4-30a0061c922c", + "code": "Add" + }, + { + "id": "1d2b8b9b-7a7d-f807-6e51-9ea6e945635a", + "code": "View" + }, + { + "id": "405ec4c7-21f6-bffb-a2d0-edbeb47a042c", + "code": "Edit" + }, + { + "id": "b5103abd-bd9c-2f56-9b56-68c94959f757", + "code": "Close" + }, + { + "id": "e86b4c09-d3d7-0f5a-1d03-17d4da6603e4", + "code": "RemoveRows" + }, + { + "id": "62d673bf-6219-a55b-1080-a4116ca1058c", + "code": "ChangePage" + }, + { + "id": "d7c77f23-fca6-8a90-8e20-8f84f5709663", + "code": "refresh" + } + ], + "d7ce1ba6-49c7-4a27-805f-f78f42e72725": [ + { + "id": "f80e026b-bd9b-002b-d2aa-52c44a633bec", + "code": "Load" + }, + { + "id": "8a19b303-4e75-c267-e42a-b56d059577a9", + "code": "Add" + }, + { + "id": "79aa9a7b-1189-8cba-dcad-2089d95aee72", + "code": "Edit" + }, + { + "id": "8253428a-0287-8390-0ea1-a31eefa1a057", + "code": "Save" + }, + { + "id": "6118693c-9d5c-f401-7101-8344744183f2", + "code": "Cancel" + }, + { + "id": "a82e6e67-ff48-05ce-a780-26a10b83253b", + "code": "Remove" + }, + { + "id": "8034cae9-ecd7-e6ab-22c2-0cdf7cfd536f", + "code": "Close" + }, + { + "id": "6bf1ed43-a493-f2dd-de19-77ebfb79916a", + "code": "ChangePage" + }, + { + "id": "dfd86e25-5cfa-313c-617a-8fd5e2eb8fc9", + "code": "RemoveRows" + } + ], + "45be24f9-c1f7-44f7-b447-fe2ada458a61": [ + { + "id": "17021da1-61a5-a90a-072c-6dda3bad01a7", + "code": "LoadList" + }, + { + "id": "5fb563aa-e860-b439-bf64-39c9cdc341db", + "code": "LoadCard" + }, + { + "id": "90603e99-8f81-968e-ca25-a6017fd874d5", + "code": "Add" + }, + { + "id": "87d3f0aa-f087-c806-466f-cda147730eb0", + "code": "Edit" + }, + { + "id": "fa100da6-83a0-e552-2aa9-415c8c27c3dd", + "code": "Save" + }, + { + "id": "1a373dee-261d-0824-9c99-a158eb376864", + "code": "Cancel" + }, + { + "id": "f9f05646-5c0d-c5d3-5218-d9acf49ebe16", + "code": "Close" + }, + { + "id": "250cd2a2-9995-4c01-64aa-5029afba08ca", + "code": "AddItem" + }, + { + "id": "a2c06958-29b1-0582-5f3e-c3cfcc741f8f", + "code": "RemoveItem" + }, + { + "id": "1425afaa-d91a-9e64-39cd-c4a0bb98e336", + "code": "ChangePage" + }, + { + "id": "1cde1e30-3c4e-2695-e2b6-7a0229368a58", + "code": "Remove" + } + ], + "7c48ef46-339c-42d4-8365-a21236c63044": [ + { + "id": "e573d6a2-8261-9ad4-c9f1-2e59af53302d", + "code": "loadList" + }, + { + "id": "d1054fa5-d18e-c22c-ed3f-2f13b4692702", + "code": "loadCard" + }, + { + "id": "6b9556d9-f510-2484-07b8-e1e190f03169", + "code": "add" + }, + { + "id": "ca451c36-4ab8-5576-545f-0bd13c1cb320", + "code": "edit" + }, + { + "id": "dbc290b7-8f64-1ce3-862f-d63e4c6db956", + "code": "save" + }, + { + "id": "5c3f88c9-52b2-bddb-b4ab-a975ec0e48d7", + "code": "cancel" + }, + { + "id": "3e722416-f1e4-d795-0194-0b876adfa253", + "code": "close" + }, + { + "id": "aae5dda3-7941-6d19-dab5-c4126d20e457", + "code": "remove" + }, + { + "id": "40302ced-33be-8d2f-9c4b-023b90351206", + "code": "changePage" + } + ], + "8fe977a1-2b32-4f0f-a6b3-2657c4d03574": [ + { + "id": "0970ba99-fe9f-c08c-81bb-60841ca94b8f", + "code": "LoadTree" + }, + { + "id": "ecd91cda-e8c0-bc59-b454-78b4027b9f9b", + "code": "LoadCard" + }, + { + "id": "57f3d943-2daf-39aa-5087-58efe7708d38", + "code": "AddSibling" + }, + { + "id": "e470716b-a104-5637-357f-ae6fa92cba05", + "code": "AddChild" + }, + { + "id": "963ed4ff-b425-d832-e887-3968feae44b4", + "code": "Remove" + }, + { + "id": "aeb647c7-8a0a-e02b-9c7a-8fd785da4b63", + "code": "Edit" + }, + { + "id": "531835dc-7c8a-5f52-7912-2c69744f8496", + "code": "Save" + }, + { + "id": "0a2a4b5c-3624-9d55-417e-10247271b556", + "code": "Cancel" + }, + { + "id": "21b0c3af-3caf-b11d-2360-d9af20016501", + "code": "AddItem" + }, + { + "id": "113f1d77-65a4-63bf-3973-80dd15f294d1", + "code": "RemoveItem" + }, + { + "id": "52334335-4e0f-dc9d-2bff-fb09cd479dcf", + "code": "Close" + } + ], + "54bddc89-5f7e-4b91-9c45-80dd6606cfe9": [ + { + "id": "92cd8b0e-4d95-3976-f0aa-c4a4cde1a60b", + "code": "Filter" + } + ], + "26e6016a-ef26-4682-bcdb-84114e934696": [ + { + "id": "062fa90d-76c1-8e99-5931-9aa0fa60e25d", + "code": "openDialog" + }, + { + "id": "70582221-f092-9809-85ff-17c01b0f4ee9", + "code": "openApp" + } + ], + "9280ec35-9194-4c8c-9020-37329f064876": [ + { + "id": "eab03d67-c390-2e2e-e252-99446062d76f", + "code": "getSlimBillCreationProcessEntityExById" + }, + { + "id": "42079fe1-c0ff-7457-ba94-c9cb38975d5a", + "code": "getFormSettingsById" + }, + { + "id": "cdf4352a-fd35-ff71-963e-10b3c079bd0f", + "code": "executeBillCreationProcess" + }, + { + "id": "30ddac60-12cc-a3c0-ca68-3bde93247313", + "code": "createEntityDatas" + }, + { + "id": "9d72dad6-2f5d-dd60-b064-16d0f993e9a2", + "code": "updateEntityDatas" + }, + { + "id": "1a57e83b-8c27-246d-aa23-6bcfe6dce064", + "code": "pushTaskCenter" + }, + { + "id": "93358329-127c-a470-6893-74f3c30ef3b8", + "code": "getCreationResultById" + }, + { + "id": "27f7cfd4-a916-d2db-4b08-f05d1d28e7a9", + "code": "addFormBillCreationProcessExecutorResult" + } + ], + "9bb60b70-6653-430f-a88a-768cc8204f85": [ + { + "id": "694a8da6-181a-76bf-17e3-ebc638c1e3be", + "code": "pushByCreationProcessId" + }, + { + "id": "65f76fe3-ca5b-8aed-85ad-4a922d699012", + "code": "openBillCreationProcessSelector4Push" + }, + { + "id": "ef5be4c9-9e0b-ad6d-be04-d8512a36439d", + "code": "openBillCreationProcessSelector4SpecificPush" + }, + { + "id": "106c22a1-9972-1de7-381c-f2f19f543ecb", + "code": "openTargetApp" + }, + { + "id": "082b705e-f43b-3ab2-257f-0d990ae82709", + "code": "pushBySourceCmId" + }, + { + "id": "91963fe4-cb21-2eb9-0e7d-c7731d723837", + "code": "pushBySourceCmIdAndTargetCmId" + } + ], + "eae0e38a-9456-4186-af17-f8113b369989": [ + { + "id": "57e67070-efa9-8988-5bf0-c8b5d5eb9618", + "code": "bifLoad" + }, + { + "id": "9437aa86-1100-0f60-cded-016116c190bb", + "code": "referByCreationProcessId" + }, + { + "id": "81f7d111-903a-180b-5157-d8c4271c47e3", + "code": "openBillCreationProcessSelector4Pull" + }, + { + "id": "1f012cd9-483a-b93b-eee4-5256e1579d08", + "code": "openBillCreationProcessSelector4SpecificPull" + }, + { + "id": "2a1f1c6d-569d-e1d6-04da-798b1df3ddc9", + "code": "openSourceDataSelector4Pull" + }, + { + "id": "fc0be3b1-0273-1c84-a872-69bb1362b15e", + "code": "getCreationResult" + }, + { + "id": "dd847401-5e8c-c0e0-7465-5cb2c50652c2", + "code": "referByTargetCmId" + }, + { + "id": "64a9ce2a-4586-cf2f-22d2-8338b67119e0", + "code": "referBySourceCmIdAndTargetCmId" + } + ], + "824361ac-8baf-4742-8843-ddab5182a342": [ + { + "id": "7a71f224-0465-4bda-b507-6bee22a44c00", + "code": "startProcess" + }, + { + "id": "852cac4c-2689-42bb-a5c4-71bb16b327c0", + "code": "viewProcessInstance" + } + ] +} \ No newline at end of file diff --git a/packages/designer/src/components/composition/control-creator/use-mobile-control-creator.ts b/packages/designer/src/components/composition/control-creator/use-mobile-control-creator.ts new file mode 100644 index 0000000000000000000000000000000000000000..36c3e6024347948cd93932bb2bb6569e09e31287 --- /dev/null +++ b/packages/designer/src/components/composition/control-creator/use-mobile-control-creator.ts @@ -0,0 +1,241 @@ +import { getSchemaByType } from "@farris/mobile-ui-vue"; +import { FormBindingType, FormSchemaEntityField, FormSchemaEntityFieldTypeName, UseControlCreator } from "../../types"; +import { FormMetadataConverter } from "../form-metadata-converter"; + +export function useMobileControlCreator(): UseControlCreator { + /** + * 配置输入控件属性 + * @param field schema字段 + * @param editorType 编辑器类型 + * @param controlClass 输入控件样式 + * @returns + */ + function setFormFieldProperty(field: FormSchemaEntityField, editorType?: string, controlClass = ''): any { + const formGroupMetadata = getSchemaByType('form-group') || {}; + formGroupMetadata.id = field.id.length > 8 ? field.id.slice(0, 8) : field.id; + formGroupMetadata.id = field.bindingField + '_' + formGroupMetadata.id.replace(/-/g, '_') + '_' + Math.random().toString(36).substr(2, 4); + formGroupMetadata.label = field.name; + formGroupMetadata.appearance = { class: controlClass || '' }; + formGroupMetadata.binding = { + type: FormBindingType.Form, + path: field.bindingField, + field: field.id, + fullPath: field.path + }; + formGroupMetadata.path = field.bindingPath; + const metadataConverter = new FormMetadataConverter(); + const resolvedEditorType = editorType || metadataConverter.getRealEditorType(field?.editor?.$type || ''); + const formEditor = getSchemaByType(resolvedEditorType) || {}; + + formGroupMetadata.editor = formEditor; + if (field.require) { + formEditor.required = field.require; + } + + // 只读属性:若字段本身为只读,则取字段属性;若非只读,则设置为状态机 + formEditor.readonly = field.readonly ? true : false; + const fieldTypeInSchema = field.type && field.type.$type; + if (!fieldTypeInSchema) { + return; + } + // 枚举类型 或者是字符串但是指定了编辑器是枚举类的 + if (fieldTypeInSchema === 'EnumType' || fieldTypeInSchema === 'StringType' && ['radio-group', 'check-group', 'combo-list'].find(type => type === formEditor.type)) { + formEditor.data = field.type.enumValues || []; + formEditor.idField = 'value'; + formEditor.valueField = 'value'; + formEditor.textField = 'name'; + } + // 数字类型 + if (fieldTypeInSchema === 'NumericType') { + formEditor.precision = field.type.precision; + formEditor.nullable = true; + } + // 数字、字符串、备注 :设置最大长度 + if (['NumericType', 'StringType', 'TextType'].includes(fieldTypeInSchema)) { + formEditor.maxLength = field.type.length; + } + // 日期类型 + if (formEditor.type === 'date-picker') { + formEditor.fieldType = field.type.name; + + // 日期时间类型字段:启用时间选择属性 + if (fieldTypeInSchema === 'DateTimeType') { + formEditor.showTime = true; + formEditor.displayFormat = 'yyyy-MM-dd HH:mm:ss'; + formEditor.valueFormat = 'yyyy-MM-dd HH:mm:ss'; + + } + } + + return formGroupMetadata; + } + + /** + * 字段类型是文本,切换成其他控件类型 + * @param editorType + * @returns + */ + function getRealGridTypeByEditorType(editorType) { + switch (editorType) { + case 'combo-list': + case 'radio-group': + case 'check-group': + return 'enum'; + case 'date-picker': + return 'date'; + default: + return 'string'; + } + } + /** + * 将控件类型映射为表单表格列上的类型 + * param field + */ + function mapControlType2GridFieldType(field: FormSchemaEntityField): string { + if (!field.editor) { + return ''; + } + switch (field.type.name) { + case FormSchemaEntityFieldTypeName.Enum: return 'enum'; + case FormSchemaEntityFieldTypeName.String: + return getRealGridTypeByEditorType(field.editor.$type); + case FormSchemaEntityFieldTypeName.Text: return 'string'; + case FormSchemaEntityFieldTypeName.Number: return 'number'; + case FormSchemaEntityFieldTypeName.Date: return 'date'; + case FormSchemaEntityFieldTypeName.DateTime: return 'datetime'; + case FormSchemaEntityFieldTypeName.Boolean: return 'boolean'; + } + + return ''; + } + /** + * 设置列格式 + * @param gridFieldType 列类型 + * @param metadata 元数据 + * @param schemaField schemaField + */ + function setGridFieldFormatter(gridFieldType: string, metadata: any, schemaField: any) { + switch (gridFieldType) { + case 'number': { + metadata.formatter = { + type: 'number', + precision: schemaField.type.precision, + thousand: ',', + decimal: '.' + }; + break; + } + case 'date': { + metadata.formatter = { + type: 'date', + dateFormat: 'yyyy-MM-dd' + }; + break; + } + case 'datetime': { + metadata.formatter = { + type: 'date', + dateFormat: 'yyyy-MM-dd HH:mm:ss' + }; + break; + } + case 'boolean': { + metadata.formatter = { + type: 'boolean', + trueText: '是', + falseText: '否' + }; + break; + } + case 'enum': { + metadata.formatter = { + type: 'enum', + data: schemaField.type.enumValues || [] + }; + break; + } + } + } + /** + * 配置列属性 + * @param field schema字段 + * @param metadata 列元数据 + * @param neddInlineEditor 是否需要列编辑器 + */ + function setGridFieldProperty(gridType: string, field: FormSchemaEntityField, metadata: any, needInlineEditor = false): any { + const metadataConverter = new FormMetadataConverter(); + if (!metadata) { + metadata = getSchemaByType(gridType, {}); + } + if (!metadata || !field) { + return; + } + + metadata.id = field.id.length > 8 ? field.id.slice(0, 8) : field.id; + metadata.id = field.bindingField + '_' + metadata.id.replace(/-/g, '_') + '_' + Math.random().toString(36).substr(2, 4); + metadata.title = field.name; + + // 关联字段dataField绑定主表字段的label + '.' + 关联字段的label + metadata.field = field.bindingPath; + + metadata.binding = { + type: FormBindingType.Form, + path: field.bindingField, + field: field.id, + fullPath: field.path + }; + + // 设置列类型. 若是枚举类型再设置enumData;若是日期类型,设置默认格式;数字类型设置格式、精度 + metadata.dataType = mapControlType2GridFieldType(field); + + // 枚举类型 设置enumData + // if (metadata.dataType === 'enum' && field.type) { + // metadata.enumData = field.type.enumValues; + // metadata.idField = 'value'; + // metadata.valueField = 'value'; + // metadata.textField = 'name'; + // } + metadata.multiLanguage = field.multiLanguage; + + // 日期类型字段:增加数据国际化配置 + if (field.type.name === FormSchemaEntityFieldTypeName.Date || + field.type.name === FormSchemaEntityFieldTypeName.DateTime) { + metadata.localization = false; + metadata.localizationType = field.type.name; + } + + // 列格式 + setGridFieldFormatter(metadata.dataType, metadata, field); + + // 列编辑器 + if (needInlineEditor) { + const realEditor = metadataConverter.getRealEditorType(field?.editor?.$type || ''); + const fieldEditor = setFormFieldProperty(field, realEditor, ''); + metadata.editor = fieldEditor.editor; + } + + return metadata; + } + + /** + * 配置输入控件属性(控件无绑定信息) + * @param editorType 编辑器类型 + * @param controlClass 输入控件样式 + */ + function createFormGroupWithoutField(editorType = 'input-group', controlClass = '') { + const formGroupMetadata = getSchemaByType('form-group') || {}; + formGroupMetadata.id = `${editorType}_${Math.random().toString(36).substr(2, 4)}`; + formGroupMetadata.appearance = { class: controlClass || '' }; + formGroupMetadata.binding = null; + + const formEditor = getSchemaByType(editorType) || {}; + + formGroupMetadata.editor = formEditor; + return formGroupMetadata; + } + return { + setFormFieldProperty, + setGridFieldProperty, + createFormGroupWithoutField + }; +} diff --git a/packages/designer/src/components/composition/control-creator.service.ts b/packages/designer/src/components/composition/control-creator/use-pc-control-creator.service.ts similarity index 98% rename from packages/designer/src/components/composition/control-creator.service.ts rename to packages/designer/src/components/composition/control-creator/use-pc-control-creator.service.ts index 004994bc2ef871e1b048c323f5e7b6fa290723ad..6cbe536c0184092a8b2cf47cc3cf7918a1817408 100644 --- a/packages/designer/src/components/composition/control-creator.service.ts +++ b/packages/designer/src/components/composition/control-creator/use-pc-control-creator.service.ts @@ -1,8 +1,8 @@ import { getSchemaByType } from "@farris/ui-vue/components"; -import { FormBindingType, FormSchemaEntityField, FormSchemaEntityFieldTypeName, UseControlCreator } from "../types"; -import { FormMetadataConverter } from "./form-metadata-converter"; +import { FormBindingType, FormSchemaEntityField, FormSchemaEntityFieldTypeName, UseControlCreator } from "../../types"; +import { FormMetadataConverter } from "../form-metadata-converter"; -export function useControlCreator(): UseControlCreator { +export function usePCControlCreator(): UseControlCreator { /** * 配置输入控件属性 * @param field schema字段 diff --git a/packages/designer/src/components/composition/control-property-changed.service.ts b/packages/designer/src/components/composition/control-property-changed.service.ts index b6dd93b59bcf66fe5fbfc518e07c7ae03b3f38ae..f642a2cdfd273ab6ed784d98b8efdb3bc07fd8a3 100644 --- a/packages/designer/src/components/composition/control-property-changed.service.ts +++ b/packages/designer/src/components/composition/control-property-changed.service.ts @@ -1,4 +1,4 @@ -import { FormPropertyChangeObject, SchemaDOMMapping } from "@farris/ui-vue"; +import { FormPropertyChangeObject, SchemaDOMMapping } from "@farris/ui-vue/components"; import { get, set } from "lodash-es"; import { FormBindingType, FormVariableCategory, UseDesignViewModel, UseFormSchema, UseSchemaService } from "../types"; import { DesignViewModelField } from "../types/design-viewmodel"; diff --git a/packages/designer/src/components/composition/designer-context/use-designer-context.ts b/packages/designer/src/components/composition/designer-context/use-designer-context.ts new file mode 100644 index 0000000000000000000000000000000000000000..a71ba23d89250b741d8aa3695543038fac56824b --- /dev/null +++ b/packages/designer/src/components/composition/designer-context/use-designer-context.ts @@ -0,0 +1,23 @@ +import { DesignerMode, UseDesignerContext } from "../../types/designer-context"; +import { MetadataService } from "../metadata.service"; +import { useMobileDesignerContext } from "./use-mobile-designer-context"; +import { usePCDesignerContext } from "./use-pc-designer-context"; + +/** + * 设计器上下文 + * @returns + */ +export function useDesignerContext(): UseDesignerContext { + function getDesignerMode(): DesignerMode { + const metadataService = new MetadataService(); + const metadataPath = metadataService.getMetadataPath(); + if (metadataPath && metadataPath.includes('.mfrm')) { + return DesignerMode.Mobile; + } + return DesignerMode.PC; + } + + const designerMode = getDesignerMode(); + + return designerMode === DesignerMode.Mobile ? useMobileDesignerContext() : usePCDesignerContext(); +} \ No newline at end of file diff --git a/packages/designer/src/components/composition/designer-context/use-mobile-designer-context.ts b/packages/designer/src/components/composition/designer-context/use-mobile-designer-context.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3da548d7aefa207d1e761cc10e48fd9c63d6063 --- /dev/null +++ b/packages/designer/src/components/composition/designer-context/use-mobile-designer-context.ts @@ -0,0 +1,59 @@ +import { DesignerMode, UseDesignerContext } from "../../types/designer-context"; +import ToolboxItems from '../../types/toolbox/mobile-toolbox.json'; +import SupportedControllers from '../../composition/command/supported-controllers/mobile-supported-controller.json'; + +import { + Component, PageContainer, PageHeaderContainer, PageBodyContainer, PageFooterContainer, Picker, NumberInput, Textarea, DatePicker, DateTimePicker, + ContentContainer, FloatContainer, Navbar, ListView, Form, FormItem, InputGroup, Button, registerDesignerComponents, Switch, CheckboxGroup, RadioGroup, +} from '@farris/mobile-ui-vue'; +import { useMobileControlCreator } from "../control-creator/use-mobile-control-creator"; +import { FormComponent, UseFormSchema } from "../../../components/types"; +import ControllCategories from '../schema-repository/controller/mobile-categories'; + +export function useMobileDesignerContext(): UseDesignerContext { + + /** 设计器模式 */ + const designerMode: DesignerMode = DesignerMode.Mobile; + + /** 工具箱的数据 */ + const toolboxItems: any[] = ToolboxItems; + + /** 要注册的UI组件 */ + const componentsToRegister: any[] = [ + Component, PageContainer, PageHeaderContainer, PageBodyContainer, PageFooterContainer, + ContentContainer, FloatContainer,Textarea,DatePicker,DateTimePicker, + Navbar, ListView,Picker,NumberInput,Switch,CheckboxGroup,RadioGroup, + Form, FormItem, InputGroup, + Button + ]; + registerDesignerComponents(componentsToRegister); + + /** 支持的控制器 */ + const supportedControllers: any = SupportedControllers; + + const controllCategories: any = ControllCategories; + + + /** 控件创建服务 */ + const useControlCreator = useMobileControlCreator; + + /** + * 获取所有的页面组件 + * @returns + */ + function getPageComponents(useFormSchema:UseFormSchema):FormComponent[]{ + const predicateFunction = (component: any) => component.componentType && component.componentType.toLowerCase() === 'page'; + const pageComponents = useFormSchema.getComponetsByPredicate(predicateFunction); + return pageComponents; + } + + return { + designerMode, + toolboxItems, + componentsToRegister, + supportedControllers, + controllCategories, + useControlCreator, + getPageComponents + } +} \ No newline at end of file diff --git a/packages/designer/src/components/composition/designer-context/use-pc-designer-context.ts b/packages/designer/src/components/composition/designer-context/use-pc-designer-context.ts new file mode 100644 index 0000000000000000000000000000000000000000..282da41d9103fa5f7543d20baf07d7fcd2a01c1b --- /dev/null +++ b/packages/designer/src/components/composition/designer-context/use-pc-designer-context.ts @@ -0,0 +1,50 @@ +import { DesignerMode, UseDesignerContext } from "../../types/designer-context"; +import ToolboxItems from '../../types/toolbox/pc-toolbox.json'; +import { usePCControlCreator } from "../control-creator/use-pc-control-creator.service"; +import SupportedControllers from '../../composition/command/supported-controllers/pc-supported-controller.json'; +import { FormComponent, UseFormSchema } from "../../../components/types"; +import ControllCategories from '../schema-repository/controller/pc-categories'; + +export function usePCDesignerContext(): UseDesignerContext { + + /** 设计器模式 */ + const designerMode: DesignerMode = DesignerMode.PC; + + /** 工具箱的数据 */ + const toolboxItems: any[] = ToolboxItems; + + /** 要注册的UI组件 */ + const componentsToRegister: any = null; + + /** 支持的控制器 */ + const supportedControllers: any = SupportedControllers; + + /** 控制器分类 */ + const controllCategories: any = ControllCategories; + + /** 控件创建服务 */ + const useControlCreator = usePCControlCreator; + + /** + * 获取所有的页面组件 + * @returns + */ + function getPageComponents(useFormSchema: UseFormSchema): FormComponent[] { + const pageComponents: FormComponent[] = []; + const pageComponent = useFormSchema.getComponentById('root-component'); + if (pageComponent) { + pageComponents.push(pageComponent); + } + return pageComponents; + } + + return { + designerMode, + toolboxItems, + componentsToRegister, + supportedControllers, + controllCategories, + useControlCreator, + getPageComponents + } +} \ No newline at end of file diff --git a/packages/designer/src/components/composition/schema-repository/controller/controller-selector.service.ts b/packages/designer/src/components/composition/schema-repository/controller/controller-selector.service.ts index d54af5217d56b8b3b67100f303c5c1fe110746bf..ccdcaedefbd1b8dee1ad26b02c1adb3ba40c4609 100644 --- a/packages/designer/src/components/composition/schema-repository/controller/controller-selector.service.ts +++ b/packages/designer/src/components/composition/schema-repository/controller/controller-selector.service.ts @@ -1,15 +1,15 @@ import { MetadataService } from "../../metadata.service"; import { SchemaItem, SchemaRepositoryPagination, SchemaCategory } from "@farris/ui-vue/components"; -import controllCategories from './categories'; -import { getAllSupportedControllers } from "../../command/supported-controller"; +import { UseDesignerContext } from "../../../../components/types/designer-context"; export class ControllerSelectorSchemaService { private metadataType = '.webcmd'; - constructor(private metadataService: MetadataService) { + + constructor(private metadataService: MetadataService, private designerContext: UseDesignerContext) { } - public getNavigationData(searchingText: string, pagination: SchemaRepositoryPagination): SchemaCategory[] { - return controllCategories; + public getNavigationData = (searchingText: string, pagination: SchemaRepositoryPagination): SchemaCategory[] => { + return this.designerContext.controllCategories; } public getRecentlyData(searchingText: string, pagination: SchemaRepositoryPagination): SchemaItem[] { @@ -21,12 +21,9 @@ export class ControllerSelectorSchemaService { } private metadata2SchemaItem(metadata: any[], category: string): SchemaItem[] { - const supportedControllers = getAllSupportedControllers(); + const { supportedControllers } = this.designerContext; + return metadata.filter((metadataItem) => { - // 移除移动控制器 - if (metadataItem.nameSpace.includes('Inspur.GS.Gsp.Mobile')) { - return false; - } // 支持自定义构件 if (metadataItem.nameSpace.includes('.Front')) { return true; diff --git a/packages/designer/src/components/composition/schema-repository/controller/mobile-categories.ts b/packages/designer/src/components/composition/schema-repository/controller/mobile-categories.ts new file mode 100644 index 0000000000000000000000000000000000000000..31ba4f36c74d3aa21641cc80b6a4739c23473689 --- /dev/null +++ b/packages/designer/src/components/composition/schema-repository/controller/mobile-categories.ts @@ -0,0 +1,73 @@ +export default [ + { + id: "all", + code: "all", + name: "全部", + active: true, + contains: [] + }, + { + id: "data", + code: "data", + name: "数据", + active: false, + contains: ['AddCommands','RemoveCommands', 'EditCommands','UpdateCommands','ViewCommands', 'SaveCommands','LoadCommands','CancelCommands'] + }, + { + id: "navigate", + code: "navigate", + name: "路由", + active: false, + contains: ['NavigateCommands'] + }, + { + id: "flow", + code: "flow", + name: "流程", + active: false, + contains: ['ApproveService'] + }, + { + id: "file", + code: "file", + name: "附件", + active: false, + contains: ['MobileAttachmentCmd'] + }, + { + id: "stateMachine", + code: "stateMachine", + name: "状态机", + active: false, + contains: ['StateMachineCommands'] + }, + { + id: "discussion", + code: "discussion", + name: "评论区", + active: false, + contains: ['DiscussionGroupCommands'] + }, + { + id: "ui", + code: "ui", + name: "UI相关", + active: false, + contains: ['UICommands'] + }, + { + id: "loadPage", + code: "loadPage", + name: "页面加载", + active: false, + contains: ['LoadPageCommands'] + }, + { + id: "other", + code: "other", + name: "其他", + active: false, + contains: ['VoVariableService'] + } + +]; diff --git a/packages/designer/src/components/composition/schema-repository/controller/categories.ts b/packages/designer/src/components/composition/schema-repository/controller/pc-categories.ts similarity index 100% rename from packages/designer/src/components/composition/schema-repository/controller/categories.ts rename to packages/designer/src/components/composition/schema-repository/controller/pc-categories.ts diff --git a/packages/designer/src/components/composition/use-form-schema.ts b/packages/designer/src/components/composition/use-form-schema.ts index 182bf3363f64ac2917f0270e50e68165bb652856..f7d85db9d07ab88fb743b9931fb5cded25a2c19d 100644 --- a/packages/designer/src/components/composition/use-form-schema.ts +++ b/packages/designer/src/components/composition/use-form-schema.ts @@ -1292,6 +1292,7 @@ export function useFormSchema(): UseFormSchema { updateRemoteVariables, getRootViewModelId, getSchemaEntities, - externalFormSchema + externalFormSchema, + getComponetsByPredicate }; } diff --git a/packages/designer/src/components/composition/use-form-statemachine.ts b/packages/designer/src/components/composition/use-form-statemachine.ts index 775b93c26766a07a7829948b420738666d546749..796e23ea67236359fc9608680936f3cfebe8314c 100644 --- a/packages/designer/src/components/composition/use-form-statemachine.ts +++ b/packages/designer/src/components/composition/use-form-statemachine.ts @@ -21,7 +21,6 @@ export default function (useFormSchemaComposition: UseFormSchema): UseFormStateM * 提取状态机中的可视化状态数据 */ function resolveRenderStateData(stateMachineCode: string) { - renderStateData = []; Object.keys(stateMachineMetadata.renderState).forEach(item => { const state = stateMachineMetadata.renderState[item]; renderStateData.push({ @@ -36,22 +35,25 @@ export default function (useFormSchemaComposition: UseFormSchema): UseFormStateM * 获取状态机元数据 */ function queryStateMachineMetadata(): void { + renderStateData = []; const formSchema = useFormSchemaComposition.getFormSchema(); const formBasicInfo = useFormSchemaComposition.getFormMetadataBasicInfo(); if (!formSchema?.module || !formBasicInfo) { return; } const { stateMachines } = formSchema.module; - if (stateMachines && stateMachines.length) { - const { uri: stateMachineID, id: stateMachineCode } = stateMachines[0]; - const { relativePath } = formBasicInfo; - metadataService.queryMetadataById(relativePath, stateMachineID).then(result => { - if (result?.data?.content) { - stateMachineMetadata = JSON.parse(result.data.content); - } - resolveRenderStateData(stateMachineCode); - }, (error) => { - messageBoxService.error(error?.response?.data?.Message || '查询状态机元数据失败。'); + if (stateMachines && stateMachines.length > 0) { + stateMachines.forEach(stateMachine => { + const { uri: stateMachineID, id: stateMachineCode } = stateMachine; + const { relativePath } = formBasicInfo; + metadataService.queryMetadataById(relativePath, stateMachineID).then(result => { + if (result?.data?.content) { + stateMachineMetadata = JSON.parse(result.data.content); + } + resolveRenderStateData(stateMachineCode); + }, (error) => { + messageBoxService.error(error?.response?.data?.Message || '查询状态机元数据失败。'); + }); }); } return; diff --git a/packages/designer/src/components/designer.component.tsx b/packages/designer/src/components/designer.component.tsx index 0b015c12e6e151e43583105eee5c4569c3a5be28..b92c011f8187de3c20a6ac035749f852f572f7b2 100644 --- a/packages/designer/src/components/designer.component.tsx +++ b/packages/designer/src/components/designer.component.tsx @@ -13,13 +13,13 @@ import { useEventsEditor } from "./composition/use-events-editor"; import { useEventsEditorUtils } from "./composition/events-editor-utils"; import { useDesignViewModel } from "./composition/design-viewmodel.service"; import { useSchemaService } from "./composition/schema.service"; -import { useControlCreator } from "./composition/control-creator.service"; import { FormMetadataConverter } from "./composition/form-metadata-converter"; import FCodeViewDesign from "./components/code-view/components/code-view.component"; import { useCommandBuilderService } from "./composition/command-builder.service"; import useFormStateMachine from './composition/use-form-statemachine'; import { MetadataService } from "./composition/metadata.service"; +import { DesignerMode, UseDesignerContext } from "./types/designer-context"; export default defineComponent({ name: 'FDesigner', @@ -41,6 +41,7 @@ export default defineComponent({ const currentViewType = ref('designer'); const codeViewComponent = ref(); const metadataService = new MetadataService(); + const designerContext = inject('designerContext') as UseDesignerContext; // 注册 formSchema服务 const useFormSchemaComposition = useFormSchema(); provide('useFormSchema', useFormSchemaComposition); @@ -64,7 +65,7 @@ export default defineComponent({ // metadatFullPath const metadataPath: string = inject(MetadataPathToken, ''); // 控件创建服务 - const controlCreatorService = useControlCreator(); + const controlCreatorService = designerContext.useControlCreator(); provide('controlCreatorUtils', controlCreatorService); provide('formMetadataConverter', new FormMetadataConverter()); const { eventBetweenDesignerAndCodeView } = commandBuilderService; @@ -117,17 +118,25 @@ export default defineComponent({ const loadingInstance = loadingService?.show({ message: '解析中,请稍候...' }); const metadataId = useFormSchemaComposition.getFormMetadataBasicInfo()?.id; const relativePath = useFormSchemaComposition.getFormMetadataBasicInfo()?.relativePath; + const formCode = useFormSchemaComposition.getFormMetadataBasicInfo()?.code; useFormMetadataComposition.publishFormMetadata().then((publishInfo) => { if (publishInfo.result) { loadingInstance.value.close(); - const previewUrl = `${window.location.origin}/platform/common/web/renderer/index.html#/preview?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; + let previewUrl; + if (designerContext.designerMode === DesignerMode.Mobile) { + const component = useFormSchemaComposition.getComponents()[0]; + const uri = component?.route?.uri; + previewUrl = `${window.location.origin}/platform/common/web/mobile-renderer/index.html#/${formCode}/${uri}?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; + } else { + previewUrl = `${window.location.origin}/platform/common/web/renderer/index.html#/preview?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; + } const windowProxy = window.open(previewUrl); if (!windowProxy) { - messageBoxService.error('预览失败,请调整浏览器安全设置后重试!'); - } - } else { - loadingInstance.value.close(); - messageBoxService.error(publishInfo.error || '表单解析失败'); + messageBoxService.error('预览失败,请调整浏览器安全设置后重试!'); + } + } else { + loadingInstance.value.close(); + messageBoxService.error(publishInfo.error || '表单解析失败'); } }); diff --git a/packages/designer/src/components/types/basic.ts b/packages/designer/src/components/types/basic.ts index 9f1a095b93babb3f0d780303a006852c914a5371..a3e36ce32c3a06e654dda9751283f939b0478e80 100644 --- a/packages/designer/src/components/types/basic.ts +++ b/packages/designer/src/components/types/basic.ts @@ -132,6 +132,7 @@ export interface FormComponent { code?: string; name?: string; + route?:any; } /** diff --git a/packages/designer/src/components/types/designer-context.ts b/packages/designer/src/components/types/designer-context.ts new file mode 100644 index 0000000000000000000000000000000000000000..33747fbee93f2628b037834c46e88626b9f67c42 --- /dev/null +++ b/packages/designer/src/components/types/designer-context.ts @@ -0,0 +1,20 @@ +import { FormComponent, UseControlCreator, UseFormSchema } from "../types"; + +/** 设计器模式 */ +export enum DesignerMode { + /** PC设计器 */ + PC = 'PC', + + /** 移动设计器 */ + Mobile = 'Mobile', +} + +export interface UseDesignerContext { + designerMode: DesignerMode; + toolboxItems: any[]; + componentsToRegister: any[]; + supportedControllers: any; + controllCategories:any; + useControlCreator: () => UseControlCreator; + getPageComponents: (useFormSchema: UseFormSchema) => FormComponent[]; +} \ No newline at end of file diff --git a/packages/designer/src/components/types/metadata.ts b/packages/designer/src/components/types/metadata.ts index ac29610e6132b0478c4fcf83685110d5778e29e2..a73a962a3ee238a6f0fbee9ab15ff4b260283e03 100644 --- a/packages/designer/src/components/types/metadata.ts +++ b/packages/designer/src/components/types/metadata.ts @@ -225,6 +225,7 @@ export interface UseFormSchema { getVariableByCode: (variableCode: string) => FormVariable | undefined; updateRemoteVariables: (variables: FormSchemaEntityField[]) => void; getSchemaEntities: () => FormSchemaEntity[]; + getComponetsByPredicate(predicate: (component: any) => boolean); } export interface UseSchemaService { diff --git a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.json b/packages/designer/src/components/types/toolbox/mobile-toolbox.json similarity index 100% rename from packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.json rename to packages/designer/src/components/types/toolbox/mobile-toolbox.json diff --git a/packages/ui-vue/components/designer-toolbox/src/toolbox.json b/packages/designer/src/components/types/toolbox/pc-toolbox.json similarity index 96% rename from packages/ui-vue/components/designer-toolbox/src/toolbox.json rename to packages/designer/src/components/types/toolbox/pc-toolbox.json index 9ae7e7cc78382e498e3110871f5472e7ea0a5f23..2a5084fb69529d983f33084d7e45b5d1f107faf3 100644 --- a/packages/ui-vue/components/designer-toolbox/src/toolbox.json +++ b/packages/designer/src/components/types/toolbox/pc-toolbox.json @@ -62,6 +62,12 @@ "type": "lookup", "name": "帮助", "category": "input" + }, + { + "id": "TimePicker", + "type": "time-picker", + "name": "时间选择", + "category": "input" } ] }, diff --git a/packages/designer/tsconfig.json b/packages/designer/tsconfig.json index 0b7f4ecc1032fe1419cda7df75df92e306ca5f87..54db16283f1f83e38e9f53039d4a891a46e4a216 100644 --- a/packages/designer/tsconfig.json +++ b/packages/designer/tsconfig.json @@ -19,7 +19,9 @@ "forceConsistentCasingInFileNames": true, "types": ["vitest/globals", "@types/jest"], "baseUrl": "./", - "paths": {} + "paths": { + "@farris/mobile-ui-vue": ["../mobile-ui-vue/components"] + } }, "include": ["components/**/*", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "designer/**/*"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/packages/designer/vite.config.dev.ts b/packages/designer/vite.config.dev.ts index cefa3ba76e95a49d1baa56ef84d147ea3ce22b42..50a530b2007c09f4e4ff27b1f9f851bf38096924 100644 --- a/packages/designer/vite.config.dev.ts +++ b/packages/designer/vite.config.dev.ts @@ -19,7 +19,7 @@ export default defineConfig({ alias: { '@': resolve(__dirname, '../'), '@farris/ui-vue': resolve(__dirname, '../ui-vue'), - '@farris/code-editor-vue': resolve(__dirname, '../code-editor') + '@farris/mobile-ui-vue': resolve(__dirname, '../mobile-ui-vue/components') } } }); diff --git a/packages/farris-theme/theme/components/time-picker.scss b/packages/farris-theme/theme/components/time-picker.scss index 99dc3db4a22df84cdbe4ce4db2d3bb25cd4f49cb..27cd8ea1913116bcd6c8ee5c27ab5d5a9716189a 100644 --- a/packages/farris-theme/theme/components/time-picker.scss +++ b/packages/farris-theme/theme/components/time-picker.scss @@ -10,15 +10,15 @@ font-feature-settings: 'tnum'; position: absolute; z-index: 9999; - + min-width: 200px; + background:$f-cmp-timepicker-bg; + .time-picker-panel-inner { position: relative; left: 0; font-size: 14px; text-align: left; list-style: none; - background:$f-cmp-timepicker-bg; - margin:$f-cmp-timepicker-panel-spacer 0 0; background-clip: padding-box; border-radius: $f-cmp-timepicker-panel-border-radius; outline: 0; @@ -91,7 +91,7 @@ } } &:last-child::after { - height: 252px; + height: 162px; display: block; content: ''; } diff --git a/packages/mobile-render/vite.config.ts b/packages/mobile-render/vite.config.ts index 4c68bb48c60634d5415ea698456095740e60676b..a90bdf444de1f5433e41f14a9347bf49d23d87a1 100644 --- a/packages/mobile-render/vite.config.ts +++ b/packages/mobile-render/vite.config.ts @@ -41,7 +41,7 @@ export default defineConfig({ 'vue': 'vue/dist/vue.esm-bundler.js', "@farris/devkit-vue": path.resolve(__dirname, "../devkit/lib/index"), "@farris/bef-vue": path.resolve(__dirname, "../bef/lib/index"), - "@farris/mobile-ui-vue": path.resolve(__dirname, "../mobile-ui-vue/components/index"), + "@farris/mobile-ui-vue": path.resolve(__dirname, "../mobile-ui-vue/components"), "@farris/mobile-command-services-vue": path.resolve(__dirname, "../mobile-command-services/lib/index"), "@components": path.resolve(__dirname, "../mobile-ui-vue/components"), "@/components": path.resolve(__dirname, "../mobile-ui-vue/components"), diff --git a/packages/mobile-ui-vue/components/action-sheet/index.ts b/packages/mobile-ui-vue/components/action-sheet/index.ts index bb2bfec3ee332333227fc9ffc099df946147aac5..ad9cda3f23552ad36be9273108a2d593c692a016 100644 --- a/packages/mobile-ui-vue/components/action-sheet/index.ts +++ b/packages/mobile-ui-vue/components/action-sheet/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import ActionSheetInstallless from './src/action-sheet.component'; export * from './src/action-sheet.props'; diff --git a/packages/mobile-ui-vue/components/action-sheet/src/action-sheet.component.tsx b/packages/mobile-ui-vue/components/action-sheet/src/action-sheet.component.tsx index 4e8a6a6df637e51a5a9ee5cae6494f137f00c859..8a91c568b4ce2183b9857c7633a8d24b35111b90 100644 --- a/packages/mobile-ui-vue/components/action-sheet/src/action-sheet.component.tsx +++ b/packages/mobile-ui-vue/components/action-sheet/src/action-sheet.component.tsx @@ -14,10 +14,10 @@ * limitations under the License. */ import { defineComponent, SetupContext, computed, CSSProperties, nextTick } from 'vue'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { ACTION_SHEET_NAME, actionSheetProps, ActionSheetProps, ActionSheetItem } from './action-sheet.props'; -import Popup from '@components/popup'; -import Icon from '@components/icon'; +import Popup from '@farris/mobile-ui-vue/popup'; +import Icon from '@farris/mobile-ui-vue/icon'; export default defineComponent({ name: ACTION_SHEET_NAME, diff --git a/packages/mobile-ui-vue/components/button-edit/index.ts b/packages/mobile-ui-vue/components/button-edit/index.ts index 5036681ccd4ec6b8ed146755ada0949ad1dc6038..cf7cbeb088044a2a81fb37222a863b710e397c31 100644 --- a/packages/mobile-ui-vue/components/button-edit/index.ts +++ b/packages/mobile-ui-vue/components/button-edit/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import ButtonEditInstallless from './src/button-edit.component'; export * from './src/button-edit.props'; diff --git a/packages/mobile-ui-vue/components/button-edit/src/button-edit.component.tsx b/packages/mobile-ui-vue/components/button-edit/src/button-edit.component.tsx index 1d958cfecce51368a074481737900d399529520c..8eed913d3b9ae41b7d85236424f225de1fc696c8 100644 --- a/packages/mobile-ui-vue/components/button-edit/src/button-edit.component.tsx +++ b/packages/mobile-ui-vue/components/button-edit/src/button-edit.component.tsx @@ -1,8 +1,8 @@ import { computed, defineComponent, ref, watch } from 'vue'; -import InputGroup from '@/components/input-group'; -import { useBem } from '@/components/common'; -import Popup from '@/components/popup'; -import Tag from '@/components/tag'; +import InputGroup from '@farris/mobile-ui-vue/input-group'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import Popup from '@farris/mobile-ui-vue/popup'; +import Tag from '@farris/mobile-ui-vue/tag'; import { BUTTON_EDIT_NAME, ButtonEditProps, buttonEditProps } from './button-edit.props'; export default defineComponent({ @@ -71,7 +71,7 @@ export default defineComponent({ readonly: props.readonly, editable: props.editable, class: props.inputClass, - rightIcon: props.readonly || 's-arrow', + rightIcon: props.readonly ? '' : props.rightIcon, textAlign: props.textAlign, showPadding: props.showPadding, formatter: props.formatter, diff --git a/packages/mobile-ui-vue/components/button-edit/src/button-edit.props.ts b/packages/mobile-ui-vue/components/button-edit/src/button-edit.props.ts index d151ece10514bfa642e59d00085d204ab378fce7..493da6ffb30a713e090b90b2f6c859b000ede308 100644 --- a/packages/mobile-ui-vue/components/button-edit/src/button-edit.props.ts +++ b/packages/mobile-ui-vue/components/button-edit/src/button-edit.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { inputCommonProps } from '@/components/input-group'; -import { popupProps } from '@/components/popup'; -import { tagProps, TagSize, TagType } from '@/components/tag'; +import { inputCommonProps } from '@farris/mobile-ui-vue/input-group'; +import { popupProps } from '@farris/mobile-ui-vue/popup'; +import { tagProps, TagSize, TagType } from '@farris/mobile-ui-vue/tag'; export const BUTTON_EDIT_NAME = 'FmButtonEdit'; @@ -15,6 +15,8 @@ export const buttonEditProps = { type: { type: String as PropType, default: 'text' }, + rightIcon: { type: String, default: 's-arrow' }, + editable: { type: Boolean, default: false }, inputClass: { type: String, default: undefined }, diff --git a/packages/mobile-ui-vue/components/button-edit/src/composition/use-button-edit-props.ts b/packages/mobile-ui-vue/components/button-edit/src/composition/use-button-edit-props.ts index 0db4a07b91cf59e38a0a75ece2259af3f07cd7fe..521f8775c91dbb3d2a2afe469e28133b9cbd071b 100644 --- a/packages/mobile-ui-vue/components/button-edit/src/composition/use-button-edit-props.ts +++ b/packages/mobile-ui-vue/components/button-edit/src/composition/use-button-edit-props.ts @@ -17,8 +17,9 @@ export const useButtonEditProps = (props: Omit, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[BUTTON_GROUP_REGISTERED_NAME] = ButtonGroup; - propsResolverMap[BUTTON_GROUP_REGISTERED_NAME] = propsResolver; -}; +withRegister(ButtonGroup, { name: BUTTON_GROUP_REGISTERED_NAME, propsResolverGenerator }); +// withRegisterDesigner(ButtonGroup, { name: BUTTON_GROUP_REGISTERED_NAME, propsResolverGenerator, designerComponent: InputGroupDesign }); export * from './src/button-group.props'; export { ButtonGroup }; diff --git a/packages/mobile-ui-vue/components/button-group/src/button-group.component.tsx b/packages/mobile-ui-vue/components/button-group/src/button-group.component.tsx index e79694a3b03d2f6ae7a247fbc6e1ba9de55063af..a4488f4c7eb77f303e1c67fd175b44507e53a4e8 100644 --- a/packages/mobile-ui-vue/components/button-group/src/button-group.component.tsx +++ b/packages/mobile-ui-vue/components/button-group/src/button-group.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@components/common'; -import FButton from '@components/button'; -import { Icon } from '@components/icon'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import FButton from '@farris/mobile-ui-vue/button'; +import { Icon } from '@farris/mobile-ui-vue/icon'; import { BUTTON_GROUP_NAME, ButtonItem, ButtonGroupProps, buttonGroupProps } from './button-group.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/button-group/src/button-group.props.ts b/packages/mobile-ui-vue/components/button-group/src/button-group.props.ts index 1c053e9fc569fea847257953022219b32ba58a0f..843146543818f5a09709a87770468dabd5928ea9 100644 --- a/packages/mobile-ui-vue/components/button-group/src/button-group.props.ts +++ b/packages/mobile-ui-vue/components/button-group/src/button-group.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { createPropsResolver } from '@components/dynamic-resolver'; -import { ButtonProps, ButtonSize, ButtonType } from '@components/button/src/button.props'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; +import { ButtonProps, ButtonSize, ButtonType } from '@farris/mobile-ui-vue/button/src/button.props'; import buttonSchema from './schema/button-group.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -43,7 +43,10 @@ export const buttonGroupProps = { vertical: { type: Boolean, default: false }, }; -export const propsResolver = createPropsResolver( +/** + * 按钮组属性处理器 + */ +export const propsResolverGenerator = getPropsResolverGenerator( buttonGroupProps, buttonSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/button/index.ts b/packages/mobile-ui-vue/components/button/index.ts index 2c5790ae8607ce0106d3836d147cc3df225c6ac1..f0dcd4d389a941de763a8275e39fd57dc4f8e80c 100644 --- a/packages/mobile-ui-vue/components/button/index.ts +++ b/packages/mobile-ui-vue/components/button/index.ts @@ -1,7 +1,7 @@ import { Plugin } from 'vue'; -import { withInstall, } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import ButtonInstallless from './src/button.component'; -import { propsResolver } from './src/button.props'; +import { propsResolverGenerator } from './src/button.props'; import ButtonDesign from './src/designer/button.design.component'; const BUTTON_REGISTERED_NAME = 'button'; @@ -9,18 +9,18 @@ const BUTTON_REGISTERED_NAME = 'button'; const Button = withInstall(ButtonInstallless); Button.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configResolverMap: Record, resolverMap: Record, registerContext: RegisterContext ) => { componentMap[BUTTON_REGISTERED_NAME] = Button; - propsResolverMap[BUTTON_REGISTERED_NAME] = propsResolver; + propsResolverMap[BUTTON_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; Button.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configResolverMap: Record, registerContext: RegisterContext ) => { componentMap[BUTTON_REGISTERED_NAME] = ButtonDesign; - propsResolverMap[BUTTON_REGISTERED_NAME] = propsResolver; + propsResolverMap[BUTTON_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; diff --git a/packages/mobile-ui-vue/components/button/src/button.component.tsx b/packages/mobile-ui-vue/components/button/src/button.component.tsx index 496721f41b1d4398fe3261a052a1155e66f5dd39..fc8dbfeb2bf0c076e9ff8ae1daba9e9bde88897d 100644 --- a/packages/mobile-ui-vue/components/button/src/button.component.tsx +++ b/packages/mobile-ui-vue/components/button/src/button.component.tsx @@ -1,6 +1,6 @@ import { CSSProperties, computed, defineComponent } from 'vue'; -import { Icon } from '@components/icon'; -import { useBem } from '@/components/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { BUTTON_NAME, ButtonProps, buttonProps } from './button.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/button/src/button.props.ts b/packages/mobile-ui-vue/components/button/src/button.props.ts index 08f95e4d48f5a2366a25cf9ce4319531b9642125..003aed6d5570c955b3d915a6432fddd4f231972d 100644 --- a/packages/mobile-ui-vue/components/button/src/button.props.ts +++ b/packages/mobile-ui-vue/components/button/src/button.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import buttonSchema from './schema/button.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -58,9 +58,10 @@ export const buttonProps = { export type ButtonProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( - buttonProps, - buttonSchema, - schemaMapper, - schemaResolver + +export const propsResolverGenerator = getPropsResolverGenerator( + buttonProps, + buttonSchema, + schemaMapper, + schemaResolver ); diff --git a/packages/mobile-ui-vue/components/button/src/designer/button.design.component.tsx b/packages/mobile-ui-vue/components/button/src/designer/button.design.component.tsx index 0d144b3ab11b4d18b8c370c2a3e4bc75ce382b16..49dc95cc6e42fe61d6d2c40a9b976c1db2921d42 100644 --- a/packages/mobile-ui-vue/components/button/src/designer/button.design.component.tsx +++ b/packages/mobile-ui-vue/components/button/src/designer/button.design.component.tsx @@ -17,7 +17,7 @@ import { computed, defineComponent, inject, onMounted, ref, SetupContext } from 'vue'; import { ButtonProps, buttonProps } from '../button.props'; import Button from '../..'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; import { useDesignerRules } from './use-designer-rules'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/button/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/button/src/designer/use-designer-rules.ts index 57b56ec4c0d3743423ed918b539b5e468d2a9911..023d0970499d317a91d5e19978430e0dcf1902a9 100644 --- a/packages/mobile-ui-vue/components/button/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/button/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { ref } from "vue"; import { ButtonProperty } from "../property-config/button.property-config"; -import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/button/src/property-config/button.property-config.ts b/packages/mobile-ui-vue/components/button/src/property-config/button.property-config.ts index 81df157ea734158c1e2347f59609094f47b7ec98..f343fdce8ba8d28d16b136e2c3c2184f443778b3 100644 --- a/packages/mobile-ui-vue/components/button/src/property-config/button.property-config.ts +++ b/packages/mobile-ui-vue/components/button/src/property-config/button.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class ButtonProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { @@ -10,12 +10,12 @@ export class ButtonProperty extends BaseControlProperty { // 外观 this.propertyConfig.categories['appearance'] = this.getAppearanceConfig(propertyData); // 行为 - this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData); + this.propertyConfig.categories['behavior'] = this.getButtonBehaviorConfig(propertyData); return this.propertyConfig; } - private getBehaviorConfig(propertyData) { + private getButtonBehaviorConfig(propertyData) { return { description: "基本信息", title: "行为", diff --git a/packages/mobile-ui-vue/components/cell/index.ts b/packages/mobile-ui-vue/components/cell/index.ts index cab6e87ce8d0aea6e9a07bc9f42442faf30f9ca7..7120eec6f480473a7fbd24bfd4127493b08fe63a 100644 --- a/packages/mobile-ui-vue/components/cell/index.ts +++ b/packages/mobile-ui-vue/components/cell/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import CellInstallless from './src/cell.component'; const Cell = withInstall(CellInstallless); diff --git a/packages/mobile-ui-vue/components/cell/src/cell.component.tsx b/packages/mobile-ui-vue/components/cell/src/cell.component.tsx index 143adb4f8136205004429902f039dbd2e62c84ea..051f2fec6518cb716b2d3f6f9f3a2ab5948cea4e 100644 --- a/packages/mobile-ui-vue/components/cell/src/cell.component.tsx +++ b/packages/mobile-ui-vue/components/cell/src/cell.component.tsx @@ -15,8 +15,8 @@ */ import { computed, defineComponent } from 'vue'; -import { isDef, resolveAsset, useBem } from '@components/common'; -import { Icon } from '@components/icon'; +import { isDef, resolveAsset, useBem } from '@farris/mobile-ui-vue/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; import { cellProps, CellProps, CELL_NAME } from './cell.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/checkbox-group/index.ts b/packages/mobile-ui-vue/components/checkbox-group/index.ts index 98107fb53f8ef8b20262f2994f04fc1132190cd1..d40dfb75597490720268935f6c3930bf325bce52 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/index.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/index.ts @@ -1,6 +1,6 @@ -import { withInstall } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import CheckboxGroupInstallless from './src/checkbox-group.component'; -import { propsResolver } from './src/checkbox-group.props'; +import { propsResolverGenerator } from './src/checkbox-group.props'; import CheckBoxGroupDesign from './src/designer/checkbox-group.design.component'; export * from './src/composition'; @@ -11,14 +11,8 @@ const CHECH_GROUP_REGISTERED_NAME = 'check-group'; const CheckboxGroup = withInstall(CheckboxGroupInstallless); -CheckboxGroup.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { - componentMap[CHECH_GROUP_REGISTERED_NAME] = CheckboxGroup; - propsResolverMap[CHECH_GROUP_REGISTERED_NAME] = propsResolver; -}; -CheckboxGroup.registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record) => { - componentMap[CHECH_GROUP_REGISTERED_NAME] = CheckBoxGroupDesign; - propsResolverMap[CHECH_GROUP_REGISTERED_NAME] = propsResolver; -}; +withRegister(CheckboxGroup, { name: CHECH_GROUP_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(CheckboxGroup, { name: CHECH_GROUP_REGISTERED_NAME, propsResolverGenerator, designerComponent: CheckBoxGroupDesign }); export { CheckboxGroup }; export default CheckboxGroup; diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.component.tsx b/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.component.tsx index 433b6b699d2d831755602dc0170f50f00b716242..844917718c10dc2dc2e174e62f8f84513752decc 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.component.tsx +++ b/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.component.tsx @@ -15,8 +15,8 @@ */ import { SetupContext, computed, defineComponent, ref, toRaw, watch } from 'vue'; -import { isArray, isString, useBem, useLink } from '@components/common'; -import Checkbox from '@components/checkbox'; +import { isArray, isString, useBem, useLink } from '@farris/mobile-ui-vue/common'; +import Checkbox from '@farris/mobile-ui-vue/checkbox'; import { CHECKBOX_GROUP_NAME, CheckboxGroupContext, diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.props.ts b/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.props.ts index 2a9cf19699dc7c22f4b65d2682c128c6db02009e..b823c42c2c9ea9cb39abcc83b02a4b8c6618374a 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.props.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/src/checkbox-group.props.ts @@ -1,9 +1,9 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { CheckerShape, CheckerShapeMap, CheckerType, CheckerTypeMap } from '@components/checker'; +import { CheckerShape, CheckerShapeMap, CheckerType, CheckerTypeMap } from '@farris/mobile-ui-vue/checker'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; import inputSchema from './schema/checkbox-group.schema.json'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; export type CheckboxItem = { disabled: boolean; @@ -50,5 +50,5 @@ export type CheckboxGroupContext = { updateChecked: (value: string | number, checked: boolean) => void; }; -export const propsResolver = createPropsResolver(checkboxGroupProps, inputSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(checkboxGroupProps, inputSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/designer/checkbox-group.design.component.tsx b/packages/mobile-ui-vue/components/checkbox-group/src/designer/checkbox-group.design.component.tsx index 9f634d3033796aebb543e5064f343b22f7eb468b..f0b846951aac97b3043d7a2193e94800c51e61c3 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/designer/checkbox-group.design.component.tsx +++ b/packages/mobile-ui-vue/components/checkbox-group/src/designer/checkbox-group.design.component.tsx @@ -16,7 +16,7 @@ */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; import { CheckboxGroup, checkboxGroupProps, CheckboxGroupProps } from '../..'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; import { useCheckBoxGroupProperty } from './use-designer-rules';; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/checkbox-group/src/designer/use-designer-rules.ts index 9186661baa91d148b6d5d3258e36d0e63bc99ac3..f65d878e31212e93249ce9b4a0bdd645ddbd6ae5 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { CheckBoxGroupProperty } from "../property-config/checkbox-group.property-config"; export function useCheckBoxGroupProperty(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/property-config/checkbox-group.property-config.ts b/packages/mobile-ui-vue/components/checkbox-group/src/property-config/checkbox-group.property-config.ts index 4a695c4d283310e91525f6d5195fd5fa5ed61c79..1ec557f202caab947e620809fd6a0fdd4889207a 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/property-config/checkbox-group.property-config.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/src/property-config/checkbox-group.property-config.ts @@ -1,53 +1,63 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { InputBaseProperty } from '@farris/mobile-ui-vue/common'; export class CheckBoxGroupProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } - - - getEditorProperties(propertyData: any) { - const self = this; - const editorProperties = self.getComponentConfig(propertyData, { type: "radio-group" }, { - direction: { - description: "", - title: "排列方向", - type: "enum", - editor: { - data: [{ "id": "horizontal", "name": "横向" }, - { "id": "vertical", "name": "纵向" }] - } - }, - data: { - description: "", - title: "数据", - type: "array", - $converter: "/converter/enum-data.converter", - ...self.getItemCollectionEditor(propertyData, propertyData.editor.valueField, propertyData.editor.textField), - // 这个属性,标记当属性变更得时候触发重新更新属性 - refreshPanelAfterChanged: true, - } - }); - editorProperties['setPropertyRelates'] = function (changeObject, newPropertyData, parameters) { - if (!changeObject) { - return; + getEditorProperties(propertyData: any) { + const self = this; + const editorProperties = self.getComponentConfig( + propertyData, + {}, + { + placeholder: { + visible: false + }, + disabled: { + visible: false + }, + data: { + description: '', + title: '数据', + type: 'array', + $converter: '/converter/enum-data.converter', + ...self.getItemCollectionEditor( + propertyData, + propertyData.editor.valueField, + propertyData.editor.textField + ), + // 这个属性,标记当属性变更得时候触发重新更新属性 + refreshPanelAfterChanged: true + }, + textField: { + description: '', + title: '文本字段', + type: 'string', + readonly: true + }, + valueField: { + description: '', + title: '值字段', + type: 'string', + readonly: true + } + }, + (changeObject, parameters) => { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'data': { + // 此类型默认可以编辑数据,要同步更新格式化 + if (propertyData.formatter) { + propertyData.formatter.data = [...changeObject.propertyValue]; } - switch (changeObject.propertyID) { - case 'data': { - if (parameters) { - propertyData.editor.valueField = parameters.valueField; - propertyData.editor.textField = parameters.nameField; - } - // 此类型默认可以编辑数据,要同步更新格式化 - if (propertyData.formatter) { - propertyData.formatter.data = [...changeObject.propertyValue]; - } - break; - } - } - }; - return editorProperties; - } - + break; + } + } + } + ); + return editorProperties; + } } diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/schema/checkbox-group.schema.json b/packages/mobile-ui-vue/components/checkbox-group/src/schema/checkbox-group.schema.json index 7cbd3c17fe86e63f3c50516c7b031f60063c454e..0a7a1f7c964b8c65cee01e7301995a5081266b5c 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/schema/checkbox-group.schema.json +++ b/packages/mobile-ui-vue/components/checkbox-group/src/schema/checkbox-group.schema.json @@ -64,6 +64,16 @@ "description": "", "type": "string", "default": "horizontal" + }, + "textField": { + "description": "", + "type": "string", + "default": "name" + }, + "valueField": { + "description": "", + "type": "string", + "default": "value" } }, "required": [ diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-mapper.ts index d8ccde7885d2af2e196fc46742ed7b6aadf853fe..cbfb41ab58450975f85c6e86786ba4f978d3437c 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance, resolveData } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance, resolveData } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/checkbox-group/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/checkbox/index.ts b/packages/mobile-ui-vue/components/checkbox/index.ts index 109b8ce19d3da3076a4a9fdafd9e357067aeb3a1..87d766bb1ffa0a24e47d3ce9eb7364746167cc00 100644 --- a/packages/mobile-ui-vue/components/checkbox/index.ts +++ b/packages/mobile-ui-vue/components/checkbox/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import CheckboxInstallless from './src/checkbox.component'; export * from './src/checkbox.props'; diff --git a/packages/mobile-ui-vue/components/checkbox/src/checkbox.component.tsx b/packages/mobile-ui-vue/components/checkbox/src/checkbox.component.tsx index 3c450b2412b9ffb44008456f20d79a1b22a54355..5510e7d5ae285149ae971fa619e98960addc0485 100644 --- a/packages/mobile-ui-vue/components/checkbox/src/checkbox.component.tsx +++ b/packages/mobile-ui-vue/components/checkbox/src/checkbox.component.tsx @@ -15,9 +15,9 @@ */ import { computed, defineComponent } from 'vue'; -import { useLink } from '@components/common'; -import { Checker, CheckerRoleMap, CheckerShapeMap } from '@components/checker'; -import { CHECKBOX_GROUP_NAME, CheckboxGroupContext } from '@components/checkbox-group'; +import { useLink } from '@farris/mobile-ui-vue/common'; +import { Checker, CheckerRoleMap, CheckerShapeMap } from '@farris/mobile-ui-vue/checker'; +import { CHECKBOX_GROUP_NAME, CheckboxGroupContext } from '@farris/mobile-ui-vue/checkbox-group'; import { CHECKBOX_NAME, CheckboxProps, diff --git a/packages/mobile-ui-vue/components/checkbox/src/checkbox.props.ts b/packages/mobile-ui-vue/components/checkbox/src/checkbox.props.ts index 7d6bda69a23d88d9f9da6587b8cbc587e988012e..6fe9e2469b6ff3b2cecd53c18b629bf03aecb525 100644 --- a/packages/mobile-ui-vue/components/checkbox/src/checkbox.props.ts +++ b/packages/mobile-ui-vue/components/checkbox/src/checkbox.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { checkerProps } from '@components/checker'; +import { checkerProps } from '@farris/mobile-ui-vue/checker'; export const CHECKBOX_NAME = 'fm-checkbox'; diff --git a/packages/mobile-ui-vue/components/checker/index.ts b/packages/mobile-ui-vue/components/checker/index.ts index b93d2b0e1112a67e932fa06abcd53c3e495a2490..e0c71a7d30382074ffe090cb45db657f7496e02e 100644 --- a/packages/mobile-ui-vue/components/checker/index.ts +++ b/packages/mobile-ui-vue/components/checker/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import CheckerInstallless from './src/checker.component'; export * from './src/checker.props'; diff --git a/packages/mobile-ui-vue/components/checker/src/checker.component.tsx b/packages/mobile-ui-vue/components/checker/src/checker.component.tsx index ff37ee4ebda39915806438668ef0068826d53164..82bb9de3ee55810878225d4f8d548f60626ab6e6 100644 --- a/packages/mobile-ui-vue/components/checker/src/checker.component.tsx +++ b/packages/mobile-ui-vue/components/checker/src/checker.component.tsx @@ -15,8 +15,8 @@ */ import { computed, defineComponent, ref, watch } from 'vue'; -import { Icon } from '@components/icon'; -import { useBem } from '@components/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { CheckerProps, checkerProps, CHECKER_NAME, CheckerTypeMap, CheckerShapeMap, CheckerRoleMap } from './checker.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/common/index.ts b/packages/mobile-ui-vue/components/common/index.ts index c6917cafadcc154e08e45791d964f58244936ad1..463f7bfd49f73cde6c6433052689d0bafdef3217 100644 --- a/packages/mobile-ui-vue/components/common/index.ts +++ b/packages/mobile-ui-vue/components/common/index.ts @@ -1,6 +1,4 @@ export * from './src/compositions'; export * from './src/utils'; -export * from './types'; - -export const FM_UI_PROVIDER_SERVICE_TOKEN = Symbol('UIProviderService'); - +export * from './src/types'; +export * from './src/properties'; diff --git a/packages/mobile-ui-vue/components/common/src/compositions/index.ts b/packages/mobile-ui-vue/components/common/src/compositions/index.ts index cde065de7d2b1150aa5db1d426d427f785b6bed5..d4ed1c00f4d18a1f3cb8e2ce525d22339fd25c3b 100644 --- a/packages/mobile-ui-vue/components/common/src/compositions/index.ts +++ b/packages/mobile-ui-vue/components/common/src/compositions/index.ts @@ -17,3 +17,4 @@ export * from './use-momentum'; export * from './use-scroll-parent'; export * from './use-resize-observer'; export * from './use-long-press'; +export * from './use-designer-component/use-designer-component'; diff --git a/packages/mobile-ui-vue/components/common/src/compositions/use-click-away/index.ts b/packages/mobile-ui-vue/components/common/src/compositions/use-click-away/index.ts index 6f8688c47aade61c88268b2acf6e7e3c0b7f2040..cc58ca6230ed7a15fd93e04d3367eecde470f396 100644 --- a/packages/mobile-ui-vue/components/common/src/compositions/use-click-away/index.ts +++ b/packages/mobile-ui-vue/components/common/src/compositions/use-click-away/index.ts @@ -1,6 +1,5 @@ import { Ref, unref } from 'vue'; import { useEventListener } from '../use-event-listener'; -import { inBrowser, initNodePath } from '../../utils'; export type ClickAwayOptions = { eventName?: string @@ -12,10 +11,6 @@ export function useClickAway( listener: EventListener, options: ClickAwayOptions = {}, ) { - if (!inBrowser) { - return; - } - const { eventName = 'click', active = true } = options; const isOutsideElement = (event: Event)=>{ diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-component.ts b/packages/mobile-ui-vue/components/common/src/compositions/use-designer-component/use-designer-component.ts similarity index 95% rename from packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-component.ts rename to packages/mobile-ui-vue/components/common/src/compositions/use-designer-component/use-designer-component.ts index fe7cd6300d123116c0ed82cef295d18318452840..0c31d5f8fd84dff1ecc319d40dbcdb61dda5def6 100644 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-component.ts +++ b/packages/mobile-ui-vue/components/common/src/compositions/use-designer-component/use-designer-component.ts @@ -1,7 +1,7 @@ import { Ref, ref } from "vue"; -import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext, UseDesignerRules } from "../types"; -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from "../../types"; -import { getSchemaByType } from '../../../../dynamic-resolver/src/schema-resolver'; +import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext, UseDesignerRules } from "../../types/designer-rule"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from "../../types/designer-component"; +import { getSchemaByTypeForDesigner } from '@farris/mobile-ui-vue/dynamic-resolver/src/resolver/schema/schema-resolver-design'; export function useDesignerComponent( elementRef: Ref, @@ -126,7 +126,7 @@ export function useDesignerComponent( */ function addNewChildComponentSchema(resolveContext: DraggingResolveContext, designerHostService: DesignerHostService) { const { componentType } = resolveContext; - let componentSchema = getSchemaByType(componentType, resolveContext, designerHostService) as ComponentSchema; + let componentSchema = getSchemaByTypeForDesigner(componentType, resolveContext, designerHostService) as ComponentSchema; if (designerRules && designerRules.onResolveNewComponentSchema) { componentSchema = designerRules.onResolveNewComponentSchema(resolveContext, componentSchema); } diff --git a/packages/mobile-ui-vue/components/common/src/compositions/use-expose/index.ts b/packages/mobile-ui-vue/components/common/src/compositions/use-expose/index.ts index 3a06d4ac4612d19a99e2ac5d6b74c74af4a50ee0..c555f0c8550b09f0fcb542f4058264d447c11d99 100644 --- a/packages/mobile-ui-vue/components/common/src/compositions/use-expose/index.ts +++ b/packages/mobile-ui-vue/components/common/src/compositions/use-expose/index.ts @@ -3,7 +3,7 @@ import { getCurrentInstance } from 'vue'; // expose public api export function useExpose(apis: Record) { const instance = getCurrentInstance(); - if (instance) { + if (instance && instance.proxy) { Object.assign(instance.proxy, apis); } } diff --git a/packages/mobile-ui-vue/components/common/src/compositions/use-lay-render/index.ts b/packages/mobile-ui-vue/components/common/src/compositions/use-lay-render/index.ts index 992df2d45b29c30736f210caf1f83f970ce74edf..0a8ce6baf78631277aa6ae4d2bee8c8026bbe4e1 100644 --- a/packages/mobile-ui-vue/components/common/src/compositions/use-lay-render/index.ts +++ b/packages/mobile-ui-vue/components/common/src/compositions/use-lay-render/index.ts @@ -1,4 +1,4 @@ -import { ref, watch, WatchSource } from 'vue'; +import { ref, VNode, watch, WatchSource } from 'vue'; export function useLazyRender(show: WatchSource) { const inited = ref(false); @@ -13,5 +13,5 @@ export function useLazyRender(show: WatchSource) { { immediate: true } ); - return (render: () => JSX.Element) => () => (inited.value ? render() : null); + return (render: () => VNode) => () => (inited.value ? render() : null); } diff --git a/packages/mobile-ui-vue/components/common/src/entity/base-property.ts b/packages/mobile-ui-vue/components/common/src/entity/base-property.ts deleted file mode 100644 index 8c9c9eb2c6784a3dc32b52e58b03a56c5a05b1b7..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/common/src/entity/base-property.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { DesignerComponentInstance, DgControl } from "@/components/designer-canvas"; -import { cloneDeep } from "lodash-es"; - -/** - * 控件属性基类 - */ -export class BaseControlProperty { - public componentId: string; - - public viewModelId: string; - - public eventsEditorUtils: any; - - public formSchemaUtils: any; - public formMetadataConverter: any; - public designViewModelUtils: any; - public designViewModelField: any; - public controlCreatorUtils: any; - public designerHostService: any; - - schemaService: any = null; - - metadataService: any = null; - - protected propertyConfig = { - type: 'object', - categories: {} - }; - - constructor(componentId: string, designerHostService: any) { - this.componentId = componentId; - this.designerHostService = designerHostService; - this.eventsEditorUtils = designerHostService['eventsEditorUtils']; - this.formSchemaUtils = designerHostService['formSchemaUtils']; - this.formMetadataConverter = designerHostService['formMetadataConverter']; - this.viewModelId = this.formSchemaUtils?.getViewModelIdByComponentId(componentId) || ''; - this.designViewModelUtils = designerHostService['designViewModelUtils']; - this.controlCreatorUtils = designerHostService['controlCreatorUtils']; - this.metadataService = designerHostService['metadataService']; - this.schemaService = designerHostService['schemaService']; - } - - getTableInfo() { - return this.schemaService?.getTableInfoByViewModelId(this.viewModelId); - } - - setDesignViewModelField(propertyData: any) { - const bindingFieldId = propertyData.binding && propertyData.binding.type === 'Form' && propertyData.binding.field; - // 视图模型中[字段更新时机]属性现在要在控件上维护,所以在控件上复制一份属性值 - if (bindingFieldId) { - if (!this.designViewModelField) { - const dgViewModel = this.designViewModelUtils.getDgViewModel(this.viewModelId); - this.designViewModelField = dgViewModel.fields.find(f => f.id === bindingFieldId); - } - propertyData.updateOn = this.designViewModelField?.updateOn; - } - } - - getBasicPropConfig(propertyData: any): any { - return { - description: 'Basic Information', - title: '基本信息', - properties: { - id: { - description: '组件标识', - title: '标识', - type: 'string', - readonly: true - }, - type: { - description: '组件类型', - title: '控件类型', - type: 'select', - editor: { - type: 'combo-list', - textField: 'name', - valueField: 'value', - editable: false, - data: [{ value: propertyData.type, name: DgControl[propertyData.type] && DgControl[propertyData.type].name }] - } - } - } - }; - - } - - - protected getAppearanceConfig(propertyData = null): any { - return { - title: "外观", - description: "Appearance", - properties: { - class: { - title: "class样式", - type: "string", - description: "组件的CSS样式", - $converter: "/converter/appearance.converter" - }, - style: { - title: "style样式", - type: "string", - description: "组件的样式", - $converter: "/converter/appearance.converter" - } - } - }; - } - - /** - * - * @param propertyId - * @param componentInstance - * @returns - */ - public updateElementByParentContainer(propertyId: string, componentInstance: DesignerComponentInstance) { - // 1、定位控件父容器 - const parentContainer = componentInstance && componentInstance.parent && componentInstance.parent['schema']; - if (!parentContainer) { - return; - } - const index = parentContainer.contents.findIndex(c => c.id === propertyId); - // 通过cloneDeep方式的触发更新 - const controlSchema = cloneDeep(parentContainer.contents[index]); - // 5、替换控件 - parentContainer.contents.splice(index, 1); - parentContainer.contents.splice(index, 0, controlSchema); - } - -} diff --git a/packages/mobile-ui-vue/components/common/src/entity/input-base-property.ts b/packages/mobile-ui-vue/components/common/src/entity/input-base-property.ts deleted file mode 100644 index e705e141babd1ad73cd0770dc49bbd56c190039b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/common/src/entity/input-base-property.ts +++ /dev/null @@ -1,285 +0,0 @@ -import { BaseControlProperty } from './base-property'; -import { DesignerComponentInstance } from "@/components/designer-canvas"; -import { SchemaDOMMapping } from "@/components/property-panel"; -import { canvasChanged } from "@/components/designer-canvas/src/composition/designer-canvas-changed"; -import { FormSchemaEntityFieldType$Type } from './entity-schema'; - -export class InputBaseProperty extends BaseControlProperty { - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } - - public getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { - // 基本信息 - this.propertyConfig.categories['basic'] = this.getBasicProperties(propertyData, componentInstance); - // 外观 - this.propertyConfig.categories['appearance'] = this.getAppearanceProperties(propertyData, componentInstance); - // 编辑器 - this.propertyConfig.categories['editor'] = this.getEditorProperties(propertyData); - return this.propertyConfig; - } - - public getBasicProperties(propertyData, componentInstance): any { - const self = this; - this.setDesignViewModelField(propertyData); - return { - description: 'Basic Information', - title: '基本信息', - properties: { - id: { - description: '组件标识', - title: '标识', - type: 'string', - readonly: true - }, - type: { - description: '编辑器类型', - title: '编辑器类型', - type: 'string', - refreshPanelAfterChanged: true, - $converter: '/converter/change-editor.converter', - editor: { - type: 'combo-list', - textField: 'value', - valueField: 'key', - editable: false, - data: self.designViewModelField ? SchemaDOMMapping.getEditorTypesByMDataType(self.designViewModelField.type?.name) : SchemaDOMMapping.getAllInputTypes() - } - }, - label: { - title: "标签", - type: "string", - $converter: '/converter/form-group-label.converter' - }, - binding: { - description: "绑定的表单字段", - title: "绑定", - editor: { - type: "binding-selector", - bindingType: { "enable": false }, - editorParams: { - componentSchema: propertyData, - needSyncToViewModel: true, - viewModelId: this.viewModelId, - designerHostService: this.designerHostService, - disableOccupiedFields: true - }, - textField: 'bindingField' - } - } - }, - setPropertyRelates(changeObject, prop) { - if (!changeObject) { - return; - } - switch (changeObject && changeObject.propertyID) { - case 'type': { - self.changeControlType(propertyData, changeObject, componentInstance); - break; - } - case 'label': { - changeObject.needRefreshControlTree = true; - break; - } - } - } - }; - } - public getAppearanceProperties(propertyData, componentInstance): any { - - const self = this; - return { - title: "外观", - description: "Appearance", - properties: { - class: { - title: "class样式", - type: "string", - description: "组件的CSS样式", - $converter: "/converter/appearance.converter" - }, - style: { - title: "style样式", - type: "string", - description: "组件的样式", - $converter: "/converter/appearance.converter" - } - }, - setPropertyRelates(changeObject, prop) { - if (!changeObject) { - return; - } - switch (changeObject && changeObject.propertyID) { - case 'class': - self.updateElementByParentContainer(propertyData.id, componentInstance); - break; - } - - } - }; - }; - - public getEditorProperties(propertyData): any { - return this.getComponentConfig(propertyData); - } - - - /** - * 卡片控件:切换控件类型后事件 - * @param propertyData 控件DOM属性 - * @param newControlType 新控件类型 - */ - private changeControlType(propertyData, changeObject, componentInstance: DesignerComponentInstance) { - const newControlType = changeObject.propertyValue; - - // 1、定位控件父容器 - const parentContainer = componentInstance && componentInstance.parent && componentInstance.parent['schema']; - if (!parentContainer) { - return; - } - - const index = parentContainer.contents.findIndex(c => c.id === propertyData.id); - const oldControl = parentContainer.contents[index]; - - let newControl; - // 2、记录绑定字段viewModel的变更 - if (this.designViewModelField) { - const dgViewModel = this.designViewModelUtils.getDgViewModel(this.viewModelId); - dgViewModel.changeField(this.designViewModelField.id, { - editor: { - $type: newControlType - }, - name: this.designViewModelField.name, - require: this.designViewModelField.require, - readonly: this.designViewModelField.readonly - }, false); - // 3、创建新控件 - newControl = this.controlCreatorUtils.setFormFieldProperty(this.designViewModelField, newControlType); - } - if (!newControl) { - newControl = this.controlCreatorUtils.createFormGroupWithoutField(newControlType); - } - // 4、保留原id样式等属性 - Object.assign(newControl, { - id: oldControl.id, - appearance: oldControl.appearance, - size: oldControl.size, - label: oldControl.label, - binding: oldControl.binding, - visible: oldControl.visible - }); - Object.assign(newControl.editor, { - isTextArea: newControl.isTextArea && oldControl.isTextArea, - placeholder: oldControl.editor?.placeholder, - holdPlace: oldControl.editor?.holdPlace, - readonly: oldControl.editor?.readonly, - required: oldControl.editor?.required, - }); - - // 5、替换控件 - parentContainer.contents.splice(index, 1); - parentContainer.contents.splice(index, 0, newControl); - componentInstance.schema = Object.assign(oldControl, newControl); - - // 6、暂时移除旧控件的选中样式(后续考虑更好的方式) - Array.from(document.getElementsByClassName('dgComponentSelected') as HTMLCollectionOf).forEach( - (element: HTMLElement) => element.classList.remove('dgComponentSelected') - ); - - Array.from(document.getElementsByClassName('dgComponentFocused') as HTMLCollectionOf).forEach( - (element: HTMLElement) => element.classList.remove('dgComponentFocused') - ); - // 7、触发刷新 - canvasChanged.value++; - - } - - public getComponentConfig(propertyData, info = {}, properties = {}, setPropertyRelates?: any) { - const editorBasic = Object.assign({ - description: "编辑器", - title: "编辑器", - type: "input-group", - $converter: "/converter/property-editor.converter" - }, info); - - const editorProperties = Object.assign({ - readonly: { - description: "", - title: "只读", - type: "boolean", - editor: { - enableClear: true, - editable: true - } - }, - disabled: { - description: "", - title: "禁用", - type: "boolean", - visible: false - }, - required: { - description: "", - title: "必填", - type: "boolean", - visible: false - }, - placeholder: { - description: "空值时,输入控件内的占位文本", - title: "提示文本", - type: "string", - visible: false - - } - }, properties); - - return { ...editorBasic, properties: { ...editorProperties }, setPropertyRelates }; - - } - - - /** - * 枚举项编辑器 - * @param propertyData - * @param valueField - * @param textField - * @returns - */ - protected getItemCollectionEditor(propertyData, valueField, textField) { - valueField = valueField || 'value'; - textField = textField || 'name'; - return { - editor: { - columns: [ - { field: valueField, title: '值', dataType: 'string' }, - { field: textField, title: '名称', dataType: 'string' }, - { field: 'disabled', title: '禁用', visible: false, dataType: 'boolean', editor: { type: 'switch' } }, - ], - type: "item-collection-editor", - valueField: valueField, - nameField: textField, - requiredFields: [valueField, textField], - uniqueFields: [valueField, textField], - readonly: this.checkEnumDataReadonly(propertyData) - } - }; - } - /** - * 判断枚举数据是否只读 - * 1、没有绑定信息或者绑定变量,可以新增、删除、修改 - * 2、绑定类型为字段,且字段为枚举字段,则不可新增、删除、修改枚举值。只能从be修改然后同步到表单上。 - * @param propertyData 下拉框控件属性值 - */ - private checkEnumDataReadonly(propertyData: any): boolean { - // 没有绑定信息或者绑定变量 - if (!propertyData.binding || propertyData.binding.type !== 'Form') { - return false; - } - if (this.designViewModelField && this.designViewModelField.type && - this.designViewModelField.type.$type === FormSchemaEntityFieldType$Type.EnumType) { - // 低代码、零代码,枚举字段均不可以改 - return true; - } - return false; - } -} diff --git a/packages/mobile-ui-vue/components/common/src/properties/base-property.ts b/packages/mobile-ui-vue/components/common/src/properties/base-property.ts new file mode 100644 index 0000000000000000000000000000000000000000..5dea5049f085210890fb0d08529f4817310b3d57 --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/properties/base-property.ts @@ -0,0 +1,373 @@ +import { cloneDeep } from "lodash-es"; +// import { refreshCanvas } from "../../../../common/src/composition/update-cancas"; +import { ExpressionProperty } from "./expression-property"; +import { usePropertyEditor } from "./use-property-editor"; +import { DgControl } from "./dg-control"; +import { DesignerComponentInstance, PropertyChangeObject } from "../types"; + +/** + * 控件属性基类 + */ +export class BaseControlProperty { + public componentId: string; + + public viewModelId: string; + + public eventsEditorUtils: any; + + public formSchemaUtils: any; + public formMetadataConverter: any; + public designViewModelUtils: any; + public designViewModelField: any; + public controlCreatorUtils: any; + public designerHostService: any; + + schemaService: any = null; + + metadataService: any = null; + + protected propertyConfig = { + type: 'object', + categories: {} + }; + + constructor(componentId: string, designerHostService: any) { + this.componentId = componentId; + this.designerHostService = designerHostService; + this.eventsEditorUtils = designerHostService['eventsEditorUtils']; + this.formSchemaUtils = designerHostService['formSchemaUtils']; + this.formMetadataConverter = designerHostService['formMetadataConverter']; + this.viewModelId = this.formSchemaUtils?.getViewModelIdByComponentId(componentId) || ''; + this.designViewModelUtils = designerHostService['designViewModelUtils']; + this.controlCreatorUtils = designerHostService['controlCreatorUtils']; + this.metadataService = designerHostService['metadataService']; + this.schemaService = designerHostService['schemaService']; + } + + getTableInfo() { + return this.schemaService?.getTableInfoByViewModelId(this.viewModelId); + } + + setDesignViewModelField(propertyData: any) { + const bindingFieldId = propertyData.binding && propertyData.binding.type === 'Form' && propertyData.binding.field; + // 视图模型中[字段更新时机]属性现在要在控件上维护,所以在控件上复制一份属性值 + if (bindingFieldId) { + if (!this.designViewModelField) { + const dgViewModel = this.designViewModelUtils.getDgViewModel(this.viewModelId); + this.designViewModelField = dgViewModel.fields.find(f => f.id === bindingFieldId); + } + propertyData.updateOn = this.designViewModelField?.updateOn; + } + } + + getBasicPropConfig(propertyData: any): any { + return { + description: 'Basic Information', + title: '基本信息', + properties: { + id: { + description: '组件标识', + title: '标识', + type: 'string', + readonly: true + }, + type: { + description: '组件类型', + title: '控件类型', + type: 'select', + editor: { + type: 'combo-list', + textField: 'name', + valueField: 'value', + idField: 'value', + editable: false, + data: [{ value: propertyData.type, name: DgControl[propertyData.type] && DgControl[propertyData.type].name }] + } + } + } + }; + + } + + + protected getAppearanceConfig(propertyData = null, properties = {}, setPropertyRelates?: (changeObject, propertyData, parameters) => any): any { + const appearanceBasic = { + title: "外观", + description: "Appearance", + }; + const appearancePoperties = { + class: { + title: "class样式", + type: "string", + description: "组件的CSS样式", + $converter: "/converter/appearance.converter" + }, + style: { + title: "style样式", + type: "string", + description: "组件的样式", + $converter: "/converter/appearance.converter" + } + + }; + for (const key in properties) { + // 合并属性,保留原属性值 + appearancePoperties[key] = Object.assign(appearancePoperties[key] || {}, properties[key]); + } + return { + ...appearanceBasic, properties: { ...appearancePoperties }, setPropertyRelates(changeObject, parameters: any) { + if (!changeObject) { + return; + } + if (!changeObject) { + return; + } + switch (changeObject && changeObject.propertyID) { + case 'class': case 'style': { + changeObject.needChangeCanvas = true; + break; + } + } + if (setPropertyRelates) { + setPropertyRelates(changeObject, propertyData, parameters); + } + } + + }; + } + protected getPropertyEditorParams(propertyData, propertyTypes: any = [], propertyName = 'visible', constInfos = {}, variableInfos = {}) { + const { getVariables, getControlName, getStateMachines } = usePropertyEditor(this.designerHostService); + const targetType = this.getRealTargetType(propertyData); + const newPropertyTypes = propertyTypes && propertyTypes.length > 0 ? propertyTypes : ['Const', 'Variable', 'Custom', 'StateMachine', 'Expression']; + const resultProperty = { + type: "property-editor", + propertyTypes: newPropertyTypes + }; + newPropertyTypes.map(item => { + switch (item) { + case 'Const': + Object.assign(resultProperty, { + constType: 'enum', + constEnums: [{ id: true, name: '是' }, { id: false, name: '否' }] + }, constInfos); + break; + case 'Expression': + resultProperty['expressionConfig'] = this.getExpressionOptions(propertyData, targetType, propertyName); + break; + case 'StateMachine': + resultProperty['stateMachines'] = getStateMachines(this.viewModelId); + break; + case 'Variable': + Object.assign(resultProperty, { + controlName: getControlName(propertyData), + newVariablePrefix: 'is', + newVariableType: 'Boolean', + variables: getVariables(this.viewModelId) + }, variableInfos); + break; + } + }); + return resultProperty; + } + + protected getVisibleProperty(propertyData, position = '') { + const editor = this.getPropertyEditorParams(propertyData, position === 'gridFieldEditor' ? ['Const', 'Expression'] : ['Const', 'Variable', 'Custom', 'StateMachine', 'Expression'], 'visible'); + return { + visible: { + title: "是否可见", + type: "boolean", + description: "运行时组件是否可见", + editor + } + }; + } + /** + * 获取行为 + * @param propertyData + * @param viewModelId + * @returns + */ + public getBehaviorConfig(propertyData: any, position = '', properties = {}, setPropertyRelates?: any): any { + const behaviorBasic = { + title: "行为", + description: "" + }; + const behaviorPoperties = this.getVisibleProperty(propertyData, position); + for (const key in properties) { + // 合并属性,保留原属性值 + behaviorPoperties[key] = Object.assign(behaviorPoperties[key] || {}, properties[key]); + } + const self = this; + + return { + ...behaviorBasic, properties: { ...behaviorPoperties }, setPropertyRelates(changeObject, parameters: any) { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'disabled': + case 'readonly': + case 'visible': + self.afterMutilEditorChanged(propertyData, changeObject); + break; + } + if (setPropertyRelates) { + setPropertyRelates(changeObject, parameters); + } + } + + }; + } + /** + * 当多值编辑器变更时 + * @param propertyData + * @param changeObject + */ + public afterMutilEditorChanged(propertyData, changeObject) { + // 变量 + this.addNewVariableToViewModel(changeObject, this.viewModelId); + // 更新表达式 + this.updateExpressionValue(changeObject); + // 清空表达式 + this.clearExpression(changeObject, propertyData); + } + + /** + * 更新element + * @param propertyId + * @param componentInstance + * @returns + */ + public updateElementByParentContainer(propertyId: string, componentInstance: DesignerComponentInstance) { + // 1、定位控件父容器 + const parentContainer = componentInstance && componentInstance.parent && componentInstance.parent['schema']; + if (!parentContainer) { + return; + } + const index = parentContainer.contents.findIndex(c => c.id === propertyId); + // 通过cloneDeep方式的触发更新 + const controlSchema = cloneDeep(parentContainer.contents[index]); + // 5、替换控件 + parentContainer.contents.splice(index, 1); + parentContainer.contents.splice(index, 0, controlSchema); + // refreshCanvas(); + } + + /** + * 属性编辑器,在编辑过程中会新增变量,此处需要将新增的变量追加到ViewModel中 + * @param changeObject + * @param viewModelId + * @returns + */ + public addNewVariableToViewModel(changeObject: PropertyChangeObject, viewModelId: string) { + const newPropertyValue = changeObject.propertyValue; + // 1、判断当前属性值是否为对象 + const isObject = newPropertyValue && typeof newPropertyValue === 'object'; + if (!isObject) { + return; + } + + // 2、判断是否为新变量 + const isNewVariable = newPropertyValue.type === 'Variable' && newPropertyValue.isNewVariable; + if (!isNewVariable) { + return; + } + + // 3、构造变量结构 + const newVariable = { + id: newPropertyValue.field, + category: 'locale', + code: newPropertyValue.fullPath, + name: newPropertyValue.fullPath, + type: newPropertyValue.newVariableType || 'String' + }; + delete newPropertyValue.newVariableType; + delete newPropertyValue.isNewVariable; + + // 4、把新变量添加到ViewModel中 + const existedVariable = this.formSchemaUtils.getVariableByCode(newVariable.code); + if (!existedVariable) { + const viewModel = this.formSchemaUtils.getViewModelById(viewModelId); + viewModel.states.push(newVariable); + } + } + + /** + * 更新表达式到expressions节点 + * @param changeObject + */ + public updateExpressionValue(changeObject: PropertyChangeObject) { + const newPropertyValue = changeObject.propertyValue; + const newValueType = newPropertyValue && newPropertyValue.type; + + // 1、判断是否需要更新表达式 + const needUpdateExpression = newValueType === 'Expression' && newPropertyValue.expressionInfo; + if (!needUpdateExpression) { + return; + } + + const { expressionId, expressionInfo } = newPropertyValue; + const { targetId, targetType, expressionType, value, message } = expressionInfo; + const module = this.formSchemaUtils.getModule(); + module.expressions ??= []; + const { expressions } = module; + + // 2、获取目标表达式,如果不存在,则创建一个空的目标表达式 + let targetExpression = expressions.find(expression => expression.target === targetId); + if (!targetExpression) { + targetExpression = { target: targetId, rules: [], targetType }; + expressions.push(targetExpression); + } + + // 3、更新表达式 + const expressionItem = targetExpression.rules.find(rule => rule.type === expressionType); + if (expressionItem) { + expressionItem.value = value; + expressionItem.message = message; + } else { + const newExpressionRule = { id: expressionId, type: expressionType, value, message }; + targetExpression.rules.push(newExpressionRule); + } + delete newPropertyValue.expressionInfo; + } + + /** + * 属性类型切换为非表达式后,清除原表达式 + * @param changeObject + * @param propertyData + * @returns + */ + clearExpression(changeObject: PropertyChangeObject, propertyData: any) { + const newPropertyValue = changeObject.propertyValue; + const isExpression = newPropertyValue && newPropertyValue.type === 'Expression'; + // 1、如果为当前属性为表达式,则不需要清空 + if (isExpression) { + return; + } + + // 2、属性值不是表达式后,需要清空表达式 + const expressionType = changeObject.propertyID; + const expressions = this.formSchemaUtils.getExpressions(); + + const targetId = propertyData.binding ? propertyData.binding.field : propertyData.id; + const targetExpression = expressions.find(expression => expression.target === targetId); + if (!targetExpression || !targetExpression.rules) { + return; + } + targetExpression.rules = targetExpression.rules.filter(rule => rule.type !== expressionType); + } + + getExpressionOptions(propertyData: any, targetType: 'Field' | 'Button' | 'Container', expressionType: string) { + return new ExpressionProperty(this.formSchemaUtils).getExpressionOptions(propertyData, targetType, expressionType); + } + + getRealTargetType(propertyData: any,) { + if (['response-toolbar-item', 'tab-toolbar-item', 'section-toolbar-item'].indexOf(propertyData.type) > -1) { + return 'Button'; + } + if (propertyData.binding && propertyData.binding.field) { + return 'Field'; + } + return 'Container'; + } +} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/dg-control.ts b/packages/mobile-ui-vue/components/common/src/properties/dg-control.ts similarity index 80% rename from packages/mobile-ui-vue/components/designer-canvas/src/composition/dg-control.ts rename to packages/mobile-ui-vue/components/common/src/properties/dg-control.ts index bc35a129a09810fa0d669460adf5150562079ffb..e230774a9f909ea9f0adfb04e5a4ec126593b1cc 100644 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/dg-control.ts +++ b/packages/mobile-ui-vue/components/common/src/properties/dg-control.ts @@ -25,24 +25,26 @@ export const DgControl = { 'lookup': { type: 'lookup', name: '帮助', icon: 'LookupEdit' }, - 'number-spinner': { type: 'number-spinner', name: '数值', icon: 'NumericBox' }, + 'number-input': { type: 'number-input', name: '数值', icon: 'NumericBox' }, 'date-picker': { type: 'date-picker', name: '日期', icon: 'DateBox' }, + 'datetime-picker': { type: 'datetime-picker', name: '日期时间', icon: 'DateBox' }, + 'switch': { type: 'switch', name: '开关', icon: 'SwitchField' }, 'radio-group': { type: 'radio-group', name: '单选组', icon: 'RadioGroup' }, + 'check-group': { type: 'check-group', name: '多选组', icon: 'CheckGroup' }, + 'check-box': { type: 'check-box', name: '复选框', icon: 'CheckBox' }, - 'check-group': { type: 'check-group', name: '复选框组', icon: 'CheckGroup' }, - 'combo-list': { type: 'combo-list', name: '下拉列表', icon: 'EnumField' }, 'form': { type: 'form', name: '卡片面板', icon: 'Form' }, - 'navigation-bar': { type: 'navigation-bar', name: '导航栏', icon: 'NavBar' }, + 'navbar': { type: 'navbar', name: '导航栏', icon: 'NavBar' }, - 'enum-field': { type: 'enum-field', name: '选择器', icon: 'EnumField' }, + 'picker': { type: 'picker', name: '选择器', icon: 'EnumField' }, }; diff --git a/packages/mobile-ui-vue/components/common/src/properties/expression-property.ts b/packages/mobile-ui-vue/components/common/src/properties/expression-property.ts new file mode 100644 index 0000000000000000000000000000000000000000..24b91f61777f5ec22452f8d872d6b9f879d98706 --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/properties/expression-property.ts @@ -0,0 +1,385 @@ +export interface RuleModel { + id: string; + type: 'compute' | 'dependency' | 'validate' | 'visible' | 'readonly' | 'required' | 'dataPicking' | string; + value: string; + message?: string; + elementId?: string; + messageType?: string; +} + +export interface ExpressionModel { + target: string; + rules: Array; + targetType: string; +} + + +export class ExpressionProperty { + + private sessionVariables = [ + { + key: "CurrentSysOrgName", + name: "当前组织Name", + description: "当前组织Name" + }, + // { + // key: "CurrentSysOrgCode", + // name: "当前组织Code", + // description: "当前组织Code" + // }, + { + key: "CurrentSysOrgId", + name: "当前组织Id", + description: "当前组织Id" + }, + { + key: "CurrentUserName", + name: "当前用户Name", + description: "当前用户Name" + }, + { + key: "CurrentUserCode", + name: "当前用户Code", + description: "当前用户Code" + }, + { + key: "CurrentUserId", + name: "当前用户Id", + description: "当前用户Id" + }, + { + key: "CurrentLanguage", + name: "当前语言编号", + description: "当前登录的语言编号,例如简体中文返回'zh-CHS',英文返回'en',繁体中文'zh-CHT'" + } + ]; + + constructor(private formSchemaService: any) { + } + + private getExpressionRule(expressionId: any, rultType: string) { + const expressions = this.formSchemaService.getExpressions(); + if (!expressions) { + return ''; + } + const expressionItem = expressions.find(item => item.target === expressionId); + if (!expressionItem) { + return ''; + } + + const ruleItem = expressionItem.rules.find(item => item.type === rultType); + if (!ruleItem) { + return ''; + } + + return ruleItem; + } + + // 获取上下文表单变量 + private getContextFormVariables() { + const { module } = this.formSchemaService.getFormSchema(); + if (!module.viewmodels || module.viewmodels.length === 0) { + return []; + } + + const rootViewModelId = this.formSchemaService.getRootViewModelId(); + const viewModel = this.formSchemaService.getViewModelById(rootViewModelId); + + if (!viewModel || !viewModel.states || viewModel.states.length === 0) { + return []; + } + + const contextEntities: any = []; + viewModel.states.forEach(variable => { + if (variable.category === 'remote') { + contextEntities.push({ + key: variable.code, + name: variable.name, + description: variable.name + }); + } + }); + return contextEntities; + } + + private createTreeNode(element: any, parentCodes: string[], fieldName = 'label') { + return { + id: element.id, + name: element.name, + bindingPath: element[fieldName], + parents: parentCodes + }; + } + + + private buildEntityFieldsTreeData(fields: any[] | null = null, parentCodes: string[]): any[] { + const treeData: any[] = []; + fields?.forEach(element => { + const nodeData = this.createTreeNode(element, parentCodes); + + let children: any[] = []; + if (element.type?.fields) { + children = this.buildEntityFieldsTreeData(element.type.fields, [...parentCodes, element.label]); + } + + treeData.push({ + data: nodeData, + children, + expanded: true + }); + }); + return treeData; + } + + private buildChildEntityTreeData(entities: any[] | null = null, parentCodes: string[]): any[] { + const treeData: any[] = []; + entities?.forEach(element => { + const nodeData = this.createTreeNode(element, parentCodes); + + const children = this.buildEntityFieldsTreeData(element.type?.fields, [...parentCodes, element.label]); // 可选链 + const childEntities = this.buildChildEntityTreeData(element.type?.entities, [...parentCodes, element.label]); // 可选链 + + if (childEntities?.length) { // 空值检查 + children?.push(...childEntities); + } + + treeData.push({ + data: nodeData, + children: children || [], // 空值回退 + expanded: true + }); + }); + return treeData; + } + + private getEntitiesTreeData() { + const entities = this.formSchemaService.getSchemaEntities(); + if (!entities?.length) { // 空值检查 + return []; + } + + const mainTable = entities[0]; + if (!mainTable?.type) { return []; } // 空值检查 + + const childFields = this.buildEntityFieldsTreeData(mainTable.type.fields, [mainTable.code]); + const childEntities = this.buildChildEntityTreeData(mainTable.type.entities, [mainTable.code]); + + if (childEntities?.length) { // 空值检查 + childFields?.push(...childEntities); + } + + return { + entityCode: mainTable.code, + fields: [{ + data: this.createTreeNode(mainTable, [], 'code'), + children: childFields || [] + }] + }; + } + + + getEntitiesAndVariables() { + return { + entities: this.getEntitiesTreeData(), + variables: { + session: { + name: '系统变量', + items: this.sessionVariables + }, + forms: { + name: '表单变量', + items: this.getContextFormVariables() + } + } + }; + } + + private onBeforeOpenExpression(propertyData: any, expressionType: string, targetType: string) { + const expressionId = targetType === 'Field' ? propertyData.binding.field : propertyData.id; + const rule = this.getExpressionRule(expressionId, expressionType); + const entitiesAndVariables = this.getEntitiesAndVariables(); + const data: any = { + message: ['validate', 'required','dataPicking'].includes(expressionType) && rule ? rule.message : '', + ...entitiesAndVariables + }; + + if (rule.messageType != null) { + data.messageType = rule.messageType; + } + + return data; + } + + private buildRule(targetId, expressionObject: Record, ruleType: string, controlId?: string) { + const { expression: expressionValue, message, messageType } = expressionObject; + const rule: RuleModel = { + id: `${targetId}_${ruleType}`, + type: ruleType, + value: expressionValue, + message, + messageType + }; + + if (ruleType === 'validate' && controlId) { + rule.elementId = controlId; + } + + return rule; + } + + private getExpressionData(): Array { + const { expressions } = this.formSchemaService.getFormSchema().module; + return expressions || []; + } + + private updateExpression(propertyData: any, + targetType: 'Field' | 'Button' | 'Container', + expressionObject: Record, ruleType: string) { + const targetId = targetType === 'Field' ? propertyData.binding.field : propertyData.id; + const newRule = this.buildRule(targetId, expressionObject, ruleType, propertyData.type === 'form-group' ?propertyData.id: ''); + + const currentExpressiones = this.getExpressionData(); + let expressionItem = currentExpressiones.find((item: ExpressionModel) => { + return item.targetType === targetType && item.target === targetId; + }); + + // 提取重复逻辑:判断 value 是否为空 + const isValueEmpty = (rule: RuleModel): boolean => rule.value.trim() === ''; + + if (expressionItem) { + const ruleItem = expressionItem.rules.find((rule) => rule.id === newRule.id); + if (ruleItem) { + if (isValueEmpty(newRule)) { + expressionItem.rules = expressionItem.rules.filter((rule) => rule.id !== newRule.id); + } else { + ruleItem.value = newRule.value; + ruleItem.message = newRule.message; + + if (ruleType === 'dataPicking') { + ruleItem.messageType = newRule.messageType; + } + + if (ruleType === 'validate' && propertyData.type === 'form-group') { + ruleItem.elementId = propertyData.id; + } + } + } else { + if (isValueEmpty(newRule)) { + return null; + } + + expressionItem.rules = expressionItem.rules || []; + expressionItem.rules.push(newRule); + } + } else { + + if (isValueEmpty(newRule)) { + return null; + } + + expressionItem = { + target: `${targetId}`, + rules: [newRule], + targetType: targetType + }; + + } + return expressionItem; + } + + private expressionNames = { + compute: '计算表达式', + dependency: '依赖表达式', + validate: '验证表达式', + dataPicking: '帮助前表达式', + visible: '可见表达式', + readonly: '只读表达式', + required: '必填表达式' + }; + + private getExpressionConverter = (expressionId: string, ruleType?: string) => { + return { + convertFrom: (schema: Record, propertyKey: string, schemaService, componentId) => { + const rule = schemaService.getExpressionRuleValue(expressionId, ruleType || propertyKey); + return rule && rule.value || ''; + }, + convertTo: (schema: Record, propertyKey: string, propertyValue: any[], + schemaService, componentId + ) => { + schemaService.updateExpression(propertyValue); + } + }; + }; + + private getExpressionEditorOptions(propertyData, targetType: 'Field' | 'Button' | 'Container', + expressionTypes: string[], callback?: (rule: Record) => void) { + return expressionTypes.reduce((expressions: Record, name: string) => { + const expressionId = targetType === 'Field' ? propertyData?.binding?.field : propertyData.id; + expressions[name] = { + hide: targetType === 'Field' ? !!propertyData?.binding?.field : false, + description: "", + title: this.expressionNames[name], + type: "string", + $converter: this.getExpressionConverter(expressionId), + editor: { + type: "expression-editor", + singleExpand: false, + dialogTitle: `${this.expressionNames[name]}编辑器`, + showMessage: name === 'validate' || name === 'dataPicking', + showMessageType: name === 'dataPicking', + beforeOpen: () => { + return this.onBeforeOpenExpression(propertyData, name, targetType); + }, + onSubmitModal: (expressionObject: any) => { + const expressionData: any = this.updateExpression(propertyData, targetType, expressionObject, name); + if (callback) { + const rule = this.buildRule(expressionId, expressionObject, name); + callback(rule); + } + return expressionData; + } + } + }; + + return expressions; + }, {}); + } + + private getExpressionInfo(propertyData: any, targetType: 'Field' | 'Button' | 'Container', expressionType: string) { + const targetId = targetType === 'Field' ? propertyData.binding.field : propertyData.id; + const expressionRule = this.getExpressionRule(targetId, expressionType); + const expressionInfo = { + value: expressionRule && expressionRule.value, + message: expressionRule && expressionRule.message, + targetId, + targetType, + expressionType + }; + return expressionInfo; + } + + getExpressionConfig(propertyData: any, type: 'Field' | 'Button' | 'Container', + expressionTypes: string[] = ['compute', 'dependency', 'validate'], + callback?: (rule: Record) => void) { + return { + description: "表达式", + title: "表达式", + properties: { + ...this.getExpressionEditorOptions(propertyData, type, expressionTypes, callback) + } + }; + } + + getExpressionOptions(propertyData: any, targetType: 'Field' | 'Button' | 'Container', expressionType: string) { + const expressionInfo = this.getExpressionInfo(propertyData, targetType, expressionType); + return { + dialogTitle: `${this.expressionNames[expressionType]}编辑器`, + singleExpand: false, + showMessage: expressionType === 'require', + beforeOpen: () => { + return this.onBeforeOpenExpression(propertyData, expressionType, targetType); + }, + expressionInfo + }; + } +} diff --git a/packages/mobile-ui-vue/components/common/src/properties/index.ts b/packages/mobile-ui-vue/components/common/src/properties/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..0e938d51c5dccacbf348f7ec126d112399644ee0 --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/properties/index.ts @@ -0,0 +1,5 @@ +export * from './dg-control'; +export { SchemaDOMMapping } from './schema-dom-mapping'; +export { BaseControlProperty } from './base-property'; +export { InputBaseProperty } from './input-base-property'; +export { ToolbarItemProperty } from './toolbar-item.property'; \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/input-base-property.ts b/packages/mobile-ui-vue/components/common/src/properties/input-base-property.ts similarity index 46% rename from packages/mobile-ui-vue/components/property-panel/src/composition/entity/input-base-property.ts rename to packages/mobile-ui-vue/components/common/src/properties/input-base-property.ts index 32aad5db2580bf5df2fe79f3391722ca0ee3a93c..58894cf7b1ada4ed147df3fa3e73cbc2441b887c 100644 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/input-base-property.ts +++ b/packages/mobile-ui-vue/components/common/src/properties/input-base-property.ts @@ -1,36 +1,48 @@ - + import { BaseControlProperty } from "./base-property"; import { SchemaDOMMapping } from './schema-dom-mapping'; -import { canvasChanged } from '../../../../designer-canvas/src/composition/designer-canvas-changed'; -import { DesignerComponentInstance } from "../../../../designer-canvas/src/types"; -import { FormUnifiedColumnLayout } from "../type"; -import { - ResponseFormLayoutContext, - UseResponseLayoutEditorSetting, -} from "@/components/response-layout-editor"; -import { useResponseLayoutEditorSetting } from "../../../../response-layout-editor/src/composition/converter/use-response-layout-editor-setting"; -import { FormSchemaEntityFieldType$Type } from "@/components/common"; +// import { canvasChanged } from '../../../../common/src/composition/common-changed'; + +import { ExpressionProperty } from "./expression-property"; +import { FormSchemaEntityField$Type, FormSchemaEntityFieldType$Type, FormVariable } from "../types/entity-schema"; +import { DesignerComponentInstance, FormBindingType, FormPropertyChangeObject } from "../types"; +import { DgControl } from "./dg-control"; export class InputBaseProperty extends BaseControlProperty { - public responseLayoutEditorFunction: UseResponseLayoutEditorSetting; + /** 控件绑定的变量 */ + public bindingVarible?: FormVariable; + constructor(componentId: string, designerHostService: any) { super(componentId, designerHostService); - this.responseLayoutEditorFunction = useResponseLayoutEditorSetting(this.formSchemaUtils); } - - public getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { + private getCommonPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance | null) { // 基本信息 this.propertyConfig.categories['basic'] = this.getBasicProperties(propertyData, componentInstance); // 外观 this.propertyConfig.categories['appearance'] = this.getAppearanceProperties(propertyData, componentInstance); + this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData); // 编辑器 this.propertyConfig.categories['editor'] = this.getEditorProperties(propertyData); + // 表达式编辑器 + this.propertyConfig.categories['expressons'] = this.getExpressionConfig(propertyData, 'Field'); + } + public getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { + this.getCommonPropertyConfig(propertyData, componentInstance); + // 事件 暂不支持 + // this.propertyConfig.categories['eventsEditor'] = this.getEventPropertyConfig(propertyData); return this.propertyConfig; } - + public getGridFieldEdtiorPropConfig(propertyData: any, componentInstance: DesignerComponentInstance | null) { + this.propertyConfig.categories = {}; + this.getCommonPropertyConfig(propertyData, componentInstance); + // 事件 暂不支持 + // this.propertyConfig.categories['eventsEditor'] = this.getEventPropertyConfig(propertyData, 'gridFieldEditor'); + return this.propertyConfig.categories; + } public getBasicProperties(propertyData, componentInstance): any { const self = this; this.setDesignViewModelField(propertyData); + const { canChangeControlType, editorTypeList } = this.getAvailableEditorType(propertyData); return { description: 'Basic Information', title: '基本信息', @@ -45,15 +57,16 @@ export class InputBaseProperty extends BaseControlProperty { description: '编辑器类型', title: '编辑器类型', type: 'string', - refreshPanelAfterChanged: true, $converter: '/converter/change-editor.converter', editor: { type: 'combo-list', textField: 'value', valueField: 'key', + idField: 'key', editable: false, - data: self.designViewModelField ? SchemaDOMMapping.getEditorTypesByMDataType(self.designViewModelField.type?.name) : SchemaDOMMapping.getAllInputTypes() - } + data: editorTypeList, + readonly: !canChangeControlType + }, }, label: { title: "标签", @@ -74,10 +87,11 @@ export class InputBaseProperty extends BaseControlProperty { disableOccupiedFields: true }, textField: 'bindingField' - } + }, + refreshPanelAfterChanged: true } }, - setPropertyRelates(changeObject, prop) { + setPropertyRelates(changeObject, prop, paramters: any) { if (!changeObject) { return; } @@ -90,10 +104,72 @@ export class InputBaseProperty extends BaseControlProperty { changeObject.needRefreshControlTree = true; break; } + case 'binding': { + self.changeBindingField(propertyData, changeObject, paramters); + break; + } } } }; } + + /** + * 校验控件是否支持切换类型 + * @param control 控件 + */ + private checkCanChangeControlType(propertyData: any, viewModelId: string): boolean { + // 没有绑定信息的控件 + if (!propertyData.binding) { + return false; + } + + if (propertyData.binding.type === 'Variable') { + this.bindingVarible = this.formSchemaUtils.getVariableById(propertyData.binding.field); + // vm中已移除的变量 + if (!this.bindingVarible) { + return false; + } + } else { + // schema中已移除的字段 或者绑定复杂类型的字段 + if (!this.designViewModelField || this.designViewModelField.$type !== FormSchemaEntityField$Type.SimpleField) { + return false; + } + } + return true; + + } + /** + * 获取可选的编辑器类型 + */ + private getAvailableEditorType(propertyData: any) { + const canChangeControlType = this.checkCanChangeControlType(propertyData, this.viewModelId); + if (!canChangeControlType) { + return { + canChangeControlType: false, + editorTypeList: [{ + key: propertyData.editor.type, + value: DgControl[propertyData.editor.type]?.name || propertyData.editor.type + }] + }; + } + + let editorTypeList: any = []; + if (this.designViewModelField && this.designViewModelField.$type === FormSchemaEntityField$Type.SimpleField) { + // 绑定字段 + editorTypeList = SchemaDOMMapping.getEditorTypesByMDataType(this.designViewModelField.type.name); + } else if (this.bindingVarible) { + // 绑定变量 + editorTypeList = SchemaDOMMapping.getEditorTypesByMDataType(this.bindingVarible.type); + } + return { canChangeControlType, editorTypeList }; + } + + public changeBindingField(propertyData: any, changeObject: FormPropertyChangeObject, paramters?: any): any { + // 刷新实体树 + // changeObject.needRefreshEntityTree = true; + } + + public getAppearanceProperties(propertyData, componentInstance): any { const self = this; @@ -110,37 +186,24 @@ export class InputBaseProperty extends BaseControlProperty { style: { title: "style样式", type: "string", - description: "组件的样式", + description: "组件的内联样式", $converter: "/converter/appearance.converter" - }, - responseLayout: { - description: "响应式列宽", - title: "响应式列宽", - type: "boolean", - visible: true, - // 这个属性,标记当属性变更得时候触发重新更新属性 - refreshPanelAfterChanged: true, - editor: { - type: "response-layout-editor-setting", - initialState: self.responseLayoutEditorFunction.checkCanOpenLayoutEditor(propertyData, self.componentId) - } } + }, setPropertyRelates(changeObject, prop) { if (!changeObject) { return; } switch (changeObject && changeObject.propertyID) { - case 'responseLayout': - self.responseLayoutEditorFunction.changeFormControlsByResponseLayoutConfig(changeObject.propertyValue, self.componentId || propertyData.id); - self.updateUnifiedLayoutAfterResponseLayoutChanged(self.componentId); - self.updateElementByParentContainer(propertyData.id, componentInstance); - delete propertyData.responseLayout; - break; case 'class': self.updateUnifiedLayoutAfterControlChanged(changeObject.propertyValue, propertyData.id, this.componentId); - self.updateElementByParentContainer(propertyData.id, componentInstance); + // canvasChanged.value++; + break; + case 'style': { + // canvasChanged.value++; break; + } } } @@ -157,7 +220,7 @@ export class InputBaseProperty extends BaseControlProperty { * @param propertyData 控件DOM属性 * @param newControlType 新控件类型 */ - private changeControlType(propertyData, changeObject, componentInstance: DesignerComponentInstance) { + private changeControlType(propertyData, changeObject, componentInstance: DesignerComponentInstance | null) { const newControlType = changeObject.propertyValue; // 1、定位控件父容器 @@ -167,20 +230,24 @@ export class InputBaseProperty extends BaseControlProperty { } const index = parentContainer.contents.findIndex(c => c.id === propertyData.id); + if (index === -1) { + return; + } const oldControl = parentContainer.contents[index]; let newControl; - // 2、记录绑定字段viewModel的变更 + if (this.designViewModelField) { + // 2、记录绑定字段viewModel的变更 + const viewModel = this.formSchemaUtils.getViewModelById(this.viewModelId); + const viewModelField = viewModel.fields.find(field => field.id === this.designViewModelField.id); + const viewModelFieldSchema = viewModelField.fieldSchema || {}; + if (!viewModelFieldSchema.editor) { viewModelFieldSchema.editor = {}; } + viewModelFieldSchema.editor.$type = newControlType; + const dgViewModel = this.designViewModelUtils.getDgViewModel(this.viewModelId); - dgViewModel.changeField(this.designViewModelField.id, { - editor: { - $type: newControlType - }, - name: this.designViewModelField.name, - require: this.designViewModelField.require, - readonly: this.designViewModelField.readonly - }, false); + dgViewModel.changeField(this.designViewModelField.id, viewModelFieldSchema, false); + // 3、创建新控件 newControl = this.controlCreatorUtils.setFormFieldProperty(this.designViewModelField, newControlType); } @@ -193,21 +260,26 @@ export class InputBaseProperty extends BaseControlProperty { appearance: oldControl.appearance, size: oldControl.size, label: oldControl.label, - binding: oldControl.binding, - visible: oldControl.visible - }); - Object.assign(newControl.editor, { - isTextArea: newControl.isTextArea && oldControl.isTextArea, - placeholder: oldControl.editor?.placeholder, - holdPlace: oldControl.editor?.holdPlace, - readonly: oldControl.editor?.readonly, - required: oldControl.editor?.required, + binding: oldControl.binding }); - + // 解决undefined下默认值问题 + if (Object.prototype.hasOwnProperty.call(oldControl, 'visible')) { + Object.assign(newControl, { visible: oldControl.visible }) + } + if (oldControl.editor) { + ['readonly', 'required', 'placeholder'].map((item) => { + if (Object.prototype.hasOwnProperty.call(oldControl.editor, item)) { + newControl.editor[item] = oldControl.editor[item]; + } + }); + } // 5、替换控件 parentContainer.contents.splice(index, 1); parentContainer.contents.splice(index, 0, newControl); componentInstance.schema = Object.assign(oldControl, newControl); + // 重组VM + // this.designViewModelUtils.assembleDesignViewModel(); + Object.assign(propertyData, newControl); // 6、暂时移除旧控件的选中样式(后续考虑更好的方式) Array.from(document.getElementsByClassName('dgComponentSelected') as HTMLCollectionOf).forEach( @@ -218,11 +290,11 @@ export class InputBaseProperty extends BaseControlProperty { (element: HTMLElement) => element.classList.remove('dgComponentFocused') ); // 7、触发刷新 - canvasChanged.value++; + // canvasChanged.value++; } - public getComponentConfig(propertyData, info = {}, properties = {}, setPropertyRelates?: any) { + public getComponentConfig(propertyData, info = {}, properties = {}, setPropertyRelates?: (changeObject, propertyData, parameters) => any) { const editorBasic = Object.assign({ description: "编辑器", title: "编辑器", @@ -230,35 +302,48 @@ export class InputBaseProperty extends BaseControlProperty { $converter: "/converter/property-editor.converter" }, info); - const editorProperties = Object.assign({ + const readonlyEditor = this.getPropertyEditorParams(propertyData, [], 'readonly'); + const requiredEditor = this.getPropertyEditorParams(propertyData, [], 'required'); + const editorProperties = { readonly: { description: "", title: "只读", - type: "boolean", - editor: { - enableClear: true, - editable: true - } + editor: readonlyEditor }, - disabled: { + required: { description: "", - title: "禁用", + title: "必填", type: "boolean", - visible: false + editor: requiredEditor }, - // required: { - // description: "", - // title: "必填", - // type: "boolean" - // }, placeholder: { - description: "空值时,输入控件内的占位文本", + description: "当控件没有值时在输入框中显示的文本", title: "提示文本", type: "string" } - }, properties); + }; + for (const key in properties) { + // 合并属性,保留原属性值 + editorProperties[key] = Object.assign(editorProperties[key] || {}, properties[key]); + } + const self = this; - return { ...editorBasic, properties: { ...editorProperties }, setPropertyRelates }; + return { + ...editorBasic, properties: { ...editorProperties }, setPropertyRelates(changeObject, parameters: any) { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'readonly': + case 'required': + self.afterMutilEditorChanged(propertyData, changeObject); + break; + } + if (setPropertyRelates) { + setPropertyRelates(changeObject, propertyData, parameters); + } + } + }; } @@ -290,47 +375,9 @@ export class InputBaseProperty extends BaseControlProperty { columnInEL: parseInt(colELClass.replace('col-el-', ''), 10), }; - this.updateUnifiedLayoutAfterResponseLayoutChanged(componentId, latestControlLayoutConfig); } - /** - * 修改控件布局配置后更新Form统一布局配置 - * @param componentId 组件Id - * @param controlLayoutConfig 某单独变动的控件配置项,FormResponseLayoutContext类型 - */ - private updateUnifiedLayoutAfterResponseLayoutChanged(componentId: string, controlLayoutConfig?: any): FormUnifiedColumnLayout | undefined { - const { formNode } = this.responseLayoutEditorFunction.checkCanFindFormNode(componentId); - // 更改form上的统一配置 - if (!formNode || !formNode.unifiedLayout) { - return; - } - const responseLayoutConfig: ResponseFormLayoutContext[] = []; - this.responseLayoutEditorFunction.getResonseFormLayoutConfig(formNode, responseLayoutConfig, 1); - if (controlLayoutConfig) { - const changedControl = responseLayoutConfig.find(c => c.id === controlLayoutConfig.id); - Object.assign(changedControl || {}, controlLayoutConfig); - } - - // 收集每种屏幕下的列数 - const columnInSMArray = responseLayoutConfig.map(config => config.columnInSM); - const columnInMDArray = responseLayoutConfig.map(config => config.columnInMD); - const columnInLGArray = responseLayoutConfig.map(config => config.columnInLG); - const columnInELArray = responseLayoutConfig.map(config => config.columnInEL); - - // 只有每个控件的宽度都一样时,才认为form上有统一宽度,否则认为是自定义的控件宽度,此处传递null - const uniqueColClassInSM = this.checkIsUniqueColumn(columnInSMArray) ? columnInSMArray[0] : null; - const uniqueColClassInMD = this.checkIsUniqueColumn(columnInMDArray) ? columnInMDArray[0] : null; - const uniqueColClassInLG = this.checkIsUniqueColumn(columnInLGArray) ? columnInLGArray[0] : null; - const uniqueColClassInEL = this.checkIsUniqueColumn(columnInELArray) ? columnInELArray[0] : null; - - Object.assign(formNode.unifiedLayout, { - uniqueColClassInSM, - uniqueColClassInMD, - uniqueColClassInLG, - uniqueColClassInEL - }); - } /** * 校验宽度样式值是否一致 */ @@ -358,7 +405,7 @@ export class InputBaseProperty extends BaseControlProperty { columns: [ { field: valueField, title: '值', dataType: 'string' }, { field: textField, title: '名称', dataType: 'string' }, - { field: 'disabled', title: '禁用', visible: false, dataType: 'boolean', editor: { type: 'switch' } }, + { field: 'disabled', title: '禁用', dataType: 'boolean', editor: { type: 'switch' } }, ], type: "item-collection-editor", valueField: valueField, @@ -375,7 +422,7 @@ export class InputBaseProperty extends BaseControlProperty { * 2、绑定类型为字段,且字段为枚举字段,则不可新增、删除、修改枚举值。只能从be修改然后同步到表单上。 * @param propertyData 下拉框控件属性值 */ - private checkEnumDataReadonly(propertyData: any): boolean { + protected checkEnumDataReadonly(propertyData: any): boolean { // 没有绑定信息或者绑定变量 if (!propertyData.binding || propertyData.binding.type !== 'Form') { return false; @@ -387,4 +434,118 @@ export class InputBaseProperty extends BaseControlProperty { } return false; } + /** + * 将字段值变化前事件、变化后事件追加到交互面板 + * 注意:因为绑定字段值变化后事件与下拉框的值变化事件(valueChanged)重名,所以这里将事件label都重命名下 + */ + appendFieldValueChangeEvents(propertyData: any, eventList: any[]) { + // 若绑定了字段,则需要显示字段变更前后事件 + if (propertyData.binding && propertyData.binding.type === FormBindingType.Form && propertyData.binding.field) { + const valueChangingExist = eventList.find(eventListItem => eventListItem.label === 'fieldValueChanging'); + if (!valueChangingExist) { + eventList.push( + { + label: 'fieldValueChanging', + name: '绑定字段值变化前事件' + } + ); + } + const valueChangedExist = eventList.find(eventListItem => eventListItem.label === 'fieldValueChanged'); + if (!valueChangedExist) { + eventList.push( + { + label: 'fieldValueChanged', + name: '绑定字段值变化后事件' + } + ); + } + if (this.designViewModelField) { + // 因为字段变更属性是存到VM中的,但是这里需要在控件上编辑,所以复制一份数据 + propertyData.fieldValueChanging = this.designViewModelField.valueChanging; + propertyData.fieldValueChanged = this.designViewModelField.valueChanged; + } + } else { + // 未绑定字段,则移除值变化事件 + eventList = eventList.filter(eventListItem => eventListItem.label !== 'fieldValueChanging' && eventListItem.label !== 'fieldValueChanged'); + } + } + private getControlMethodType(propertyData: any) { + if (!propertyData.binding) { + return propertyData.type; + } + switch (propertyData.binding.type) { + case FormBindingType.Form: { + return propertyData.binding.path || propertyData.type; + } + case FormBindingType.Variable: { + return propertyData.binding.fullPath || propertyData.type; + } + } + + return propertyData.type; + } + /** + * 组装输入类控件的交互面板:包含标签超链、绑定字段值变化前后事件等。 + * @param propertyData 属性值 + * @param viewModelId 视图模型id + * @param showPosition 面板展示位置 + * @param customEvent 输入控件特有的事件配置 + */ + public getEventPropertyConfig(propertyData: any, showPosition = 'card', customEventList?: { label: string, name: string }[], setPropertyRelates?: (changeObject, data, parameters) => void) { + const self = this; + // 静态事件 + let eventList = [] as any; + if (customEventList) { + eventList = eventList.concat(customEventList); + } + // 追加值变化 + this.appendFieldValueChangeEvents(propertyData, eventList); + + const initialData = self.eventsEditorUtils['formProperties'](propertyData, self.viewModelId, eventList); + const properties = {}; + properties[self.viewModelId] = { + type: 'events-editor', + editor: { + initialData + } + }; + const eventsEditorConfig = { + title: '事件', + hideTitle: true, + properties, + tabId: 'commands', + tabName: '交互', + setPropertyRelates(changeObject: FormPropertyChangeObject, data: any) { + const parameters = changeObject.propertyValue; + delete propertyData[self.viewModelId]; + if (parameters) { + parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后,调用此回调方法,用于处理联动属性 + parameters.controlInfo = { type: self.getControlMethodType(propertyData), name: propertyData.title }; // 暂存控件信息,用于自动创建新方法的方法编号和名称 + + self.eventsEditorUtils.saveRelatedParameters(propertyData, self.viewModelId, parameters['events'], parameters); + } + + if (setPropertyRelates) { + setPropertyRelates(changeObject, data, parameters); + } + + // 同步视图模型值变化事件 + const designVM = self.designViewModelUtils.getDgViewModel(self.viewModelId); + if (designVM && self.designViewModelField) { + designVM.changeField(self.designViewModelField.id, { valueChanging: propertyData.fieldValueChanging, valueChanged: propertyData.fieldValueChanged }); + } + } + }; + + return eventsEditorConfig; + } + + getExpressionConfig(propertyData: any, type: 'Field' | 'Button' | 'Container', + expressionTypes: string[] = ['compute', 'dependency', 'validate'], + associationCallBack?: (rule: Record) => void + ) { + return new ExpressionProperty(this.formSchemaUtils).getExpressionConfig( + propertyData, type, expressionTypes, associationCallBack); + } + } diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/schema-dom-mapping.ts b/packages/mobile-ui-vue/components/common/src/properties/schema-dom-mapping.ts similarity index 78% rename from packages/mobile-ui-vue/components/property-panel/src/composition/entity/schema-dom-mapping.ts rename to packages/mobile-ui-vue/components/common/src/properties/schema-dom-mapping.ts index fe8b715256414ee3d6a94a4915284522613c1032..6dcc589367d7d0d9af318a07f5294340eabe91d0 100644 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/schema-dom-mapping.ts +++ b/packages/mobile-ui-vue/components/common/src/properties/schema-dom-mapping.ts @@ -1,5 +1,5 @@ -import { DgControl } from "../../../../designer-canvas/src/composition/dg-control"; +import { DgControl } from "./dg-control"; export class SchemaDOMMapping { @@ -13,7 +13,7 @@ export class SchemaDOMMapping { { key: DgControl['date-picker'].type, value: DgControl['date-picker'].name }, { key: DgControl['check-group'].type, value: DgControl['check-group'].name }, { key: DgControl['radio-group'].type, value: DgControl['radio-group'].name }, - { key: DgControl['combo-list'].type, value: DgControl['combo-list'].name }, + { key: DgControl['picker'].type, value: DgControl['picker'].name }, { key: DgControl['textarea'].type, value: DgControl['textarea'].name }, ], Text: [ @@ -21,16 +21,16 @@ export class SchemaDOMMapping { { key: DgControl['lookup'].type, value: DgControl['lookup'].name } ], Decimal: [ - { key: DgControl['number-spinner'].type, value: DgControl['number-spinner'].name } + { key: DgControl['number-input'].type, value: DgControl['number-input'].name } ], Integer: [ - { key: DgControl['number-spinner'].type, value: DgControl['number-spinner'].name } + { key: DgControl['number-input'].type, value: DgControl['number-input'].name } ], Number: [ - { key: DgControl['number-spinner'].type, value: DgControl['number-spinner'].name } + { key: DgControl['number-input'].type, value: DgControl['number-input'].name } ], BigNumber: [ - { key: DgControl['number-spinner'].type, value: DgControl['number-spinner'].name } + { key: DgControl['number-input'].type, value: DgControl['number-input'].name } ], Date: [ { key: DgControl['date-picker'].type, value: DgControl['date-picker'].name } @@ -43,12 +43,12 @@ export class SchemaDOMMapping { { key: DgControl['check-box'].type, value: DgControl['check-box'].name }, ], Enum: [ - { key: DgControl['combo-list'].type, value: DgControl['combo-list'].name }, + { key: DgControl['picker'].type, value: DgControl['picker'].name }, { key: DgControl['radio-group'].type, value: DgControl['radio-group'].name }, ], Object: [ { key: DgControl['lookup'].type, value: DgControl['lookup'].name }, - { key: DgControl['combo-list'].type, value: DgControl['combo-list'].name }, + { key: DgControl['picker'].type, value: DgControl['picker'].name }, { key: DgControl['radio-group'].type, value: DgControl['radio-group'].name }, ] }; diff --git a/packages/mobile-ui-vue/components/common/src/properties/toolbar-item.property.ts b/packages/mobile-ui-vue/components/common/src/properties/toolbar-item.property.ts new file mode 100644 index 0000000000000000000000000000000000000000..17e8eb8223459ed0f8e70d0ce29d56c16b74440c --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/properties/toolbar-item.property.ts @@ -0,0 +1,101 @@ +import { BaseControlProperty } from "./base-property"; + +export class ToolbarItemProperty extends BaseControlProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } + + public getPropertyConfig(propertyData: any) { + // 基本信息 + this.propertyConfig.categories['basic'] = this.getBasicPropConfig(propertyData); + // 行为 + this.propertyConfig.categories['behavior'] = this.getNavBarBehaviorConfig(propertyData); + // 事件 + this.getEventPropConfig(propertyData); + + return this.propertyConfig; + } + + getBasicPropConfig(propertyData: any): any { + return { + description: 'Basic Information', + title: '基本信息', + properties: { + id: { + description: '工具栏按钮的标识', + title: '标识', + type: 'string', + readonly: true + }, + text: { + description: '工具栏按钮的标签', + title: '标签', + type: 'string', + readonly: false + } + } + }; + + } + + private getNavBarBehaviorConfig(propertyData) { + const visibleProperty = this.getVisibleProperty(propertyData) + const self = this; + return { + description: "基本信息", + title: "行为", + properties: { + ...visibleProperty, + disabled: { + title: "是否禁用", + type: "boolean", + } + }, + setPropertyRelates(changeObject: any, data: any) { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'visible': + self.afterMutilEditorChanged(propertyData, changeObject); + break; + } + } + }; + } + + private getEventPropConfig(propertyData: any) { + const events = [ + { + label: "onClick", + name: "点击事件", + } + ]; + const self = this; + const initialData = self.eventsEditorUtils['formProperties'](propertyData, self.viewModelId, events); + const properties = {}; + properties[self.viewModelId] = { + type: 'events-editor', + editor: { + initialData + } + }; + this.propertyConfig.categories['eventsEditor'] = { + title: '事件', + hideTitle: true, + properties, + refreshPanelAfterChanged: true, + tabId: 'commands', + tabName: '交互', + setPropertyRelates(changeObject: any, data: any) { + const parameters = changeObject.propertyValue; + delete propertyData[self.viewModelId]; + if (parameters) { + parameters.setPropertyRelates = this.setPropertyRelates; + self.eventsEditorUtils.saveRelatedParameters(propertyData, self.viewModelId, parameters['events'], parameters); + } + } + }; + } + +} diff --git a/packages/mobile-ui-vue/components/common/src/properties/use-property-editor.ts b/packages/mobile-ui-vue/components/common/src/properties/use-property-editor.ts new file mode 100644 index 0000000000000000000000000000000000000000..edc1e1d510145b7459b33e306a9346228b7681e8 --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/properties/use-property-editor.ts @@ -0,0 +1,73 @@ +import { DesignerHostService } from "../types"; + +/** + * PropertyEditor对外提供的接口 + * @param designerHostService + * @returns + */ +export function usePropertyEditor(designerHostService: DesignerHostService): any { + const { formSchemaUtils, formStateMachineUtils } = designerHostService; + + /** + * 把变量视图模型的变量转化为PropertyEditor的变量格式 + * @param variable + * @returns + */ + function convertToEditorVariable(variable: any, pathPrefix: string = ''): any { + return { + path: pathPrefix + variable.code, + field: variable.id, + fullPath: variable.code + }; + } + + /** + * 获取视图模型上的变量 + * @param viewModelId + * @returns + */ + function getVariablesByViewModelId(viewModelId: string, pathPrefix: string = ''): any[] { + const viewModel = formSchemaUtils.getViewModelById(viewModelId); + return viewModel.states.map(state => convertToEditorVariable(state, pathPrefix)); + } + + /** + * 获取PropertyEditor需要的变量数据 + */ + function getVariables(viewModelId: string): any[] { + const rootViewModelId = formSchemaUtils.getRootViewModelId(); + // 1、当前组件的组件变量 + const currentViewModelVariables = getVariablesByViewModelId(viewModelId); + if (viewModelId === rootViewModelId) { + return currentViewModelVariables; + } + + // 2、根组件的组件变量 + const rootViewModelVariables = getVariablesByViewModelId(rootViewModelId, 'root-component.'); + return [...currentViewModelVariables, ...rootViewModelVariables]; + } + + /** + * 获取控件名称 + * @param propertyData + * @returns + */ + function getControlName(propertyData: any): string { + const controlName = propertyData.binding && propertyData.binding.path || propertyData.id || ''; + return controlName; + } + + /** + * 获取PropertyEditor需要的状态机数据 + */ + function getStateMachines(viewModelId:string): any[] { + const renderStates = formStateMachineUtils && formStateMachineUtils.getRenderStates(); + if(renderStates){ + const viewModel = formSchemaUtils.getViewModelById(viewModelId); + return renderStates.filter(renderState => renderState.stateMachineId === viewModel.stateMachine); + } + return renderStates || []; + } + + return { getVariables, getControlName, getStateMachines }; +} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/types.ts b/packages/mobile-ui-vue/components/common/src/types/designer-component.ts similarity index 98% rename from packages/mobile-ui-vue/components/designer-canvas/src/types.ts rename to packages/mobile-ui-vue/components/common/src/types/designer-component.ts index c63ceb11c799e56767b8962c6e51f34ea487c690..6ca1bb9c26e2843c9972a3120b3473f569a51d27 100644 --- a/packages/mobile-ui-vue/components/designer-canvas/src/types.ts +++ b/packages/mobile-ui-vue/components/common/src/types/designer-component.ts @@ -1,6 +1,6 @@ /* eslint-disable no-use-before-define */ import { Ref, SetupContext } from "vue"; -import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext } from "./composition/types"; +import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext } from "./designer-rule"; export interface ComponentSchema { diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/types.ts b/packages/mobile-ui-vue/components/common/src/types/designer-rule.ts similarity index 93% rename from packages/mobile-ui-vue/components/designer-canvas/src/composition/types.ts rename to packages/mobile-ui-vue/components/common/src/types/designer-rule.ts index a3dc5bbfad20596649c87001a8891b6d575a47e7..ed261cb18f6ec651c94bc51f992f1c3ff9ec08c3 100644 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/types.ts +++ b/packages/mobile-ui-vue/components/common/src/types/designer-rule.ts @@ -1,6 +1,6 @@ -import { DesignFormVariable, DesignViewModelField, FormSchemaEntity, FormSchemaEntityField } from "../../../common/entity/entity-schema"; import { Ref } from "vue"; -import { ComponentSchema, DesignerComponentButton, DesignerComponentInstance } from "../types"; +import { ComponentSchema, DesignerComponentButton, DesignerComponentInstance } from "./designer-component"; +import { DesignFormVariable, DesignViewModelField, FormSchemaEntity, FormSchemaEntityField } from "./entity-schema"; export interface DesignerHTMLElement extends HTMLElement { /** 记录各子元素对应的控件schema json的集合,用于container类dom节点 */ @@ -12,14 +12,6 @@ export interface DesignerHTMLElement extends HTMLElement { schema: ComponentSchema; } - -export interface UseDragula { - attachComponents: (element: HTMLElement, component: ComponentSchema) => void; - - initializeDragula: (containerElement: DesignerHTMLElement) => void; - - getDragulaInstance: () => any; -} export interface DesignerHostService { eventsEditorUtils: any; formSchemaUtils: any; diff --git a/packages/mobile-ui-vue/components/common/src/entity/entity-schema.ts b/packages/mobile-ui-vue/components/common/src/types/entity-schema.ts similarity index 100% rename from packages/mobile-ui-vue/components/common/src/entity/entity-schema.ts rename to packages/mobile-ui-vue/components/common/src/types/entity-schema.ts diff --git a/packages/mobile-ui-vue/components/common/src/types/index.ts b/packages/mobile-ui-vue/components/common/src/types/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..195bea74cd34c250e739f2c5ef58be6524bfa349 --- /dev/null +++ b/packages/mobile-ui-vue/components/common/src/types/index.ts @@ -0,0 +1,5 @@ +export * from './types'; +export * from './designer-component'; +export * from './designer-rule'; +export * from './entity-schema'; +export * from './property-config'; diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/property-entity.ts b/packages/mobile-ui-vue/components/common/src/types/property-config.ts similarity index 79% rename from packages/mobile-ui-vue/components/property-panel/src/composition/entity/property-entity.ts rename to packages/mobile-ui-vue/components/common/src/types/property-config.ts index 2a8f1dcd855e970558f4c31e09f2523aa9e4cae7..0b525f2bea35eb24f03127225016801ae9b2f1d3 100644 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/property-entity.ts +++ b/packages/mobile-ui-vue/components/common/src/types/property-config.ts @@ -1,4 +1,3 @@ -import { EditorConfig } from "@/components/dynamic-form"; import { Ref } from "vue"; export interface KeyMap { @@ -6,6 +5,29 @@ export interface KeyMap { value: any; } +export type EditorType = 'button-edit' | 'check-box' | 'check-group' | 'combo-list' | 'combo-lookup' | 'combo-tree' | + 'date-picker' | 'date-range' | 'datetime-picker' | 'datetime-range' | 'events-editor' | 'month-picker' | 'month-range' | + 'year-picker' | 'year-range' | 'input-group' | 'lookup' | 'number-range' | 'number-spinner' | 'radio-group' | 'text' | + 'response-layout-editor-setting' | 'switch' | 'grid-field-editor' | 'field-selector' | 'schema-selector' | 'mapping-editor' | + 'textarea' | 'response-form-layout-setting'|'binding-selector' | 'query-solution-config' | 'solution-preset' | 'item-collection-editor'; + +export interface EditorConfig { + /** 编辑器类型 */ + type: EditorType; + /** 自定义样式 */ + customClass?: string; + /** 禁用 */ + disabled?: boolean; + /** 只读 */ + readonly?: boolean; + /** 必填 */ + required?: boolean; + /** 提示文本 */ + placeholder?: string; + /** 其他属性 */ + [key: string]: any; +} + /** 属性实体 */ export interface PropertyEntity { /** @@ -223,8 +245,8 @@ export interface FormPropertyChangeObject extends PropertyChangeObject { /** 是否需要刷新控件树 */ needRefreshControlTree?: boolean; - /** 是否需要更新控件树节点名称 */ - needUpdateControlTreeNodeName?: boolean; + /** 是否需要刷新控件树 */ + needRefreshEntityTree?: boolean; /** 关联变更的属性集合,用于更新表单DOM属性 */ relateChangeProps?: Array<{ @@ -232,9 +254,13 @@ export interface FormPropertyChangeObject extends PropertyChangeObject { propertyValue: any }>; - /** 属性变更后是否需要向schema字段同步 */ - needSyncToSchemaField?: boolean; - /** 强关联的属性id:在当前属性变更后,页面自动定位到强关联的属性 */ autoLocatedPropertyId?: string; } + + +export enum FormBindingType { + Form = "Form", + Variable = "Variable" +} + diff --git a/packages/mobile-ui-vue/components/common/types.ts b/packages/mobile-ui-vue/components/common/src/types/types.ts similarity index 90% rename from packages/mobile-ui-vue/components/common/types.ts rename to packages/mobile-ui-vue/components/common/src/types/types.ts index 317a5cf302068b5deb88d960fe05c0e108091e6b..47a5ed1fc2b084b41f998fdf0c15229e8b6a4b5b 100644 --- a/packages/mobile-ui-vue/components/common/types.ts +++ b/packages/mobile-ui-vue/components/common/src/types/types.ts @@ -1,4 +1,5 @@ import { ComputedRef, Ref } from "vue"; +import { EffectFunction, SchemaResolverFunction } from "@farris/mobile-ui-vue/dynamic-resolver/src/types"; export interface TextBoxProps { @@ -129,3 +130,10 @@ export type TimeAgoOptions = { export interface UseTimeAgoFormat { formatTo(date: TimeAgoDate, opts?: TimeAgoOptions): string } + +export interface RegisterContext { + schemaMap: Record; + schemaResolverMap: Record; + propertyConfigSchemaMap: Record; + propertyEffectMap: Record; +} \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/common/src/utils/src/common.ts b/packages/mobile-ui-vue/components/common/src/utils/src/common.ts index b2be798cc21cb142d329a60f35f5b01fc334508e..1010e19020f584c0011c18b95daa19ff85c425ef 100644 --- a/packages/mobile-ui-vue/components/common/src/utils/src/common.ts +++ b/packages/mobile-ui-vue/components/common/src/utils/src/common.ts @@ -2,6 +2,11 @@ import { isDef, isNumeric, isObject } from './type'; export function noop() { } +export const omitProperty = >(obj: T, key: keyof T): Omit => { + const { [key]: omitted, ...rest } = obj; + return rest as Omit; +}; + export function addUnit(value: string | number) { if (!isDef(value)) { return undefined; diff --git a/packages/mobile-ui-vue/components/common/src/utils/src/date.ts b/packages/mobile-ui-vue/components/common/src/utils/src/date.ts index 12d69995035c31f751578a1fb093881ff3771315..14fbaec4b97eb902cb6ca52c56565b5fd3a1bbbe 100644 --- a/packages/mobile-ui-vue/components/common/src/utils/src/date.ts +++ b/packages/mobile-ui-vue/components/common/src/utils/src/date.ts @@ -63,9 +63,9 @@ export const parseTime = (value: string) => { export const formatDate = (value: Date, format: string) => { const { year, month, day, hours, minutes, seconds } = getDateRecord(value); return format - .replace('YYYY', String(year)) + .replace('yyyy', String(year)) .replace('MM', String(month).padStart(2, '0')) - .replace('DD', String(day).padStart(2, '0')) + .replace('dd', String(day).padStart(2, '0')) .replace('HH', String(hours).padStart(2, '0')) .replace('mm', String(minutes).padStart(2, '0')) .replace('ss', String(seconds).padStart(2, '0')); @@ -88,9 +88,9 @@ export const parseDate = (value: string, format: string) => { .split('-') .map((item) => Number(item)); - const year = dateValueParts[formatMap.YYYY]; + const year = dateValueParts[formatMap.yyyy]; const month = dateValueParts[formatMap.MM] ? dateValueParts[formatMap.MM] - 1 : 0; - const day = dateValueParts[formatMap.DD] || 1; + const day = dateValueParts[formatMap.dd] || 1; const { hours, minutes, seconds } = getTimeRecord(timeValue); diff --git a/packages/mobile-ui-vue/components/common/src/utils/src/dom/event.ts b/packages/mobile-ui-vue/components/common/src/utils/src/dom/event.ts index 4bd7afe82ec38cbe3e2254443cf9765ef6021b12..07e07fc6addf078dea31511cf1389709648a88c0 100644 --- a/packages/mobile-ui-vue/components/common/src/utils/src/dom/event.ts +++ b/packages/mobile-ui-vue/components/common/src/utils/src/dom/event.ts @@ -12,26 +12,3 @@ export function preventDefault(event: Event, isStopPropagation?: boolean) { stopPropagation(event); } } - -export function trigger(target: Element, type: string) { - const inputEvent = document.createEvent('HTMLEvents'); - inputEvent.initEvent(type, true, true); - target.dispatchEvent(inputEvent); -} - -// ios event没有path属性 -export const initNodePath = (event: Event) => { - const path: any[] = []; - let currentElem: any = event.target; - while (currentElem) { - path.push(currentElem); - currentElem = currentElem.parentElement; - } - if (path.indexOf(window) === -1 && path.indexOf(document) === -1) { - path.push(document); - } - if (path.indexOf(window) === -1) { - path.push(window); - } - return path; -}; diff --git a/packages/mobile-ui-vue/components/common/src/utils/src/with-register-designer.ts b/packages/mobile-ui-vue/components/common/src/utils/src/with-register-designer.ts index d9583f5d56f09fcacd498341ae2eecace916f02c..b0b5557958ac4bb5589ef9e47acf776dca5a8a70 100644 --- a/packages/mobile-ui-vue/components/common/src/utils/src/with-register-designer.ts +++ b/packages/mobile-ui-vue/components/common/src/utils/src/with-register-designer.ts @@ -1,15 +1,21 @@ +import { RegisterContext } from '@farris/mobile-ui-vue/common'; import type { App, Component } from 'vue'; export type WithRegisterDesigner = T & { registerDesigner(app: App): void; }; -export function withRegisterDesigner(component: T, options: { name: string, designerComponent: Component, propsResolver: (schemaValue?: Record) => Record }) { - const { name, designerComponent, propsResolver } = options; +export function withRegisterDesigner(component: T, options: { name: string, designerComponent: Component, propsResolverGenerator: (registerContext: RegisterContext) => (schemaValue?: Record) => Record }) { + const { name, designerComponent, propsResolverGenerator } = options; - (component as Record).registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { + (component as Record).registerDesigner = ( + componentMap: Record, + propsResolverMap: Record, + configResolverMap: Record, + registerContext: RegisterContext + ) => { componentMap[name] = designerComponent; - propsResolverMap[name] = propsResolver; + propsResolverMap[name] = propsResolverGenerator(registerContext); }; return component as WithRegisterDesigner; diff --git a/packages/mobile-ui-vue/components/common/src/utils/src/with-register.ts b/packages/mobile-ui-vue/components/common/src/utils/src/with-register.ts index 483e6fdbfdd52c4a6bbc1f9e44c5f904ec1e300e..15608d737bd99b87dd2a53d032751f640b7da7b5 100644 --- a/packages/mobile-ui-vue/components/common/src/utils/src/with-register.ts +++ b/packages/mobile-ui-vue/components/common/src/utils/src/with-register.ts @@ -1,15 +1,22 @@ +import { RegisterContext } from '@farris/mobile-ui-vue/common'; import type { App, Component } from 'vue'; export type WithRegister = T & { register(app: App): void; }; -export function withRegister(component: T, options: { name: string, propsResolver: (schemaValue?: Record) => Record }) { - const { name, propsResolver } = options; +export function withRegister(component: T, options: { name: string, propsResolverGenerator: (registerContext: RegisterContext) => (schemaValue?: Record) => Record }) { + const { name, propsResolverGenerator } = options; - (component as Record).register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { + (component as Record).register = ( + componentMap: Record, + propsResolverMap: Record, + configResolverMap: Record, + resolverMap: Record, + registerContext: RegisterContext + ) => { componentMap[name] = component; - propsResolverMap[name] = propsResolver; + propsResolverMap[name] = propsResolverGenerator(registerContext); }; return component as WithRegister; diff --git a/packages/mobile-ui-vue/components/component/index.ts b/packages/mobile-ui-vue/components/component/index.ts index bed6e3bd70cd80554f28e8804df778429f009b33..ba722ade21f9ec81eaec0c9a148c5bd1ad75c43c 100644 --- a/packages/mobile-ui-vue/components/component/index.ts +++ b/packages/mobile-ui-vue/components/component/index.ts @@ -15,9 +15,9 @@ * limitations under the License. */ import type { Plugin } from 'vue'; -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import ComponentInstallless from './src/component.component'; -import { propsResolver } from './src/component.props'; +import { propsResolverGenerator } from './src/component.props'; import ComponentDesign from './src/designer/component.design.component'; const COMPONENT_REGISTERED_NAME = 'component'; @@ -25,18 +25,18 @@ const COMPONENT_REGISTERED_NAME = 'component'; const Component = withInstall(ComponentInstallless); Component.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext ) => { componentMap[COMPONENT_REGISTERED_NAME] = Component; - propsResolverMap[COMPONENT_REGISTERED_NAME] = propsResolver; + propsResolverMap[COMPONENT_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; Component.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record, registerContext: RegisterContext ) => { componentMap[COMPONENT_REGISTERED_NAME] = ComponentDesign; - propsResolverMap[COMPONENT_REGISTERED_NAME] = propsResolver; + propsResolverMap[COMPONENT_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; diff --git a/packages/mobile-ui-vue/components/component/src/component.props.ts b/packages/mobile-ui-vue/components/component/src/component.props.ts index ab01ca66a4875402f59c9a6682c30287d586cb33..43d758ae9bc2d881c74afa7f61ed6e3b78dd6fc0 100644 --- a/packages/mobile-ui-vue/components/component/src/component.props.ts +++ b/packages/mobile-ui-vue/components/component/src/component.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import componentSchema from './schema/component.schema.json'; import { schemaResolver } from './schema/schema-resolver'; @@ -32,7 +32,7 @@ export const componentProps = { export type ComponentPropsType = ExtractPropTypes; // 属性处理器 -export const propsResolver = createPropsResolver(componentProps, componentSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(componentProps, componentSchema, schemaMapper, schemaResolver); // 设计时属性 export const componentDesignProps = Object.assign({}, componentProps, { componentId: { type: String, default: '' } }); diff --git a/packages/mobile-ui-vue/components/component/src/designer/component.design.component.tsx b/packages/mobile-ui-vue/components/component/src/designer/component.design.component.tsx index 06b97e5ff2afec556b8d17838eeb90da304e77e4..d2e9b308c7b52ac34a5a2d164867d1431d69fad4 100644 --- a/packages/mobile-ui-vue/components/component/src/designer/component.design.component.tsx +++ b/packages/mobile-ui-vue/components/component/src/designer/component.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, ref, onMounted, computed } from 'vue'; import { ComponentPropsType, componentProps } from '../component.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: 'FComponetDesign', diff --git a/packages/mobile-ui-vue/components/component/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/component/src/designer/use-designer-rules.ts index 4759823a140fdbf6489773888f45d0d2ea2095d2..02050723a6fa2e5095a7112ba846f797c8f6c720 100644 --- a/packages/mobile-ui-vue/components/component/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/component/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { ComponentProperty } from "../property-config/component.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/component/src/property-config/component.property-config.ts b/packages/mobile-ui-vue/components/component/src/property-config/component.property-config.ts index cdf986d57bd6141e9ea9b08e61678688250f8f44..43b773f68a1d98af19de80a94d784e3edd896cd2 100644 --- a/packages/mobile-ui-vue/components/component/src/property-config/component.property-config.ts +++ b/packages/mobile-ui-vue/components/component/src/property-config/component.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class ComponentProperty extends BaseControlProperty { diff --git a/packages/mobile-ui-vue/components/content-container/index.ts b/packages/mobile-ui-vue/components/content-container/index.ts index c14dc398ca2359ee48a295b77e68ae1c73e6065b..d6c256518cfed069637f42a0834f2808eec5a729 100644 --- a/packages/mobile-ui-vue/components/content-container/index.ts +++ b/packages/mobile-ui-vue/components/content-container/index.ts @@ -1,7 +1,8 @@ import { App, Plugin } from 'vue'; import FContentContainer from './src/content-container.component'; -import { propsResolver } from './src/content-container.props'; +import { propsResolverGenerator } from './src/content-container.props'; import ContentContainerDesign from './src/designer/content-container.design.component'; +import { RegisterContext } from '../common'; const CONTENT_CONTAINER_REGISTERED_NAME = 'content-container'; @@ -11,18 +12,18 @@ FContentContainer.install = (app: App) => { FContentContainer.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record, resolverMap: Record,registerContext: RegisterContext ) => { componentMap[CONTENT_CONTAINER_REGISTERED_NAME] = FContentContainer; - propsResolverMap[CONTENT_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[CONTENT_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; FContentContainer.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record,registerContext: RegisterContext ) => { componentMap[CONTENT_CONTAINER_REGISTERED_NAME] = ContentContainerDesign; - propsResolverMap[CONTENT_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[CONTENT_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; diff --git a/packages/mobile-ui-vue/components/content-container/src/content-container.props.ts b/packages/mobile-ui-vue/components/content-container/src/content-container.props.ts index b356d338f5d1810b4bba797c2867a46e6a9ebb6e..213f331a3db1f7a5dae38fd426c5d8d7923a7ff0 100644 --- a/packages/mobile-ui-vue/components/content-container/src/content-container.props.ts +++ b/packages/mobile-ui-vue/components/content-container/src/content-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import contentContainerSchema from './schema/content-container.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -13,7 +13,7 @@ export const contentContainerProps = { export type ContentContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( contentContainerProps, contentContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/content-container/src/designer/content-container.design.component.tsx b/packages/mobile-ui-vue/components/content-container/src/designer/content-container.design.component.tsx index 2ec2f1037db90475fdd7ce7e36a01ecb714e0975..5e2ccbc41159a8a8c22d57d5fd3007ebb9e8f396 100644 --- a/packages/mobile-ui-vue/components/content-container/src/designer/content-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/content-container/src/designer/content-container.design.component.tsx @@ -1,14 +1,14 @@ import { SetupContext, computed, defineComponent, inject, onMounted, ref } from 'vue'; -import { ContentContainerPropsType, contentContainerProps } from '../content-container.props'; +import { ContentContainerProps, contentContainerProps } from '../content-container.props'; import { useDesignerRulesForContentContainer } from './use-designer-rules'; -import { getCustomClass } from '@/components/common'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { getCustomClass } from '@farris/mobile-ui-vue/common'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FContentContainerDesign', props: contentContainerProps, emits: [], - setup(props: ContentContainerPropsType, context) { + setup(props: ContentContainerProps, context) { const elementRef = ref(); const designerHostService = inject('designer-host-service'); const designItemContext = inject('design-item-context') as DesignerItemContext; diff --git a/packages/mobile-ui-vue/components/content-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/content-container/src/designer/use-designer-rules.ts index 5164c6e8101c84f32bfba1c4ac62b4378fe77d98..b78cbfcc46b09de641a5dbf1567ae1d251f77c85 100644 --- a/packages/mobile-ui-vue/components/content-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/content-container/src/designer/use-designer-rules.ts @@ -1,6 +1,6 @@ -import { ComponentSchema, DesignerItemContext } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerItemContext } from "@farris/mobile-ui-vue/common"; import { ContentContainerProperty } from "../property-config/content-container.property-config"; -import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "@/components/designer-canvas/src/composition/types"; +import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; export function useDesignerRulesForContentContainer(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { const schema = designItemContext.schema as ComponentSchema; diff --git a/packages/mobile-ui-vue/components/content-container/src/property-config/content-container.property-config.ts b/packages/mobile-ui-vue/components/content-container/src/property-config/content-container.property-config.ts index 8db40b24dd1163136e3baedc8d8c5e4366c86642..e7d94c41f1e0833446632df144eae40d4aba41ff 100644 --- a/packages/mobile-ui-vue/components/content-container/src/property-config/content-container.property-config.ts +++ b/packages/mobile-ui-vue/components/content-container/src/property-config/content-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class ContentContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/date-picker/index.ts b/packages/mobile-ui-vue/components/date-picker/index.ts index 5b69cbee5568ac95dd2f0393bd176502b149fb78..ca62f376a8c25c88b562f78d68934d190b0e91a7 100644 --- a/packages/mobile-ui-vue/components/date-picker/index.ts +++ b/packages/mobile-ui-vue/components/date-picker/index.ts @@ -1,18 +1,18 @@ -import { withInstall, withRegister, withRegisterDesigner } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import DatePickerPanelInstallless from './src/date-picker-panel.component'; -export * from './src/date-picker-panel.props'; +export { DatePickerType, ModelValueType } from './src/composition'; import DatePickerInstallless from './src/date-picker.component'; import DatePickerDesign from './src/designer/date-picker.design.component'; -import { propsResolver } from './src/date-picker.props'; +import { propsResolverGenerator } from './src/date-picker.props'; const DatePickerPanel = withInstall(DatePickerPanelInstallless); const DatePicker = withInstall(DatePickerInstallless); // 注册运行时及设计时 const DATE_PICKER_REGISTERED_NAME = 'date-picker'; -withRegister(DatePicker, { name: DATE_PICKER_REGISTERED_NAME, propsResolver }); -withRegisterDesigner(DatePicker, { name: DATE_PICKER_REGISTERED_NAME, propsResolver, designerComponent: DatePickerDesign }); +withRegister(DatePicker, { name: DATE_PICKER_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(DatePicker, { name: DATE_PICKER_REGISTERED_NAME, propsResolverGenerator, designerComponent: DatePickerDesign }); export { DatePicker, DatePickerPanel }; diff --git a/packages/mobile-ui-vue/components/date-picker/src/composition/index.ts b/packages/mobile-ui-vue/components/date-picker/src/composition/index.ts index a16d7300f03203d29f6ecf73013af6c7f9ff548a..5cef12991855e35a5063cfe9ce7cea2462bf8c4e 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/composition/index.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/composition/index.ts @@ -1 +1,2 @@ +export * from './type'; export * from './use-date-columns'; diff --git a/packages/mobile-ui-vue/components/date-picker/src/composition/type.ts b/packages/mobile-ui-vue/components/date-picker/src/composition/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..165d19c1c82d8c79441659e97d7f641489fe9ca4 --- /dev/null +++ b/packages/mobile-ui-vue/components/date-picker/src/composition/type.ts @@ -0,0 +1,25 @@ +export enum DatePickerType { + Year = 'year', + YearMonth = 'year-month', + YearMonthDay = 'year-month-day', + Date= 'date', +} + +export enum ModelValueType { + Date = 'date', + String = 'string' +}; + +export enum DateColumn { + Year = 'year', + Month = 'month', + Date = 'day' +} + +export type DateRecord = { + year: number; + month: number; + day: number; +}; + +export type ColumnsMap = ('year' | 'month' | 'day')[]; diff --git a/packages/mobile-ui-vue/components/date-picker/src/composition/use-date-columns.ts b/packages/mobile-ui-vue/components/date-picker/src/composition/use-date-columns.ts index 9d20d1fa164a56b4f814cd282505c8fe8af2628b..be87d29f85dcc2f7abd6794bbd18b98aa650e74d 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/composition/use-date-columns.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/composition/use-date-columns.ts @@ -1,5 +1,5 @@ import { computed, watch, ref } from 'vue'; -import { Column, Columns, PickerChange } from '@components/picker'; +import { Column, Columns, PickerChange } from '@farris/mobile-ui-vue/picker'; import { compareDate, formatDate, @@ -8,22 +8,9 @@ import { isLeap, isString, parseDate -} from '@components/common'; -import { DatePickerPanelProps, DatePickerPanelTypeMap } from '../date-picker-panel.props'; - -enum DateColumn { - Year = 'year', - Month = 'month', - Date = 'day' -} - -type DateRecord = { - year: number; - month: number; - day: number; -}; - -type ColumnsMap = ('year' | 'month' | 'day')[]; +} from '@farris/mobile-ui-vue/common'; +import { DatePickerPanelProps } from '../date-picker-panel.props'; +import { ColumnsMap, DateColumn, DatePickerType, DateRecord, ModelValueType } from './type'; export const useDateColumns = (props: DatePickerPanelProps) => { const textField = 'text'; @@ -145,7 +132,7 @@ export const useDateColumns = (props: DatePickerPanelProps) => { const columnsMap = computed(() => { const type = - props.type === DatePickerPanelTypeMap.Date ? DatePickerPanelTypeMap.YearMonthDay : props.type; + props.type === DatePickerType.Date ? DatePickerType.YearMonthDay : props.type; return type.split('-') as ColumnsMap; }); @@ -170,6 +157,17 @@ export const useDateColumns = (props: DatePickerPanelProps) => { }); }); + const modelValueType = computed(()=>{ + if(props.modelValueType) { + return props.modelValueType; + } + if(props.type === DatePickerType.Date || props.type === DatePickerType.YearMonthDay) { + return ModelValueType.Date; + } else { + return ModelValueType.String; + } + }); + const getDateValue = (changes?: PickerChange) => { const dates = [...innerValue.value]; if (changes) { @@ -180,10 +178,11 @@ export const useDateColumns = (props: DatePickerPanelProps) => { const result = new Date(year, month - 1, day); - if (props.type === DatePickerPanelTypeMap.Date || props.type === DatePickerPanelTypeMap.YearMonthDay) { + if (modelValueType.value === ModelValueType.Date) { return result; + } else { + return formatDate(result, props.format); } - return formatDate(result, props.format); }; const getTextValue = () => { diff --git a/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.component.tsx b/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.component.tsx index 82be7b26d74b04f2294618667b2fc3be42b68eb2..590679e78c00ce55ae07f6b7366ad23343a95859 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.component.tsx +++ b/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.component.tsx @@ -1,6 +1,6 @@ import { defineComponent, SetupContext } from 'vue'; -import { PickerPanel, PickerChange } from '@components/picker'; -import { useBem } from '@components/common'; +import { PickerPanel, PickerChange } from '@farris/mobile-ui-vue/picker'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { useDateColumns } from './composition'; import { datePickerPanelProps, DATE_PICKER_PANEL_NAME } from './date-picker-panel.props'; diff --git a/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.props.ts b/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.props.ts index f31162f43a2dd17ca96c5e30d30abbdc89553e91..2d4219a4fed9a13cfdcb8f0c56e59aca32ddbafd 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.props.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/date-picker-panel.props.ts @@ -1,24 +1,18 @@ import { ExtractPropTypes, PropType } from 'vue'; +import { DatePickerType, ModelValueType } from './composition/type'; export const DATE_PICKER_PANEL_NAME = 'FmDatePickerPanel'; -export const enum DatePickerPanelTypeMap { - Year = 'year', - YearMonth = 'year-month', - YearMonthDay = 'year-month-day', - Date= 'date', -} - -export type DatePickerType = `${DatePickerPanelTypeMap}`; - export const datePickerPanelProps = { title: { type: String, default: '' }, - type: { type: String as PropType, default: DatePickerPanelTypeMap.Date }, + type: { type: String as PropType, default: DatePickerType.Date }, modelValue: { type: [String, Date], default: '' }, - format: { type: String, default: 'YYYY-MM-DD' }, + modelValueType: { type: String as PropType, default: '' }, + + format: { type: String, default: 'yyyy-MM-dd' }, maxDate: { type: Date, default: undefined }, diff --git a/packages/mobile-ui-vue/components/date-picker/src/date-picker.component.tsx b/packages/mobile-ui-vue/components/date-picker/src/date-picker.component.tsx index 114cbec904f7b4446dc6f0481e33218f1084ded4..629ae348f889a06a36cccb9384387b913f7d3550 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/date-picker.component.tsx +++ b/packages/mobile-ui-vue/components/date-picker/src/date-picker.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@components/common'; -import { ButtonEdit } from '@/components/button-edit'; -import { usePickerInputState } from '@/components/picker'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { ButtonEdit } from '@farris/mobile-ui-vue/button-edit'; +import { usePickerInputState } from '@farris/mobile-ui-vue/picker'; import { datePickerProps, DATA_PICKER_NAME } from './date-picker.props'; import DatePickerPanel from './date-picker-panel.component'; @@ -22,6 +22,7 @@ export default defineComponent({ format: props.format, maxDate: props.maxDate, minDate: props.minDate, + modelValueType: props.modelValueType, visiableOptionCount: props.visiableOptionCount, optionFormatter: props.optionFormatter, onChange: handleChange, diff --git a/packages/mobile-ui-vue/components/date-picker/src/date-picker.props.ts b/packages/mobile-ui-vue/components/date-picker/src/date-picker.props.ts index 2f458104e9c181820a55c26ec9ccd93afd2688e5..54ffec58aa00bdab7633ab8d1a28d047a7723ab6 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/date-picker.props.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/date-picker.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes } from 'vue'; -import { buttonEditProps } from '@/components/button-edit'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import { buttonEditProps } from '@farris/mobile-ui-vue/button-edit'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; import datePickerSchema from './schema/date-picker.schema.json'; @@ -12,9 +12,11 @@ export const datePickerProps = { ...buttonEditProps, ...datePickerPanelProps, + placeholder: { type: String, default: '请选择日期' }, + round: { type: Boolean, default: false } }; export type DatePickerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(datePickerProps, datePickerSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(datePickerProps, datePickerSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/date-picker/src/designer/date-picker.design.component.tsx b/packages/mobile-ui-vue/components/date-picker/src/designer/date-picker.design.component.tsx index 58e12ca2f0c5b00fbbcf622fff624a8d557c4222..f3f77598216f84f08cda60302ac4dd5a7f2e2a34 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/designer/date-picker.design.component.tsx +++ b/packages/mobile-ui-vue/components/date-picker/src/designer/date-picker.design.component.tsx @@ -16,7 +16,7 @@ */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; import { useDesignerRules } from './use-designer-rules'; import { datePickerProps, DatePickerProps } from '../date-picker.props'; import DatePickerInput from '../..'; diff --git a/packages/mobile-ui-vue/components/date-picker/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/date-picker/src/designer/use-designer-rules.ts index fd48c2cf3fac7df1cebfa753fc253cd2a4f1410d..8abda334f14b5e9f8da55fc0cf438c8d1b84e7bb 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { DatePickerProperty } from "../property-config/date-picker.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts b/packages/mobile-ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts index 0dad89b0fb18ac1fdb59ef5c0ed349049f375187..1ea66076a515b4e20972f5532dbe058505703663 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts @@ -1,44 +1,72 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; -import { DATE_FORMATS } from "./date-format"; +import { InputBaseProperty } from '@farris/mobile-ui-vue/common'; +import { DATE_FORMATS } from './date-format'; export class DatePickerProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } + getEditorProperties(propertyData: any) { + const displayFormatOptions = this.getDateFormatOptions(propertyData?.editor); + return this.getComponentConfig( + propertyData, + {}, + { + title: { + description: '', + title: '标题', + type: 'string', + }, + valueFormat: { + description: '', + title: '日期格式', + type: 'enum', + editor: { + data: displayFormatOptions + } + }, + maxDate: { + description: '', + title: '最大日期', + type: 'string', + editor: { + type: 'date-picker', + displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + minDate: propertyData?.editor?.minDate || '1900-01-01', + maxDate: '9999-12-31', + showTime: false + }, + refreshPanelAfterChanged: true + }, + minDate: { + description: '', + title: '最小日期', + type: 'string', + editor: { + type: 'date-picker', + displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + minDate: '1900-01-01', + maxDate: propertyData?.editor?.maxDate || '9999-12-31', + showTime: false + }, + refreshPanelAfterChanged: true + } + } + ); + } + private getDateFormatOptions(editorData: any) { + let formats: any[] = []; + const { timeFormats, yMdFormats, yMFormats, mdFormats, yFormats } = DATE_FORMATS(); - getEditorProperties(propertyData: any) { - const displayFormatOptions = this.getDateFormatOptions(propertyData?.editor); - return this.getComponentConfig(propertyData, { type: "year-month-day" }, { - placeholder: { - description: "空值时,输入控件内的占位文本", - title: "提示文本", - type: "string" - }, - displayFormat: { - description: "", - title: "显示格式", - type: "enum", - editor: { - data: displayFormatOptions - } - } - }); - } - - private getDateFormatOptions(editorData: any) { - let formats: any[] = []; - const { timeFormats, yMdFormats, yMFormats, mdFormats, yFormats } = DATE_FORMATS(); - - formats = formats.concat(timeFormats); - - formats = formats.concat(yMdFormats); - formats = formats.concat(yMFormats); - formats = formats.concat(yFormats); - formats = formats.concat(mdFormats); - - return formats; - } + formats = formats.concat(yMdFormats); + // formats = formats.concat(timeFormats); + // formats = formats.concat(yMFormats); + // formats = formats.concat(yFormats); + // formats = formats.concat(mdFormats); + return formats; + } } diff --git a/packages/mobile-ui-vue/components/date-picker/src/schema/date-picker.schema.json b/packages/mobile-ui-vue/components/date-picker/src/schema/date-picker.schema.json index e9c26da211018e28e07e5a626c35a6797e90638b..0174321e036b9c9b85295d6dcc839f1baac74faf 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/schema/date-picker.schema.json +++ b/packages/mobile-ui-vue/components/date-picker/src/schema/date-picker.schema.json @@ -12,7 +12,7 @@ "type": { "description": "控件类型", "type": "string", - "default": "textarea" + "default": "date-picker" }, "appearance": { "description": "外观", diff --git a/packages/mobile-ui-vue/components/date-picker/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/date-picker/src/schema/schema-mapper.ts index 6fc7657c6edc1ae23f80104748ebc90730123a79..70f3c0e7744a5425bfce8cf5f4f3e9b295d9073e 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/date-picker/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/date-picker/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/date-picker/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/date-picker/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/date-time-picker/index.ts b/packages/mobile-ui-vue/components/date-time-picker/index.ts index 8857ca520d62af278fb4b6e3a4703e2ec757beac..04222bedc9ceb06c750fd01edef906f0f1353980 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/index.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/index.ts @@ -1,7 +1,8 @@ -import { withInstall, withRegister } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import DateTimePickerInputInstallless from './src/date-time-picker.component'; import DateTimePickerPanelInstallless from './src/date-time-picker-panel.component'; -import { propsResolver } from './src/date-time-picker.props'; +import { propsResolverGenerator } from './src/date-time-picker.props'; +import DateTimePickerDesigner from './src/designer/date-picker.design.component'; export * from './src/date-time-picker-panel.props'; @@ -10,7 +11,8 @@ const DateTimePicker = withInstall(DateTimePickerInputInstallless); // 注册运行时及设计时 const DATETIME_PICKER_REGISTERED_NAME = 'datetime-picker'; -withRegister(DateTimePicker, { name: DATETIME_PICKER_REGISTERED_NAME, propsResolver }); +withRegister(DateTimePicker, { name: DATETIME_PICKER_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(DateTimePicker, { name: DATETIME_PICKER_REGISTERED_NAME, propsResolverGenerator, designerComponent: DateTimePickerDesigner }); export { DateTimePicker, DateTimePickerPanel }; export default DateTimePicker; diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/composition/type.ts b/packages/mobile-ui-vue/components/date-time-picker/src/composition/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb6b7b653e04836c87fb7e2ed8e68fd779096c6f --- /dev/null +++ b/packages/mobile-ui-vue/components/date-time-picker/src/composition/type.ts @@ -0,0 +1,8 @@ +import { DatePickerType } from "@farris/mobile-ui-vue/date-picker"; +import { TimePickerType } from "@farris/mobile-ui-vue/time-picker"; + +export const enum DateTimeType { + DateTime = `${DatePickerType.Date} ${TimePickerType.Time}`, + DateHour = `${DatePickerType.Date} ${TimePickerType.Hours}`, + DateMinute = `${DatePickerType.Date} ${TimePickerType.HoursMinutes}` +} diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-state.ts b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-state.ts index 0ebe74e483500d655643a53d9d30337c2b433fff..947eb2714105fe72baace863cc3832f4fccbbeb5 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-state.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-state.ts @@ -1,13 +1,13 @@ import { computed, ref } from "vue"; -import { DatePickerType, DatePickerPanelTypeMap } from "@/components/date-picker"; +import { DatePickerType } from "@farris/mobile-ui-vue/date-picker"; import { DateTimePickerPanelProps } from "../date-time-picker-panel.props"; export const useDateState = (props: DateTimePickerPanelProps) => { const dateType = computed(() => { - return (props.type.split(" ")[0] as DatePickerType) || DatePickerPanelTypeMap.Date; + return (props.type.split(" ")[0] as DatePickerType) || DatePickerType.Date; }); const dateFormat = computed(() => { - return props.format.split(" ")[0] || 'YYYY-MM-DD'; + return props.format.split(" ")[0] || 'yyyy-MM-dd'; }); const dateValue = ref(); diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-time-value.ts b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-time-value.ts index 1f70346ee7778ba46e80133cff285e256d01ceed..361accc5cebbf8bc9a671fb73a3b2f6822a124a8 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-time-value.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-date-time-value.ts @@ -1,6 +1,6 @@ import { watch } from "vue"; +import { compareDate, formatDate, isDate, parseDate } from "@farris/mobile-ui-vue/common"; import { DateTimePickerPanelProps } from "../date-time-picker-panel.props"; -import { compareDate, formatDate, isDate, parseDate } from "@components/common"; import { DateState } from "./use-date-state"; import { TimeState } from "./use-time-state"; diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-time-state.ts b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-time-state.ts index 367c9646b42e5f56785ab93594622efc492df124..47d04a9b1c9decbc21521dfec4ea2c281c9228f9 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-time-state.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/composition/use-time-state.ts @@ -1,14 +1,14 @@ import { computed, ref } from "vue"; -import { TimePickerPanelType, TimePickerPanelTypeMap } from "@components/time-picker"; +import { TimePickerType } from "@farris/mobile-ui-vue/time-picker"; import { DateTimePickerPanelProps } from "../date-time-picker-panel.props"; -import { formatDate, isEqualDate } from "@components/common"; +import { formatDate, isEqualDate } from "@farris/mobile-ui-vue/common"; import { DateState } from "./use-date-state"; export const useTimeState = (props: DateTimePickerPanelProps, datePropsComposition: DateState) => { const { dateValue } = datePropsComposition; const timeType = computed(() => { - return (props.type.split(" ")[1] as TimePickerPanelType) || TimePickerPanelTypeMap.Time; + return (props.type.split(" ")[1] as TimePickerType) || TimePickerType.Time; }); const timeFormat = computed(() => { return props.format.split(" ")[1] || 'HH:mm:ss'; diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.component.tsx b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.component.tsx index dc0880b9b22ecd98ea14949c150b453079af46cd..bbc75bebf38f3c950cc7883df1436b94000d35be 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.component.tsx +++ b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.component.tsx @@ -1,7 +1,7 @@ import { defineComponent } from 'vue'; -import { DatePickerPanel } from '@/components/date-picker'; -import { TimePickerPanel } from '@components/time-picker'; -import PickerGroup from '@/components/picker-group'; +import { DatePickerPanel } from '@farris/mobile-ui-vue/date-picker'; +import { TimePickerPanel } from '@farris/mobile-ui-vue/time-picker'; +import PickerGroup from '@farris/mobile-ui-vue/picker-group'; import { useDateState, useDateTimeValue, useTimeState } from './composition'; import { dateTimePickerPanelProps, DATE_TIME_PICKER_PANEL_NAME } from './date-time-picker-panel.props'; diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.props.ts b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.props.ts index c3358f28753049a009771866ce522b4b903c20c3..764f4c16036ee57e7c99512082fc1d9e54776e0f 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.props.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker-panel.props.ts @@ -1,25 +1,19 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { DatePickerPanelTypeMap } from '@/components/date-picker'; -import { TimePickerPanelTypeMap } from '@/components/time-picker'; +import { ModelValueType } from '@farris/mobile-ui-vue/date-picker'; +import { DateTimeType } from './composition/type'; export const DATE_TIME_PICKER_PANEL_NAME = 'FmDateTimePickerPanel'; -export const enum DateTimeTypeMap { - DateTime = `${DatePickerPanelTypeMap.Date} ${TimePickerPanelTypeMap.Time}`, - DateHour = `${DatePickerPanelTypeMap.Date} ${TimePickerPanelTypeMap.Hours}`, - DateMinute = `${DatePickerPanelTypeMap.Date} ${TimePickerPanelTypeMap.HoursMinutes}` -} - -type DateTimeType = `${DateTimeTypeMap}`; - export const dateTimePickerPanelProps = { title: { type: String, default: '' }, - type: { type: String as PropType, default: DateTimeTypeMap.DateTime }, + type: { type: String as PropType, default: DateTimeType.DateTime }, modelValue: { type: [String, Date], default: '' }, - format: { type: String, default: 'YYYY-MM-DD HH:mm:ss' }, + modelValueType: { type: String as PropType, default: '' }, + + format: { type: String, default: 'yyyy-MM-dd HH:mm:ss' }, maxDate: { type: Date, default: undefined }, diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.component.tsx b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.component.tsx index 6a2c058bab5f8d0b2c91c718747dc1317e490819..78aa563838e89a5e29383281340062782b4b95aa 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.component.tsx +++ b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@components/common'; -import { usePickerInputState } from '@/components/picker'; -import ButtonEdit from '@/components/button-edit'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { usePickerInputState } from '@farris/mobile-ui-vue/picker'; +import ButtonEdit from '@farris/mobile-ui-vue/button-edit'; import { dateTimePickerProps, DATA_TIME_PICKER_NAME } from './date-time-picker.props'; import DateTimePickerPanel from './date-time-picker-panel.component'; diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.props.ts b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.props.ts index 2806cdb68478f7ed3d12e29ee17349f9fbc0e179..c2a66c2a27857ad4a581e84a3114865e49d7b193 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.props.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/date-time-picker.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes } from 'vue'; -import { buttonEditProps } from '@/components/button-edit'; +import { buttonEditProps } from '@farris/mobile-ui-vue/button-edit'; import { dateTimePickerPanelProps } from './date-time-picker-panel.props'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaResolver } from './schema/schema-resolver'; import { schemaMapper } from './schema/schema-mapper'; import dateTimePickerSchema from './schema/datetime-picker.schema.json' @@ -10,11 +10,12 @@ export const DATA_TIME_PICKER_NAME = 'FmDateTimePicker'; export const dateTimePickerProps = { ...buttonEditProps, - ...dateTimePickerPanelProps + ...dateTimePickerPanelProps, + placeholder: { type: String, default: '请选择日期时间' }, }; export type DateTimePickerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( dateTimePickerProps, dateTimePickerSchema, schemaMapper, schemaResolver ); diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/designer/date-picker.design.component.tsx b/packages/mobile-ui-vue/components/date-time-picker/src/designer/date-picker.design.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..feaea41cd8b43103e1f9e865025e42641cca6d2a --- /dev/null +++ b/packages/mobile-ui-vue/components/date-time-picker/src/designer/date-picker.design.component.tsx @@ -0,0 +1,37 @@ +import { computed, defineComponent, inject, onMounted, ref } from 'vue'; + +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; +import { useDesignerRules } from './use-designer-rules'; +import { ButtonEdit, buttonEditProps} from '@farris/mobile-ui-vue/button-edit'; + +export default defineComponent({ + name: 'FmDatePickerDesign', + props: buttonEditProps, + emits: [], + setup(props, context) { + const elementRef = ref(); + const designItemContext = inject('design-item-context') as DesignerItemContext; + const designerHostService = inject('designer-host-service'); + const designerRulesComposition = useDesignerRules(designItemContext, designerHostService); + const componentInstance = useDesignerComponent(elementRef, designItemContext,designerRulesComposition); + + onMounted(() => { + elementRef.value.componentInstance = componentInstance; + }); + + context.expose(componentInstance.value); + + const inputProps = computed(() => ({ + ...props, + editable: false, + readonly: true, + modelValue: '' + })); + + return () => { + return ( + + ); + }; + } +}); diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/date-time-picker/src/designer/use-designer-rules.ts new file mode 100644 index 0000000000000000000000000000000000000000..3219c6ed65d399c1d6ff7c73812ce690654aba5f --- /dev/null +++ b/packages/mobile-ui-vue/components/date-time-picker/src/designer/use-designer-rules.ts @@ -0,0 +1,15 @@ +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DateTimePickerProperty } from "../property-config/date-picker.property-config"; +export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { + + const schema = designItemContext.schema as ComponentSchema; + + // 构造属性配置方法 + function getPropsConfig(componentId: string, componentInstance: DesignerComponentInstance) { + const dateTimePickerProps = new DateTimePickerProperty(componentId, designerHostService); + return dateTimePickerProps.getPropertyConfig(schema, componentInstance); + } + + return { getPropsConfig } as UseDesignerRules; + +} diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-format.ts b/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-format.ts new file mode 100644 index 0000000000000000000000000000000000000000..7a962b1db6a7fe2faf572e16c8c75077b3a6f6c9 --- /dev/null +++ b/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-format.ts @@ -0,0 +1,79 @@ +export function DATE_FORMATS() { + + let languageCode = 'zh-CHS'; + if (window && window.top && window.top.localStorage && window.top.localStorage.languageCode) { + ({ languageCode } = window.top.localStorage); + } + + const timeFormats = [ + { id: 'yyyy-MM-dd HH:mm:ss', name: 'yyyy-MM-dd HH:mm:ss' }, + { id: 'yyyy/MM/dd HH:mm:ss', name: 'yyyy/MM/dd HH:mm:ss' }, + { id: 'yyyyMMddHHmmss', name: 'yyyyMMddHHmmss' }, + { id: 'yyyy-MM-dd HH:mm', name: 'yyyy-MM-dd HH:mm' }, + { id: 'yyyy/MM/dd HH:mm', name: 'yyyy/MM/dd HH:mm' }, + { id: 'yyyyMMddHHmm', name: 'yyyyMMddHHmm' } + ]; + const yMdFormats = [ + { id: 'yyyy-MM-dd', name: 'yyyy-MM-dd' }, + { id: 'yyyy/MM/dd', name: 'yyyy/MM/dd' }, + { id: 'yyyyMMdd', name: 'yyyyMMdd' }, + { id: 'MM/dd/yyyy', name: 'MM/dd/yyyy' } + ]; + const yMFormats = [ + { id: 'yyyy-MM', name: 'yyyy-MM' }, + { id: 'yyyy/MM', name: 'yyyy/MM' }, + { id: 'yyyyMM', name: 'yyyyMM' } + ]; + + const mdFormats = [ + { id: 'MM/dd', name: 'MM/dd' }, + { id: 'MMdd', name: 'MMdd' }, + { id: 'MM-dd', name: 'MM-dd' } + ]; + + const yFormats = [ + { id: 'yyyy', name: 'yyyy' } + ]; + + // 区分语言 + if (languageCode === 'zh-CHS') { + timeFormats.push( + { id: 'yyyy年MM月dd日 HH时mm分ss秒', name: 'yyyy年MM月dd日 HH时mm分ss秒' }, + { id: 'yyyy年MM月dd日 HH时mm分', name: 'yyyy年MM月dd日 HH时mm分' } + ); + yMdFormats.push( + { id: 'yyyy年MM月dd日', name: 'yyyy年MM月dd日' } + ); + yMFormats.push( + { id: 'yyyy年MM月', name: 'yyyy年MM月' } + ); + mdFormats.push( + { id: 'MM月dd日', name: 'MM月dd日' } + ); + yFormats.push( + { id: 'yyyy年', name: 'yyyy年' } + ); + } + if (languageCode === 'zh-CHT') { + timeFormats.push( + { id: 'yyyy年MM月dd日 HH時mm分ss秒', name: 'yyyy年MM月dd日 HH時mm分ss秒' }, + { id: 'yyyy年MM月dd日 HH時mm分', name: 'yyyy年MM月dd日 HH時mm分' } + ); + yMdFormats.push( + { id: 'yyyy年MM月dd日', name: 'yyyy年MM月dd日' } + ); + yMFormats.push( + { id: 'yyyy年MM月', name: 'yyyy年MM月' } + ); + mdFormats.push( + { id: 'MM月dd日', name: 'MM月dd日' } + ); + yFormats.push( + { id: 'yyyy年', name: 'yyyy年' } + ); + } + + + return { timeFormats, yMFormats, yMdFormats, mdFormats, yFormats }; + +} diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-picker.property-config.ts b/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-picker.property-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..5fd91541b73055875c6d0e1adac12fd990b041ee --- /dev/null +++ b/packages/mobile-ui-vue/components/date-time-picker/src/property-config/date-picker.property-config.ts @@ -0,0 +1,73 @@ +import { InputBaseProperty } from '@farris/mobile-ui-vue/common'; +import { DATE_FORMATS } from './date-format'; + +export class DateTimePickerProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } + + getEditorProperties(propertyData: any) { + const displayFormatOptions = this.getDateFormatOptions(propertyData?.editor); + return this.getComponentConfig( + propertyData, + {}, + { + title: { + description: '', + title: '标题', + type: 'string', + }, + valueFormat: { + description: '', + title: '日期格式', + type: 'enum', + editor: { + data: displayFormatOptions + } + }, + maxDate: { + description: '', + title: '最大日期', + type: 'string', + editor: { + type: 'date-picker', + displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd HH:mm:ss', + valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd HH:mm:ss', + minDate: propertyData?.editor?.minDate || '1900-01-01', + maxDate: '9999-12-31', + showTime: true + }, + refreshPanelAfterChanged: true + }, + minDate: { + description: '', + title: '最小日期', + type: 'string', + editor: { + type: 'date-picker', + displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd HH:mm:ss', + valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd HH:mm:ss', + minDate: '1900-01-01', + maxDate: propertyData?.editor?.maxDate || '9999-12-31', + showTime: true + }, + refreshPanelAfterChanged: true + } + } + ); + } + + private getDateFormatOptions(editorData: any) { + let formats: any[] = []; + const { timeFormats, yMdFormats, yMFormats, mdFormats, yFormats } = DATE_FORMATS(); + + formats = formats.concat(timeFormats); + + // formats = formats.concat(yMdFormats); + // formats = formats.concat(yMFormats); + // formats = formats.concat(yFormats); + // formats = formats.concat(mdFormats); + + return formats; + } +} diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/schema/datetime-picker.schema.json b/packages/mobile-ui-vue/components/date-time-picker/src/schema/datetime-picker.schema.json index 75a07a3f60828d429477fa1b2e70057706e492af..73f07942acef1b63cab6cbd3e2f8e3783f4bf8cf 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/schema/datetime-picker.schema.json +++ b/packages/mobile-ui-vue/components/date-time-picker/src/schema/datetime-picker.schema.json @@ -12,7 +12,7 @@ "type": { "description": "控件类型", "type": "string", - "default": "textarea" + "default": "datetime-picker" }, "appearance": { "description": "外观", diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-mapper.ts index 00a707c6fba6386e38aa297ff465abea8714205a..a14506b5dd6337cb6648aab10116a419f8689ebb 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/date-time-picker/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/designer-canvas/index.ts b/packages/mobile-ui-vue/components/designer-canvas/index.ts deleted file mode 100644 index 6ce6546f37b7992e7cd5fe27f3f9b221c3c3558b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import FDesignerCanvasInstallless from './src/designer-canvas.component'; -import FDesignerItem from './src/components/designer-item.component'; -import { DgControl } from './src/composition/dg-control'; -import type { DesignerHostService, UseDesignerRules } from './src/composition/types'; -import { withInstall } from '../common'; - -export * from './src/composition/props/designer-canvas.props'; -export * from './src/composition/function/use-designer-component'; -export * from './src/composition/function/use-designer-inner-component'; -export * from './src/types'; -const FDesignerCanvas = withInstall(FDesignerCanvasInstallless); - -export { FDesignerCanvas, FDesignerItem, DgControl, UseDesignerRules, DesignerHostService }; -export default FDesignerCanvas; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-inner-item.component.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-inner-item.component.tsx deleted file mode 100644 index 9225b195cbf6ee9e2a52ea21a851accdf8372f28..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-inner-item.component.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import { Ref, SetupContext, computed, defineComponent, inject, onMounted, provide, ref, watch, onBeforeUnmount, withModifiers } from 'vue'; -import { DesignerInnerItemPropsType, designerInnerItemProps } from '../composition/props/designer-inner-item.props'; -import { DraggingResolveContext, UseDragula } from '../composition/types'; -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from '../types'; -import { canvasChanged, setPositionOfButtonGroup } from '../composition/designer-canvas-changed'; -import { useDesignerInnerComponent } from '../composition/function/use-designer-inner-component'; - -const FDesignerInnerItem = defineComponent({ - name: 'FDesignerInnerItem', - props: designerInnerItemProps, - emits: ['selectionChange', 'addComponent', 'removeComponent'], - setup(props: DesignerInnerItemPropsType, context) { - const canMove = ref(props.canMove); - const canAdd = ref(props.canAdd); - const canDelete = ref(props.canDelete); - const canNested = ref(false); - const contentKey = ref(props.contentKey); - const childType = ref(props.childType); - const childLabel = ref(props.childLabel); - const schema = ref(props.modelValue); - const designComponentStyle = ref(''); - const designerItemElementRef = ref(); - const useDragulaComposition = inject('canvas-dragula'); - const componentInstance = ref() as Ref; - const parent = inject('design-item-context'); - const designItemContext = { designerItemElementRef, componentInstance, schema: schema.value, parent, setupContext: context as SetupContext }; - provide('design-item-context', designItemContext); - - const designerItemClass = computed(() => { - const classObject = { - 'farris-component': true, - // 受position-relative影响,整个容器的高度不能被撑起 - 'flex-fill': props.id === 'root-component', - 'position-relative': canMove.value || canDelete.value, - 'farris-nested': canNested.value, - 'can-move': canMove.value, - 'd-none': designerItemElementRef.value && (designerItemElementRef.value as HTMLElement).classList.contains('d-none') - } as Record; - return classObject; - }); - - const desginerItemStyle = computed(() => { - const styleObject = {} as Record; - if (designComponentStyle.value) { - designComponentStyle.value.split(';').reduce((result: Record, styleString: string) => { - const [styleKey, styleValue] = styleString.split(':'); - if (styleKey) { - result[styleKey] = styleValue; - } - return result; - }, styleObject); - } - return styleObject; - }); - - function onClickDeleteButton(payload: MouseEvent, schemaToRemove: ComponentSchema) { - if (parent && parent.schema[contentKey.value]) { - const indexToRemove = parent.schema[contentKey.value].findIndex( - (contentItem: ComponentSchema) => contentItem.id === schemaToRemove.id - ); - // 如果仍然存在子级,点击子级事件,展示属性面板 - if (indexToRemove > -1) { - const childrenSize = parent.schema[contentKey.value].length; - const nextSchema = parent.schema[contentKey.value][indexToRemove % childrenSize]; - const designerItem = parent.designerItemElementRef.value.querySelector( - `#${nextSchema.id}-design-item` - ); - parent.schema[contentKey.value].splice(indexToRemove, 1); - - // 此处删除子组件schame后,会自动选中第一个元素但属性面板不更新,暂时绕过此问题,使用emit removeComponent方式来解决 - canvasChanged.value++; - context.emit('removeComponent'); - context.emit('selectionChange'); - } - } - - } - - function onClickAddButton(payload: MouseEvent) { - if (componentInstance.value.addNewChildComponentSchema) { - const resolveContext = { - componentType: childType.value, - label: childLabel.value, - parentComponentInstance: componentInstance.value, - targetPosition: -1 - } as DraggingResolveContext; - const childComponentSchema = componentInstance.value.addNewChildComponentSchema(resolveContext); - schema.value[contentKey.value].push(childComponentSchema); - context.emit('addComponent'); - } - } - - function renderAddButton() { - return ( - canAdd.value && ( -
{ - onClickAddButton(payload); - }}> - -
- ) - ); - } - - function renderDeleteButton(componentSchema: ComponentSchema) { - return ( - canDelete.value && ( -
- onClickDeleteButton(payload as MouseEvent, componentSchema), - ['stop'])}> - -
- ) - ); - } - function renderMoveButton() { - return ( - canMove.value && ( -
- -
- ) - ); - } - - function renderIconPanel(componentSchema: ComponentSchema) { - return ( -
-
- {renderAddButton()} - {renderMoveButton()} - {renderDeleteButton(componentSchema)} -
-
- ); - } - - watch( - () => props.modelValue, - (value: any) => { - schema.value = value; - designItemContext.schema = value; - } - ); - - function updatePositionOfButtonGroup(e: Event | any) { - const targetEl = e.target as any; - setPositionOfButtonGroup(targetEl); - } - - function bindingScrollEvent() { - if (schema.value?.contents?.length && designerItemElementRef.value) { - designerItemElementRef.value.addEventListener('scroll', updatePositionOfButtonGroup); - } - } - - function createDefaultComponentInstance() { - const designerItemElement = designerItemElementRef.value as HTMLElement; - const innerComponentElementRef = ref(designerItemElement.children[1] as HTMLElement); - const innerComponentInstance = useDesignerInnerComponent(innerComponentElementRef, designItemContext); - return innerComponentInstance.value; - } - - onMounted(() => { - if (designerItemElementRef.value) { - const draggableContainer = designerItemElementRef.value.querySelector( - `[data-dragref='${schema.value.id}-container']` - ); - componentInstance.value = (draggableContainer && draggableContainer.componentInstance) ? - draggableContainer.componentInstance.value : createDefaultComponentInstance(); - - if (useDragulaComposition && draggableContainer) { - useDragulaComposition.attachComponents(draggableContainer, schema.value); - } - canNested.value = componentInstance.value.canNested !== undefined ? componentInstance.value.canNested : canNested.value; - canAdd.value = componentInstance.value.canAdd !== undefined ? componentInstance.value.canAdd : canAdd.value; - canDelete.value = componentInstance.value.canDelete !== undefined ? componentInstance.value.canDelete : canDelete.value; - canMove.value = componentInstance.value.canMove !== undefined ? componentInstance.value.canMove : canMove.value; - designComponentStyle.value = componentInstance.value.styles || ''; - if (designerItemElementRef.value) { - designerItemElementRef.value.componentInstance = componentInstance; - designerItemElementRef.value.designItemContext = designItemContext; - } - } - bindingScrollEvent(); - - canvasChanged.value++; - }); - - onBeforeUnmount(() => { - if (designerItemElementRef.value) { - designerItemElementRef.value.removeEventListener('scroll', updatePositionOfButtonGroup); - } - }); - - function onClickDesignerItem(payload: MouseEvent) { - - if (payload) { - payload.preventDefault(); - payload.stopPropagation(); - } - let draggabledesignerItemElementRef: any = designItemContext.designerItemElementRef; - const designerItemElement = designerItemElementRef.value as HTMLElement; - if (designerItemElement) { - const currentFocusedElements = document.getElementsByClassName('dgComponentFocused') as HTMLCollectionOf; - // 重复点击 - const duplicateClick = - currentFocusedElements && - currentFocusedElements.length === 1 && - currentFocusedElements[0] === designerItemElementRef.value; - if (!duplicateClick) { - Array.from(currentFocusedElements).forEach((element: HTMLElement) => element.classList.remove('dgComponentFocused')); - Array.from(document.getElementsByClassName('dgComponentSelected') as HTMLCollectionOf).forEach( - (element: HTMLElement) => element.classList.remove('dgComponentSelected') - ); - - designerItemElement.classList.add('dgComponentFocused'); - context.emit('selectionChange', schema.value.type, schema.value, props.componentId, componentInstance.value); - if (componentInstance.value.getDraggableDesignItemElement) { - draggabledesignerItemElementRef = componentInstance.value.getDraggableDesignItemElement(designItemContext); - if (draggabledesignerItemElementRef && draggabledesignerItemElementRef.value) { - draggabledesignerItemElementRef.value.classList.add('dgComponentSelected'); - - } - } - } - } - - updatePositionOfButtonGroup({ target: draggabledesignerItemElementRef?.value }); - } - - return () => { - return ( -
- {renderIconPanel(schema.value)} - {context.slots.default && context.slots.default()} -
- ); - }; - } -}); -export default FDesignerInnerItem; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-item.component.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-item.component.tsx deleted file mode 100644 index 04e847449278377e6c580da191f46605d8969f4f..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-item.component.tsx +++ /dev/null @@ -1,340 +0,0 @@ - -import { Ref, SetupContext, computed, defineComponent, inject, onMounted, provide, ref, watch, onBeforeUnmount } from 'vue'; -import { DesignerItemPropsType, designerItemProps } from '../composition/props/designer-item.props'; -import { componentMap, componentPropsConverter } from './maps'; -import { UseDragula } from '../composition/types'; -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from '../types'; -import FDesignerPlaceholder from './designer-placeholder.component'; -import { canvasChanged, setPositionOfButtonGroup } from '../composition/designer-canvas-changed'; -import { getCustomClass } from '@/components/common'; - -const FDesignerItem = defineComponent({ - name: 'FDesignerItem', - props: designerItemProps, - emits: ['selectionChange'], - setup(props: DesignerItemPropsType, context) { - const id = ref(`${props.modelValue.id}-component`); - const canMove = ref(props.canMove); - const canDelete = ref(props.canDelete); - const canNested = ref(false); - const schema = ref(props.modelValue); - const componentId = ref(props.componentId || ''); - const designComponentStyle = ref(''); - const designComponentClass = ref(''); - const designCustomClass = ref(props.customClass); - const designerItemElementRef = ref(); - const useDragulaComposition = inject('canvas-dragula'); - const componentInstance = ref() as Ref; - const parent = inject('design-item-context'); - const designItemContext = { designerItemElementRef, componentInstance, schema: schema.value, parent, setupContext: context as SetupContext }; - provide('design-item-context', designItemContext); - const useFormSchema = inject('useFormSchema'); - - const designerItemClass = computed(() => { - const componentClass = props.modelValue.appearance ? (props.modelValue.appearance.class as string) || '' : ''; - const customButtons = componentInstance.value?.getCustomButtons && componentInstance.value.getCustomButtons(); - let classObject = { - 'farris-component': true, - // 受position-relative影响,整个容器的高度不能被撑起 - 'flex-fill': schema.value.id === 'root-component', - 'position-relative': canMove.value && canDelete.value || (customButtons?.length), - 'farris-nested': canNested.value, - 'can-move': canMove.value, - 'd-none': designerItemElementRef.value && (designerItemElementRef.value as HTMLElement).classList.contains('d-none'), - 'dgComponentSelected': designerItemElementRef.value && (designerItemElementRef.value as HTMLElement).classList.contains('dgComponentSelected'), - 'dgComponentFocused': designerItemElementRef.value && (designerItemElementRef.value as HTMLElement).classList.contains('dgComponentFocused'), - } as Record; - classObject[`farris-component-${schema.value.type}`] = true; - classObject = getCustomClass(classObject, componentClass); - classObject = getCustomClass(classObject, designComponentClass.value); - classObject = getCustomClass(classObject, designCustomClass.value); - return classObject; - }); - - const desginerItemStyle = computed(() => { - const styleObject = {} as Record; - const componentStyle = props.modelValue.appearance ? (props.modelValue.appearance.style as string) || '' : ''; - if (componentStyle) { - componentStyle.split(';').reduce((result: Record, styleString: string) => { - const [styleKey, styleValue] = styleString.split(':'); - result[styleKey] = styleValue; - return result; - }, styleObject); - } - if (designComponentStyle.value) { - designComponentStyle.value.split(';').reduce((result: Record, styleString: string) => { - const [styleKey, styleValue] = styleString.split(':'); - if (styleKey) { - result[styleKey] = styleValue; - } - return result; - }, styleObject); - } - return styleObject; - }); - - function onClickDeleteButton(payload: MouseEvent, schemaToRemove: ComponentSchema) { - if (payload) { - payload.preventDefault(); - payload.stopPropagation(); - } - - // 连同所属组件一起删除,使用场景如data-grid、form控件等。 - if (componentInstance.value.triggerBelongedComponentToDeleteWhenDeleted) { - const belongedComponentInstance = componentInstance.value.getBelongedComponentInstance(componentInstance); - if (belongedComponentInstance && belongedComponentInstance.parent) { - const belongedComponentInstanceParent = ref(belongedComponentInstance?.parent) as any; - const indexToRemove = belongedComponentInstanceParent.value.contents.findIndex( - (contentItem: ComponentSchema) => contentItem.id === belongedComponentInstance.schema.id - ); - belongedComponentInstanceParent.value?.contents?.splice(indexToRemove, 1); - - canvasChanged.value++; - } - return; - } - componentInstance.value.onRemoveComponent(); - let parentContext = parent; - let locatePredicate: any = (contentItem: ComponentSchema) => contentItem.id === schemaToRemove.id; - if (schemaToRemove.type === 'component') { - parentContext = parent?.parent; - locatePredicate = (contentItem: ComponentSchema) => contentItem.component === schemaToRemove.id; - - } - if (parentContext && parentContext.schema.contents) { - const indexToRemove = parentContext.schema.contents.findIndex(locatePredicate); - parentContext.schema.contents.splice(indexToRemove, 1); - - canvasChanged.value++; - context.emit('selectionChange'); - - } - - } - - function renderDeleteButton(componentSchema: ComponentSchema) { - return ( - canDelete.value && ( -
{ - onClickDeleteButton(payload, componentSchema); - }}> - -
- ) - ); - } - - function renderMoveButton() { - return ( - canMove.value && ( -
- -
- ) - ); - } - - function renderCustomButtons() { - const customButtons = componentInstance.value?.getCustomButtons && componentInstance.value.getCustomButtons(); - - return ( - customButtons && - !!customButtons.length && - customButtons.map((buttonConfig: any) => { - return ( -
buttonConfig.onClick && buttonConfig.onClick(payload)}> - -
- ); - }) - ); - } - - function renderIconPanel(componentSchema: ComponentSchema) { - return ( -
-
- {renderDeleteButton(componentSchema)} - {renderMoveButton()} - {renderCustomButtons()} -
-
- ); - } - - function onSelectionChange(schemaType: string, schemaValue: ComponentSchema, componentId: string, componentInstance: DesignerComponentInstance) { - context.emit('selectionChange', schemaType, schemaValue, componentId, componentInstance); - } - - function renderContent(viewSchema: ComponentSchema) { - const componentKey = viewSchema.type; - const Component = componentMap[componentKey]; - const propsConverter = componentPropsConverter[componentKey]; - const viewProps = propsConverter ? propsConverter(viewSchema) : {}; - viewProps.customClass = props.ignore ? viewProps.customClass : ''; - viewProps.componentId = componentId.value; - viewProps.id = viewSchema.id; - const shouldShowPlaceholder = viewSchema.contents && viewSchema.contents.length === 0; - const hasContent = viewSchema.contents && !!viewSchema.contents.length; - return hasContent && Component ? ( - - {(viewSchema.contents as ComponentSchema[]).map((contentSchema: any) => ( - - ))} - - ) : Component ? ( - shouldShowPlaceholder ? ( - - - - ) : ( - - ) - ) : ( -
- ); - } - - function renderChildComponentContent(viewSchema: ComponentSchema) { - const componentKey = viewSchema.type; - if (componentKey === 'component-ref') { - // eslint-disable-next-line prefer-const - let componentSchema = useFormSchema?.getFormSchema().module.components - .find((component: any) => component.id === viewSchema.component); - if (componentSchema) { - - return ; - } - } - } - watch( - () => props.modelValue, - (value: any) => { - schema.value = value; - id.value = `${value.id}-component`; - componentId.value = value.id; - } - ); - - function updatePositionOfButtonGroup(event: Event | any) { - const targetElement = event?.target as any; - setPositionOfButtonGroup(targetElement); - } - /** - * 记录滚动区域 - */ - function recordScrollContainer(element: HTMLElement) { - if (!window['scrollContainerList']) { window['scrollContainerList'] = new Set(); } - - const id = element.getAttribute('id'); - if (id) { - window['scrollContainerList'].add(id); - } - } - - function updatePositionOfBtnGroupWhenScroll(event: Event | any) { - const targetElement = event?.target as any; - recordScrollContainer(targetElement); - updatePositionOfButtonGroup(event); - } - function bindingScrollEvent() { - if (schema.value?.contents?.length && designerItemElementRef.value) { - designerItemElementRef.value.addEventListener('scroll', updatePositionOfBtnGroupWhenScroll); - } - } - - onMounted(() => { - if (designerItemElementRef.value && componentInstance.value && componentInstance.value.schema) { - const draggableContainer = designerItemElementRef.value.querySelector( - `[data-dragref='${componentInstance.value.schema.id}-container']` - ); - if (useDragulaComposition && draggableContainer) { - useDragulaComposition.attachComponents(draggableContainer, schema.value); - } - canNested.value = componentInstance.value.canNested !== undefined ? componentInstance.value.canNested : canNested.value; - canDelete.value = componentInstance.value.canDelete !== undefined ? componentInstance.value.canDelete : canDelete.value; - canMove.value = componentInstance.value.canMove !== undefined ? componentInstance.value.canMove : canMove.value; - designComponentStyle.value = componentInstance.value.styles || ''; - designComponentClass.value = componentInstance.value.designerClass || ''; - if (designerItemElementRef.value) { - designerItemElementRef.value.componentInstance = componentInstance; - designerItemElementRef.value.designItemContext = designItemContext; - } - componentInstance.value.belongedComponentId = componentId.value; - - } - bindingScrollEvent(); - - canvasChanged.value++; - }); - - onBeforeUnmount(() => { - if (designerItemElementRef.value) { - designerItemElementRef.value.removeEventListener('scroll', updatePositionOfButtonGroup); - } - }); - - function onClickDesignerItem(payload: MouseEvent) { - if (payload) { - payload.preventDefault(); - payload.stopPropagation(); - } - let draggabledesignerItemElementRef: any = designItemContext.designerItemElementRef; - const designerItemElement = designerItemElementRef.value as HTMLElement; - if (designerItemElement) { - const currentFocusedElements = document.getElementsByClassName('dgComponentFocused') as HTMLCollectionOf; - // 重复点击 - const duplicateClick = - currentFocusedElements && - currentFocusedElements.length === 1 && - currentFocusedElements[0] === designerItemElementRef.value; - if (!duplicateClick) { - Array.from(currentFocusedElements).forEach((element: HTMLElement) => element.classList.remove('dgComponentFocused')); - Array.from(document.getElementsByClassName('dgComponentSelected') as HTMLCollectionOf).forEach( - (element: HTMLElement) => element.classList.remove('dgComponentSelected') - ); - - designerItemElement.classList.add('dgComponentFocused'); - context.emit('selectionChange', schema.value.type, schema.value, componentId.value, componentInstance.value); - if (componentInstance.value.getDraggableDesignItemElement) { - draggabledesignerItemElementRef = componentInstance.value.getDraggableDesignItemElement(designItemContext); - if (draggabledesignerItemElementRef && draggabledesignerItemElementRef.value) { - draggabledesignerItemElementRef.value.classList.add('dgComponentSelected'); - - } - } - - } - } - - updatePositionOfButtonGroup({ target: draggabledesignerItemElementRef?.value }); - } - - return () => { - return ( - schema.value.type === 'component-ref' ? - renderChildComponentContent(schema.value) : -
- {renderIconPanel(schema.value)} - {renderContent(schema.value)} -
- ); - }; - } -}); -export default FDesignerItem; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-placeholder.component.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-placeholder.component.tsx deleted file mode 100644 index 5dd90cb489ae5a2637354f7ce168bebeaffd8096..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-placeholder.component.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { SetupContext, computed, defineComponent } from 'vue'; -import { DesignerPlaceholderPropsType, designerPlaceholderProps } from '../composition/props/designer-placeholder.props'; - -export default defineComponent({ - name: 'FDesignerPlaceholder', - props: designerPlaceholderProps, - emits: [], - setup(props: DesignerPlaceholderPropsType) { - const designerPlaceholderClass = computed(() => { - const classObject = { - 'drag-and-drop-alert': true, - 'no-drag': true, - 'w-100': true - } as Record; - return classObject; - }); - - const designerPlaceholderStyle = computed(() => { - const styleObject = { - 'height': '60px', - 'display': 'flex', - 'justify-content': 'center', - 'align-items': 'center', - 'margin': 0, - 'padding': '.75rem 1.25rem', - 'border': '1px solid transparent', - 'border-radius': '3px', - 'color': '#315585', - 'background-color': '#dfedff', - 'border-color': '#d2e6ff', - } as Record; - return styleObject; - }); - - return () => ( - - ); - } -}); diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-template-item.component.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-template-item.component.tsx deleted file mode 100644 index 9df082c1b83fdb4e00db0ecec29594280820e066..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/components/designer-template-item.component.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { computed, defineComponent, ref } from 'vue'; -import { DesignerItemPropsType, designerItemProps } from '../composition/props/designer-item.props'; -import { canvasChanged } from '../composition/designer-canvas-changed'; - -const FDesignerTemplateItem = defineComponent({ - name: 'FDesignerTemplateItem', - props: designerItemProps, - emits: ['selectionChange'], - setup(props: DesignerItemPropsType, context) { - const designerItemElementRef = ref(); - - const designerItemClass = computed(() => { - const classObject = { - 'farris-component': true - } as Record; - return classObject; - }); - - function onClickDesignerItem(payload: MouseEvent) { - - if (payload) { - payload.preventDefault(); - payload.stopPropagation(); - } - const designerItemElement = designerItemElementRef.value as HTMLElement; - if (designerItemElement) { - const currentSelectedElements = document.getElementsByClassName('dgComponentFocused') as HTMLCollectionOf; - - // 重复点击 - const duplicateClick = - currentSelectedElements && - currentSelectedElements.length === 1 && - currentSelectedElements[0] === designerItemElementRef.value; - if (!duplicateClick) { - Array.from(currentSelectedElements).forEach((element: HTMLElement) => element.classList.remove('dgComponentSelected')); - Array.from(currentSelectedElements).forEach((element: HTMLElement) => element.classList.remove('dgComponentFocused')); - - designerItemElement.classList.add('dgComponentFocused'); - } - } - canvasChanged.value++; - } - - return () => { - return ( -
- {context.slots.default && context.slots.default()} -
- ); - }; - } -}); -export default FDesignerTemplateItem; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/components/maps.ts b/packages/mobile-ui-vue/components/designer-canvas/src/components/maps.ts deleted file mode 100644 index c44e05d5c1bce00efd3df046344d350403ea97d5..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/components/maps.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { CheckboxGroup, ContentContainer, DatePicker, FormItem, PageHeaderContainer, Picker, RadioGroup, Switch } from "@/components"; -import Button from "@/components/button"; -import Component from "@/components/component"; -import FloatContainer from "@/components/float-container"; -import Form from "@/components/form"; -import InputGroup from "@/components/input-group"; -import ListView from "@/components/list-view"; -import Navbar from "@/components/navbar"; -import PageBodyContainer from "@/components/page-body-container"; -import PageContainer from "@/components/page-container"; -import PageFooterContainer from "@/components/page-footer-container"; -import Textarea from "@/components/textarea"; - -const componentMap: Record = {}; -const componentPropsConverter: Record = {}; -const componentPropertyConfigConverter: Record = {}; - - -let hasLoaded = false; -/** - * 加载设计时组件 - */ -function loadDesignerRegister() { - if (!hasLoaded) { - hasLoaded = true; - Button.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - PageContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - PageHeaderContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - PageBodyContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - PageFooterContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Navbar.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Component.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - ListView.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Form.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - InputGroup.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - FloatContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - ContentContainer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - FormItem.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - DatePicker.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Textarea.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - RadioGroup.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Switch.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - Picker.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - CheckboxGroup.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); - - } -} - -export { componentMap, componentPropsConverter, componentPropertyConfigConverter, loadDesignerRegister }; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/control.css b/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/control.css deleted file mode 100644 index 9044cd61f76655fb7d387bb70f82e0a3516a5b7d..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/control.css +++ /dev/null @@ -1,30 +0,0 @@ -/** 筛选方案 **/ -.f-section-scheme { - background: #fff; - margin: 0.5625rem 0.5rem 0; -} - -/** 标签页tabs **/ -.farris-component-tabs .farris-tabs-content.f-utils-fill-flex-column .farris-component-tab-page:has(.farris-tab-page-active) { - display: flex !important; - overflow: hidden; - flex-shrink: 1; - flex-grow: 1; - flex-basis: 0; - flex-direction: column !important; -} - -/** 布局容器 ResponseLayout **/ -.response-layout { - border: dotted 2px #e8e8e8; - -} - -.response-layout .response-layout-item { - border-right: dotted 2px #e8e8e8; - -} - -.response-layout .response-layout-item:not(:last-child) { - padding-right: 8px !important; -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/designer-canvas.css b/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/designer-canvas.css deleted file mode 100644 index d92b16e7338c8c4ca9b74ef734ddb3feecb7054a..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/class/designer-canvas.css +++ /dev/null @@ -1,284 +0,0 @@ -.form-group-in-canvas .f-cmp-inputgroup .f-state-readonly .input-group-append{ - display: flex !important; -} -.component-btn-group { - flex-direction: row-reverse; - position: absolute; - z-index: 800; - background: #fff; - display: none; - top: -26px; - right: 0; -} - -.component-btn-group > div { - position: fixed; -} - -.farris-component { - /* border: dotted 2px transparent; */ -} - -.farris-component.farris-nested { - padding: 10px !important; - border: dotted 2px #e8e8e8; -} - -.farris-component.farris-nested.dgComponentFocused { - /* padding: 10px; */ - border: dotted 2px #388fff; -} - -.farris-component.can-move { - padding: 2px; -} - -.farris-component.dgComponentSelected > .component-btn-group { - display: flex; -} - -.component-btn-group .component-settings-button { - display: flex; - cursor: pointer; - float: right; - margin-left: 4px; - padding: 0; - font-size: 10px; - line-height: 1.2em; - border-radius: 2px 2px 0px 0px; - width: 24px !important; - height: 24px !important; - color: #fff !important; - background: #388fff !important; -} - -.component-btn-group .component-settings-button .f-icon { - font-size: 18px; - margin: 0 auto; - line-height: 20px; -} - -.component-btn-group .component-settings-button .f-icon.f-icon-yxs_move { - cursor: move; -} - -.farris-component-content-container .drag-container { - display: inherit; - flex-direction: inherit; - flex-shrink: 1; - flex-grow: 1; - flex-basis: 0%; - flex-wrap: inherit; - justify-content: inherit; - align-items: inherit; - width: 100%; - overflow: inherit; - height: inherit; -} - -/* gu-mirror被添加到镜像中 */ -.gu-mirror { - position: fixed !important; - margin: 0 !important; - z-index: 9999 !important; - opacity: 0.8; - -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; - filter: alpha(opacity=80); -} - -.gu-mirror.undroppable .component-settings-button .f-icon-yxs_move { - cursor: no-drop; -} - -.component-btn-group .component-settings-button .f-icon.f-icon-yxs_delete { - color: #fff !important; - background: #388fff !important; -} - -.gu-hide { - display: none !important; -} - -/** 拖拽时镜像元素的父级元素 */ -.gu-unselectable { - -webkit-user-select: none !important; - -moz-user-select: none !important; - -ms-user-select: none !important; - user-select: none !important; -} - -/* 当拖动源元素的镜像时,gu-transit被添加到源元素中。只是增加了透明度。 */ -.gu-transit { - opacity: 0.2; - -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=20)'; - filter: alpha(opacity=20); -} - -/* 拖拽经过某区域时,为区域增加底色 */ -.drag-over:not(.no-drop) { - background-color: #f3f8ff !important; -} - -/** 拖拽区域内的元素不显示按钮区域 */ -.gu-unselectable .farris-component.dgComponentSelected > .component-btn-group { - display: none; -} - -/** 拖拽区域内的镜像元素显示按钮区域 */ -.gu-unselectable .gu-mirror.farris-component.dgComponentSelected > .component-btn-group { - display: flex; -} - -/** 拖拽过程中的源元素不显示按钮区域 */ -.gu-transit.farris-component.dgComponentSelected > .component-btn-group { - display: none; -} - -/* 镜像元素为fixed定位 */ -.gu-mirror.farris-component.dgComponentSelected { - position: fixed !important; -} - -/* 镜像元素的按钮区域定位 */ -.gu-mirror.farris-component.dgComponentSelected > .component-btn-group > div { - position: relative; - top: 0 !important; - left: 0 !important; -} - -/** 镜像元素的按钮区域设置宽度。是为了适配控件本身宽度比较小,但是操作按钮比较多时,按钮被换行的问题 */ -.gu-mirror.farris-component.dgComponentSelected > .component-btn-group { - width: max-content; -} - -.dgComponentFocused { - border-top: 2px dotted #388fff !important; - border-left: 2px dotted #388fff !important; - border-right: 2px dotted #388fff !important; - border-bottom: 2px dotted #388fff !important; -} - -.dgComponentSelected { - border-top: 2px solid #388fff !important; - border-left: 2px solid #388fff !important; - border-right: 2px solid #388fff !important; - border-bottom: 2px solid #388fff !important; -} - -.editorDiv { - background-color: #dbe6f7; - overflow-x: auto; -} - -.editorPanel { - position: relative; - height: 100%; - min-width: 900px; -} - -/** 卡片区块 **/ -.editorDiv .f-struct-like-card { - display: block; -} - -/** 解决farristab 开启内容填充后切换标签页导致内部列表不显示的问题**/ -.editorDiv .farris-tabs.f-tabs-content-fill .f-struct-is-subgrid .f-grid-is-sub { - width: 100%; -} - -/** 解决在模态框中弹出右键菜单 菜单不显示的问题**/ -.ide-framework .cdk-overlay-container { - z-index: 1100; -} -.editorDiv .f-struct-wrapper { - margin-bottom: 15px; -} - -.f-struct-wrapper + .f-struct-wrapper { - position: relative; - display: inherit; - margin-bottom: 15px; -} - -.f-page-is-mainsubcard .f-page-main .f-struct-wrapper { - background: #fff; -} - -/** 解决带导航的列表和带导航的卡片模板中,不显示右侧区域的问题 */ -.editorDiv .f-page-navigate .f-page { - position: absolute !important; -} - -/** 解决带导航的列表和带导航的卡片模板中,右侧区域滚动条位置问题 */ -.editorDiv .f-page-navigate .f-page.f-page-card .f-page-main > .drag-container { - display: block; - overflow: unset; -} - -/* 解决OA模板(带页头的导航类模板) 中,右侧滚动条位置问题 */ -.editorDiv .f-page.f-page-navigate.f-page-is-listnav-with-header .f-page-main .f-page-content-main { - display: block; -} - -/** 解决在弹窗中使用smoothDnd时不显示镜像元素的问题 */ -.smooth-dnd-ghost { - z-index: 1100 !important; -} - -/** 解决零代码设计器中OA类卡片表单滚动条位置问题 */ -.editorDiv .farris-oa-page.f-page-card .f-page-main { - display: block !important; - overflow: auto !important; -} - -/** 解决带筛选方案的列表表单中,选中表格组件后没有上边线的问题 */ -.editorDiv .f-page-has-scheme .f-page-main.farris-component { - margin-top: 0; -} - -/** 解决表单设计器中顶层工具栏的下拉面板被属性面板(z-index:850)遮挡的问题 */ -.dropdown-menu.show { - z-index: 860; -} - -/** 解决拟物风下从从表区域的下拉箭头错位的问题 */ -.f-struct-subsub-wrapper { - padding-top: 0 !important; -} - -/** 新拖拽 */ -.gu-mirror.undroppable { - cursor: no-drop; -} - -.gu-insertion { - position: fixed; - z-index: 840 !important; - pointer-events: none !important; - background-color: #388fff; - height: 4px; - overflow: hidden; -} - -/* 在designer canvas中还原嵌套页面样式,解决desinger和canvas各自f-page样式冲突 */ -.editorPanel .f-page::before { - display: initial !important; -} - -.editorPanel .f-page .f-page-main { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - margin-bottom: 0.5rem !important; -} - -.editorPanel .f-page.f-page-is-listnav .f-page-main { - margin-top: 0.5rem !important; -} - -.editorPanel .f-page .f-page-main .f-page-main { - margin: 0 !important; -} - -.editorPanel .f-page.f-page-has-scheme .f-page-header{ - margin: 0 .5rem; -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/designer-canvas-changed.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/designer-canvas-changed.ts deleted file mode 100644 index 11ada793acc2a6cb1f85d72862c14502e86f102e..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/designer-canvas-changed.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { ref } from "vue"; - -/** 用于响应画布发生变更 */ -export const canvasChanged = ref(0); - -/** - * 判断DOM 是否在可视区域内 - * @param el 元素 - * @param containerEl 容器 - */ -function isElementInViewport(el: HTMLElement, containerEl: HTMLElement) { - const container = containerEl.getBoundingClientRect(); - const box = el.getBoundingClientRect(); - const top = box.top >= container.top; - const bottom = box.top <= container.bottom; - return (top && bottom); -} - -function setPositionForSelectedElement(selectElement: HTMLElement) { - const toolbar = selectElement.querySelector('.component-btn-group') as HTMLElement; - if (!toolbar) { - return; - } - toolbar.style.display = ''; - const toolbarRect = toolbar.getBoundingClientRect(); - const divPanel = toolbar.querySelector('div') as HTMLElement; - if (divPanel) { - const divPanelRect = divPanel.getBoundingClientRect(); - divPanel.style.top = toolbarRect.top + 'px'; - - // 若操作按钮的最左边比画布最左边还要靠左,那么操作按钮就以控件的最左边为界 - let left = toolbarRect.left - divPanelRect.width; - const editorDiv = document.querySelector('.editorDiv'); - if (editorDiv) { - const editorDivRect = editorDiv.getBoundingClientRect(); - if (left < editorDivRect.left) { - const elementRect = selectElement.getBoundingClientRect(); - ({ left } = elementRect); - } - } - divPanel.style.left = left + 'px'; - } -} - -/** - * 定位画布中已选控件的操作按钮的位置 - * @param canvasElement 画布父容器 - */ -export function setPositionOfButtonGroup(canvasElement: HTMLElement) { - if (!canvasElement) { - return; - } - let selectElement: HTMLElement; - if (canvasElement.className.includes('dgComponentSelected')) { - selectElement = canvasElement; - } else { - selectElement = canvasElement.querySelector('.dgComponentSelected') as HTMLElement; - } - if (!selectElement) { - return; - } - - const selectDomRect = selectElement.getBoundingClientRect(); - if (selectDomRect.width === 0 && selectDomRect.height === 0) { - return; - } - const toolbar = selectElement.querySelector('.component-btn-group') as HTMLElement; - if (toolbar) { - - const isInView = isElementInViewport(selectElement, canvasElement); - if (!isInView) { - toolbar.style.display = 'none'; - return; - } - // 计算位置 - setPositionForSelectedElement(selectElement); - } -} - - -/** - * 定位页面中选中控件的操作按钮位置。 - * 场景:控件内部点击收折或者切换显示内容后,需要重新计算页面中下方选中控件的按钮位置。 - * 例如点击section控件的收折图标后,需要重新计算section下方已选控件的操作按钮位置 - */ -export function setPositionOfSelectedComponentBtnGroup(canvasElement: HTMLElement) { - const selectElement = document.querySelector('.dgComponentSelected') as HTMLElement; - if (!selectElement) { - return; - } - const selectedElementRect = selectElement.getBoundingClientRect(); - const elementRect = canvasElement.getBoundingClientRect(); - - const toolbar = selectElement.querySelector('.component-btn-group') as HTMLElement; - if (toolbar) { - const toolbarRect = toolbar.getBoundingClientRect(); - const isBelow = elementRect.top < selectedElementRect.top; - - // 选中控件已显示并且在基准位置的下方 - if (toolbarRect.top !== 0 && isBelow) { - setPositionForSelectedElement(selectElement); - } - } -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/entity/builder-element.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/entity/builder-element.ts deleted file mode 100644 index b071db8858797c51e878802f1839262cb96a72ec..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/entity/builder-element.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 设计器DOM元素结构 - */ -export interface BuilderHTMLElement extends Element{ - /** 记录各子元素对应的控件schema json的集合,用于container类dom节点 */ - childrenContents?: any[]; - - /** 记录element对应的component实例,用于单个component节点 */ - componentInstance?: any; - - component?: any; -}; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/create-design-builder.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/create-design-builder.ts deleted file mode 100644 index 7d950952527e3328b380d4731abfe5eab6551f28..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/create-design-builder.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { SetupContext } from 'vue'; -import { DesignerOutlineProps } from '../../../../designer-outline/src/designer-outline.props'; - -/** 创建设计器 */ -export function createDesigner(props: DesignerOutlineProps, context: SetupContext) { - - function createDesignBuilder(domJson: any) { - // 画布渲染过程中,可能会在控件上补充属性,这种变更用户不感知,所以不需要通知IDE框架 - // window.suspendChangesOnForm = true; - - const elements = document.getElementsByClassName('editorPanel'); - let rootElement; - if (elements && elements.length) { - rootElement = elements[0]; - } - - // if (!DesignerBuilder) { - // return; - // } - - // addServiceToDevkit(); - // const designerHost = addServiceToUI(); - - const childComponents = domJson.module.components.slice(1); - const rootComponent = domJson.module.components[0]; - const designerSchema = { - contents: [rootComponent] - }; - // designBuilder = new DesignerBuilder(rootElement, designerSchema, childComponents, AllComponents, designerHost); - // designBuilder.instance.ready.then(() => { - // onBuilderReady(); - - // 加载控件工具箱 - // controlBox.getDisplayedControls(); - - // 设计器渲染完毕,开始监听DOM变更 - // window.suspendChangesOnForm = false; - // }); - - // designBuilder.instance.on('change', () => { - // onComponentChanged(); - // }); - // designBuilder.instance.on('removeComponent', () => { - // updatePropertyPanel(null); - // onComponentChanged(); - // }); - } - - return { - }; - -}; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx deleted file mode 100644 index 491c53d94b19f9bd19489c1c842c534e1ba32515..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import { ModalFunctions } from "../../../../modal/src/composition/type"; -import { ComponentBindingSourceContext, DesignerHostService, DesignerHTMLElement, DraggingResolveContext } from "../types"; -import { DesignViewModelField, FormVariable } from "../../../../common/entity/entity-schema"; -import { merge } from "lodash-es"; -import { DgControl } from "../dg-control"; -import { DesignerComponentInstance } from "@/components"; - -export function dragResolveService(designerHostService: DesignerHostService) { - /** 弹窗实例 */ - let modalEditorRef: ModalFunctions; - /** 拖拽上下文 */ - let componentResolveContext: DraggingResolveContext; - - /** - * 获取拖拽上下文信息 - */ - function getComponentResolveContext(sourceElement: DesignerHTMLElement, sourceContainer: DesignerHTMLElement, targetContainer: DesignerHTMLElement) - : DraggingResolveContext { - - const resolveContext: DraggingResolveContext = { - componentType: String(sourceElement.getAttribute('data-controltype')), - componentFeature: String(sourceElement.getAttribute('data-feature')), - componentCategory: String(sourceElement.getAttribute('data-category')), - label: String(sourceElement.getAttribute('data-controlTypeName')), - sourceType: String(sourceElement.getAttribute('data-sourceType') || 'move'), - parentComponentInstance: targetContainer.componentInstance.value, - sourceElement, - sourceContainer, - targetContainer, - bindingSourceContext: null - }; - - // 现有控件移动位置:从控件实例上获取控件类型 - if (sourceElement.componentInstance) { - resolveContext.componentType = sourceElement.componentInstance.value.schema?.type; - // resolveContext.componentCategory = sourceElement.componentInstance.value.category; - } - - return resolveContext; - } - /** - * 选择绑定实体后事件 - */ - function onSubmitEntitySelctor(bindingSourceContext: ComponentBindingSourceContext) { - componentResolveContext.bindingSourceContext = bindingSourceContext; - - if (modalEditorRef?.modalRef?.value.close) { - modalEditorRef?.modalRef?.value.close(); - } - } - /** - * 取消绑定实体 - */ - function onCancelEntitySelector() { - componentResolveContext.bindingSourceContext = undefined; - if (modalEditorRef?.modalRef?.value.close) { - modalEditorRef?.modalRef?.value.close(); - } - } - /** - * 选择绑定实体窗口 - */ - function renderEntityComponent() { - const { componentType } = componentResolveContext; - const FEntityBindingSelector = designerHostService.uiProviderService.getUiComponent('FEntityBindingSelector'); - return () => (<> ); - } - /** - * 弹出实体绑定窗口 - */ - function triggerBindingEntity() { - return new Promise((resolve, reject) => { - modalEditorRef = designerHostService.modalService.open({ - title: '选择绑定', - width: 800, - height: 600, - fitContent: false, - showButtons: false, - render: renderEntityComponent(), - rejectCallback:()=>{ - componentResolveContext.bindingSourceContext = undefined; - }, - closedCallback: () => { - resolve(componentResolveContext); - }, - draggable: true - }); - }); - } - /** - * 取消绑定字段后事件 - */ - function onCancelFieldSelector() { - componentResolveContext.bindingSourceContext = undefined; - if (modalEditorRef?.modalRef?.value.close) { - modalEditorRef?.modalRef?.value.close(); - } - } - /** - * 获取控件拖拽后的分组信息,以便于后续记录到视图模型 - */ - function getFieldGroupInfo(parentComponentInstance: DesignerComponentInstance) { - let groupId = ''; - let groupName = ''; - if (DgControl['field-set'] && parentComponentInstance.schema.type === DgControl['field-set'].type) { - groupId = parentComponentInstance.schema.id; - groupName = parentComponentInstance.schema.title; - } - return { groupId, groupName }; - } - /** - * 选择绑定字段后事件 - */ - function onSubmitFieldSelctor(data: { selectedData: any, bindingType: any }) { - if (!data || !data.selectedData || !data.bindingType) { - return; - } - const { selectedData, bindingType } = data; - // 若添加到小分组内,需要向vm保存groupId和groupName - const { groupId, groupName } = getFieldGroupInfo(componentResolveContext.parentComponentInstance); - const bindingSourceContext: ComponentBindingSourceContext = { bindingType: 'field' }; - - if (bindingType === 'Form') { - // 绑定字段 - const entityField = selectedData as DesignViewModelField; - bindingSourceContext.entityFieldNode = entityField; - - bindingSourceContext.designViewModelField = merge({}, entityField, { groupId, groupName }); - - componentResolveContext.bindingSourceContext = bindingSourceContext; - } else { - // 绑定变量 - const varibleField = selectedData as FormVariable; - bindingSourceContext.variableFieldNode = merge({}, varibleField, { groupId, groupName }); - componentResolveContext.bindingSourceContext = bindingSourceContext; - } - - if (modalEditorRef?.modalRef?.value.close) { - modalEditorRef?.modalRef?.value.close(); - } - } - /** - * 绑定字段弹窗 - */ - function renderFieldComponent() { - const { parentComponentInstance } = componentResolveContext; - const viewModelId = designerHostService.formSchemaUtils.getViewModelIdByComponentId(parentComponentInstance?.belongedComponentId); - const editorParams = { - viewModelId, - designerHostService, - disableOccupiedFields: true, - componentSchema: { editor: { type: componentResolveContext.componentType } } - }; - const bindingSettings = { enable: false }; - - const FBindingSelectorContainer = designerHostService.uiProviderService.getUiComponent('FBindingSelectorContainer'); - - return () => (<> ); - } - /** - * 弹出绑定字段的窗口 - */ - function triggerBindingField() { - return new Promise((resolve, reject) => { - modalEditorRef = designerHostService.modalService.open({ - title: '选择绑定', - width: 800, - height: 600, - fitContent: false, - showButtons: false, - render: renderFieldComponent(), - rejectCallback:()=>{ - componentResolveContext.bindingSourceContext = undefined; - }, - closedCallback: () => { - resolve(componentResolveContext); - }, - draggable: true - }); - }); - } - /** - * 生成控件schema结构 - */ - function resolveComponentSchema() { - const { parentComponentInstance } = componentResolveContext; - const componentSchema = parentComponentInstance.addNewChildComponentSchema(componentResolveContext, designerHostService); - componentResolveContext.componentSchema = componentSchema; - } - /** - * 解析拖拽元素,并根据场景展示不同的绑定窗口 - */ - async function resolveBindingSource() { - const { componentCategory } = componentResolveContext; - - switch (componentCategory) { - case 'input': { - await triggerBindingField(); - break; - } - case 'dataCollection': { - await triggerBindingEntity(); - break; - } - - } - } - /** - * 根据拖拽元素解析并创建控件 - */ - async function resolveComponentCreationContextByDrop(sourceElement: DesignerHTMLElement, sourceContainer: DesignerHTMLElement, targetContainer: DesignerHTMLElement): Promise { - componentResolveContext = getComponentResolveContext(sourceElement, sourceContainer, targetContainer); - - await resolveBindingSource(); - - // 若返回 undefined 代表终止后续生成 - if (componentResolveContext.bindingSourceContext === undefined) { - return null; - } else { - resolveComponentSchema(); - return componentResolveContext; - } - - } - - return { - getComponentResolveContext, - resolveComponentCreationContextByDrop - }; -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-inner-component.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-inner-component.ts deleted file mode 100644 index d0858e6471694097110dcac44adcdcfe1709e3ea..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-designer-inner-component.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { inject, Ref, ref } from "vue"; -import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext, UseDesignerRules } from "../types"; -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from "../../types"; -import { getSchemaByType } from '../../../../dynamic-resolver/src/schema-resolver'; - -export function useDesignerInnerComponent( - elementRef: Ref, - designItemContext: DesignerItemContext, - designerRules?: UseDesignerRules -): Ref { - const styles = (designerRules && designerRules.getStyles && designerRules.getStyles()) || ''; - const componentInstance = ref(); - /** - * 校验组件是否支持移动 - */ - function checkCanMoveComponent(): boolean { - if (designerRules && designerRules.checkCanMoveComponent) { - return designerRules.checkCanMoveComponent(); - } - return true; - } - - /** - * 校验组件是否支持选中父级 - */ - function checkCanSelectParentComponent(): boolean { - return false; - } - - /** - * 校验组件是否支持删除 - */ - function checkCanDeleteComponent() { - if (designerRules && designerRules.checkCanDeleteComponent) { - return designerRules.checkCanDeleteComponent(); - } - return true; - } - - /** - * 校验组件是否支持添加子元素 - */ - function checkCanAddComponent() { - if (designerRules && designerRules.checkCanAddComponent) { - return designerRules.checkCanAddComponent(); - } - return true; - } - - /** - * 判断在可视化区域中是否隐藏容器间距和线条 - */ - function hideNestedPaddingInDesginerView() { - return true; - } - - /** - * 获取组件在表单DOM中所属的Component的实例 - * @param componentInstance 组件实例 - */ - function getBelongedComponentInstance(componentInstance?: Ref): DesignerComponentInstance | null { - if (!componentInstance || !componentInstance.value) { - return null; - } - const parent = ref(componentInstance?.value.parent) as Ref; - const grandParent = getBelongedComponentInstance(parent); - if (grandParent) { - return grandParent; - } - return null; - } - - function getDraggableDesignItemElement(context: DesignerItemContext = designItemContext): Ref | null { - const { componentInstance, designerItemElementRef } = context; - if (!componentInstance || !componentInstance.value) { - return null; - } - if (componentInstance.value.canMove || componentInstance.value.canAdd || componentInstance.value.canDelete) { - return designerItemElementRef; - } - return getDraggableDesignItemElement(context.parent); - } - - /** - * 判断是否可以接收拖拽新增的子级控件 - * @param data 新控件的类型、所属分类 - * @returns boolean - */ - function canAccepts(draggingContext: DraggingResolveContext) { - return !!designerRules && designerRules.canAccepts(draggingContext); - } - - function getDraggingDisplayText() { - return designItemContext?.schema.label || designItemContext?.schema.title || designItemContext?.schema.name; - } - - /** - * 控件可以拖拽到的最外层容器,用于限制控件向外层容器拖拽的范围。不写则不限制 - */ - function getDragScopeElement(): HTMLElement | undefined { - return undefined; - } - - /** - * 移动控件后事件:在可视化设计器中,将现有的控件移动到容器中 - * @param element 移动的源DOM结构 - */ - function onAcceptMovedChildElement(element: DesignerHTMLElement, sourceContainer?: DesignerHTMLElement) { - if (!element || !sourceContainer) { - return; - } - if (designerRules?.onAcceptMovedChildElement) { - designerRules.onAcceptMovedChildElement(element, sourceContainer); - } - } - - function addNewChildComponentSchema(resolveContext: DraggingResolveContext) { - const { componentType } = resolveContext; - const designerHostServer = inject('designer-host-service') as DesignerHostService; - let componentSchema = getSchemaByType(componentType, resolveContext, designerHostServer) as ComponentSchema; - if (designerRules && designerRules.onResolveNewComponentSchema) { - componentSchema = designerRules.onResolveNewComponentSchema(resolveContext, componentSchema); - } - - const typePrefix = componentType.toLowerCase().replace(/-/g, '_'); - if (componentSchema && !componentSchema.id && componentSchema.type === componentType) { - componentSchema.id = `${typePrefix}_${Math.random().toString().slice(2, 6)}`; - } - return componentSchema; - } - - /** - * 移动内部控件后事件:在可视化设计器中,将现有的控件移动到容器中 - * @param element 移动的源DOM结构 - */ - function onChildElementMovedOut(element: HTMLElement) { - - } - - /** 属性面板属性 */ - function getPropConfig(...args) { - if (designerRules && designerRules.getPropsConfig) { - return designerRules.getPropsConfig(...args); - } - return []; - } - function onRemoveComponent() { - - } - /** - * 控件属性变更后事件 - */ - function onPropertyChanged(event: any) { - if (designerRules && designerRules.onPropertyChanged) { - return designerRules.onPropertyChanged(event); - } - } - componentInstance.value = { - canMove: checkCanMoveComponent(), - canSelectParent: checkCanSelectParentComponent(), - canAdd: checkCanAddComponent(), - canDelete: checkCanDeleteComponent(), - canNested: !hideNestedPaddingInDesginerView(), - contents: [], - elementRef, - parent: designItemContext.parent?.componentInstance, - schema: designItemContext.schema, - styles, - canAccepts, - getBelongedComponentInstance, - getDraggableDesignItemElement, - getDraggingDisplayText, - getPropConfig, - getDragScopeElement, - onAcceptMovedChildElement, - onChildElementMovedOut, - addNewChildComponentSchema, - onRemoveComponent, - triggerBelongedComponentToMoveWhenMoved: !!designerRules && designerRules.triggerBelongedComponentToMoveWhenMoved || ref(false), - triggerBelongedComponentToDeleteWhenDeleted: !!designerRules && designerRules.triggerBelongedComponentToDeleteWhenDeleted || ref(false), - onPropertyChanged - } as DesignerComponentInstance; - - return componentInstance as Ref; - -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-dragula.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-dragula.ts deleted file mode 100644 index 1b8b01052bc27ae976cbb2ac0d1ab8ed2e1b9c21..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/function/use-dragula.ts +++ /dev/null @@ -1,358 +0,0 @@ -import dragula from '@farris/designer-dragula'; -import { DesignerHostService, DesignerHTMLElement, DraggingResolveContext, UseDragula } from '../types'; -import { findIndex } from 'lodash-es'; -import { ref } from 'vue'; -import { canvasChanged } from '../designer-canvas-changed'; -import { ComponentSchema } from '../../types'; -import { dragResolveService } from './drag-resolve'; - -export function useDragula(designerHostService: DesignerHostService): UseDragula { - - let dragulaInstance: any; - - /** - * 判断是否可以接收拖拽的新控件 - * @param el 拖拽的新控件元素 - * @param target 目标位置 - * @returns boolean - */ - function checkCanAcceptDrops( - element: DesignerHTMLElement, - target: DesignerHTMLElement, - sourceContainer: DesignerHTMLElement - ): boolean { - if (!!element.contains(target) || target.classList.contains('no-drop')) { - return false; - } - const result = true; - if (element.componentInstance && element.componentInstance.value.getDragScopeElement) { - const dragScopEle = element.componentInstance.value.getDragScopeElement(); - if (dragScopEle) { - if (!dragScopEle.contains(target)) { - return false; - } - } - } - if (target.componentInstance && target.componentInstance.value.canAccepts) { - const dragResolveUtil = dragResolveService(designerHostService); - const draggingContext = dragResolveUtil.getComponentResolveContext(element, sourceContainer, target); - - return target.componentInstance.value.canAccepts(draggingContext); - } - return result; - } - - /** - * 判断DOM 是否在可视区域内 - * @param el 元素 - * @param containerEl 容器 - */ - function isElementInViewport(element: HTMLElement, sourceContainer: HTMLElement) { - const container = sourceContainer.getBoundingClientRect(); - const box = element.getBoundingClientRect(); - const top = box.top >= container.top; - const bottom = box.top < container.bottom; - return (top && bottom); - } - - /** - * 拖拽过程若中产生了页面的上下滚动,需要将已选控件的操作按钮上下移动相等的距离。 - * @param formElement 滚动父容器 - * @param scrollDirection 滚动方向 - * @param scrollHeight 滚动距离 - */ - function scrollInDragging(formElement: HTMLElement, scrollHeight: number) { - const selectedDom = formElement.querySelector('.dgComponentSelected') as HTMLElement; - if (!selectedDom || scrollHeight === 0) { - return; - } - if (isElementInViewport(selectedDom, formElement)) { - const toolbar = selectedDom.querySelector('.component-btn-group'); - if (toolbar) { - const divPanel = toolbar.querySelector('div'); - if (divPanel && divPanel.style.top) { - const top = Number.parseFloat(divPanel.style.top); - divPanel.style.top = (top - scrollHeight) + 'px'; - } - } - } - } - - /** - * 将新控件json添加到新容器schema json中 - * @param target 目标容器元素 - * @param sourceControlSchema 新控件的JSON schema结构 - * @param sibling 目标位置的下一个同级元素 - */ - function addNewControlToTarget( - target: DesignerHTMLElement, - sourceControlSchema: ComponentSchema | null, - sibling: DesignerHTMLElement - ): number { - let index = -1; - if (!sourceControlSchema) { - return -1; - } - if (target.componentInstance.value.contents) { - if (sibling && sibling.componentInstance) { - if (!sibling.getAttribute('data-noattach')) { - // 定位目标位置 - const siblingComponentSchema = sibling.componentInstance.value.schema; - let locatePredicate: any = { id: siblingComponentSchema.id }; - if (siblingComponentSchema.type === 'component') { - locatePredicate = { component: siblingComponentSchema.id }; - } - - index = findIndex(target.componentInstance.value.contents, locatePredicate); - index = (index === -1) ? 0 : index; - } else { - index = Number(sibling.getAttribute('data-position')); - } - if (index !== -1) { - target.componentInstance.value.contents.splice(index, 0, sourceControlSchema); - } - } else { - target.componentInstance.value.contents.push(sourceControlSchema); - } - } - return index; - } - - /** - * 从控件工具箱中拖拽新建控件 - * @param element 拖拽的元素 - * @param target 目标容器元素 - * @param source 原容器元素 - * @param sibling 目标位置的下一个同级元素 - */ - function createControlFromOutside( - element: DesignerHTMLElement, - target: DesignerHTMLElement, - source: DesignerHTMLElement, - sibling: DesignerHTMLElement - ) { - const dragResolveUtil = dragResolveService(designerHostService); - dragResolveUtil.resolveComponentCreationContextByDrop(element, source, target).then(componentResolveContext => { - if (!componentResolveContext) { - return; - } - const sourceControlSchema = componentResolveContext.componentSchema; - if (sourceControlSchema) { - addNewControlToTarget(target, sourceControlSchema, sibling); - } - }); - // 移除拷贝生成的源DOM - if (target.contains(element)) { - target.removeChild(element); - } - } - /** - * 在现有的表单中拖拽移动控件位置 - * @param element 拖拽的元素 - * @param target 目标容器元素 - * @param source 源容器元素 - * @param sibling 目标位置的下一个同级元素 - */ - function dragBetweenCurrentForm( - element: DesignerHTMLElement, - target: DesignerHTMLElement, - source: DesignerHTMLElement, - sibling: DesignerHTMLElement - ) { - let sourceControlSchema; - let index = -1; - // Form、DataGrid等控件在拖拽时,需要连同所属Component一起拖拽。 - if (element.componentInstance && element.componentInstance.value.triggerBelongedComponentToMoveWhenMoved) { - const cmpInstance = element.componentInstance.value.getBelongedComponentInstance(element.componentInstance); - if (cmpInstance) { - // 将拖拽元素替换为所属Component - element = ref(cmpInstance.elementRef).value.parentElement as DesignerHTMLElement; - // 将源容器元素替换为所属Component的父级元素 - source = element.parentElement as DesignerHTMLElement; - } - - } - const elementComponentSchema = element.componentInstance && element.componentInstance.value.schema; - - let locatePredicate: any = { id: elementComponentSchema && elementComponentSchema.id }; - if (elementComponentSchema.type === 'component') { - locatePredicate = { component: elementComponentSchema && elementComponentSchema.id }; - } - - index = findIndex(source.componentInstance.value.contents, locatePredicate); - - // 从源容器schema json中移除 - if (index !== -1 && source.componentInstance.value.contents) { - sourceControlSchema = source.componentInstance.value.contents.splice(index, 1); - sourceControlSchema = sourceControlSchema[0]; - } - - addNewControlToTarget(target, sourceControlSchema as ComponentSchema, sibling); - - // 源容器的控件被移除掉 - if (source.componentInstance && source.componentInstance.value.onChildElementMovedOut) { - source.componentInstance.value.onChildElementMovedOut(element); - } - - // 目标容器接收新控件 - if (target.componentInstance && target.componentInstance.value.onAcceptMovedChildElement) { - target.componentInstance.value.onAcceptMovedChildElement(element, source); - } - } - - /** - * 拖拽结束 - * @param element 拖拽的元素 - * @param target 目标容器元素 - * @param source 原容器元素 - * @param sibling 目标位置的下一个同级元素 - */ - function onDrop(element: DesignerHTMLElement, target: DesignerHTMLElement, source: DesignerHTMLElement, sibling: DesignerHTMLElement) { - if (!target) { - return; - } - if (element.contains(target)) { - return; - } - const sourceType = element.getAttribute('data-sourceType'); - - switch (sourceType) { - case 'control': case 'field': case 'entity': { - createControlFromOutside(element, target, source, sibling); - break; - } - default: { - if (source.componentInstance.value.contents) { - dragBetweenCurrentForm(element, target, source, sibling); - } else { - // 移除拷贝生成的源DOM - if (target.contains(element)) { - target.removeChild(element); - } - } - } - } - canvasChanged.value++; - - } - - function initializeDragula(containerElement: DesignerHTMLElement) { - if (dragulaInstance) { - dragulaInstance.destroy(); - } - - if (!dragula) { - return; - } - - dragulaInstance = dragula([], { - // 镜像容器 - mirrorContainer: containerElement, - direction: 'mixed', - revertOnSpill: true, - // 判断是否可移动 - moves(element: DesignerHTMLElement, container: DesignerHTMLElement, handle: DesignerHTMLElement): boolean { - let moves = true; - - // 包含no-drag样式的元素不允许拖动 - if (element.classList.contains('no-drag')) { - moves = false; - } - // 为防止误操作,可视化区域的控件只能通过移动图标来拖拽 - if (element.componentInstance) { - moves = !!handle.getAttribute('data-dragging-icon'); - } - return moves; - }, - // 判断是否可拷贝 - copy(element: HTMLElement): boolean { - // 工具箱里的div需要配置drag-copy - return element.classList.contains('drag-copy'); - }, - // 获取镜像元素的文本内容 - getMirrorText(element: DesignerHTMLElement): string { - if (element.componentInstance && element.componentInstance.value.getDraggingDisplayText) { - return element.componentInstance.value.getDraggingDisplayText(); - } - return element.innerText || '控件'; - }, - // 判断目标区域是否可接收拖拽的控件 - accepts(element: DesignerHTMLElement, target: DesignerHTMLElement, source: DesignerHTMLElement): boolean { - const canAccept = checkCanAcceptDrops(element, target, source); - const guMirrotElement = containerElement.lastElementChild as Element; - if (canAccept) { - guMirrotElement.className = guMirrotElement.className.replace('undroppable', ''); - } else if (!guMirrotElement.className.includes('undroppable')) { - guMirrotElement.className += ' undroppable'; - } - return canAccept; - } - }).on('over', (el: DesignerHTMLElement, container: DesignerHTMLElement) => { - container.className += ' drag-over'; - }).on('out', (el: DesignerHTMLElement, container: DesignerHTMLElement) => { - container.className = container.className.replace('drag-over', '').replace(' ', ''); - }).on('drop', ( - element: DesignerHTMLElement, target: DesignerHTMLElement, source: DesignerHTMLElement, sibling: DesignerHTMLElement - ) => { - onDrop(element, target, source, sibling); - }).on('dragend', (element: HTMLElement, scrollHeight: number) => { - scrollInDragging(element, scrollHeight); - }); - } - - /** - * 子组件JSON结构和当前组件的实例添加到DOM中并注册拖拽容器。节点class= 'builder-components...' - * @param element dom元素 - * @param childrenComponents 容器内的子组件实例集合 - * @param childrenContents 子组件JSON schema集合 - * @param component 容器组件实例 - * @returns 容器类组件的子组件集合 - */ - function attachComponents(element: HTMLElement, component: Record) { - - // don't attach if no element was found or component doesn't participate in drag'n'drop. - if (!element) { - return; - } - if (component.noDragDrop) { - return element; - } - // 获取容器中的子组件集合节点 - const containerElement: HTMLElement = element.querySelector(`[data-dragref='${component.id}-container']`) || element; - - // 将容器添加到拖拽列表中,dragula控件会监听容器中元素的拖动事件 - if (dragulaInstance && containerElement) { - // containerElement 为页面中的容器节点的builder-components层级 - dragulaInstance.containers.push(containerElement); - } - } - - /** - * 将工具箱各容器添加到dragula的拖拽列表中 - */ - function attachToolbox() { - if (!dragulaInstance) { - return; - } - const controlPanels = document.getElementsByClassName('controlCategory'); - if (!controlPanels) { - return; - } - - dragulaInstance.containers = dragulaInstance.containers.filter( - (element: HTMLElement) => !element.className.includes('controlCategory') - ); - - Array.from(controlPanels).forEach((panelElement) => { - dragulaInstance.containers.push(panelElement); - }); - - } - - function getDragulaInstance() { - return dragulaInstance; - } - - return { attachComponents, initializeDragula,getDragulaInstance }; - -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-canvas.props.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-canvas.props.ts deleted file mode 100644 index e07d95a7ac998de22c81ccbd545eb0443f2ada7e..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-canvas.props.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ExtractPropTypes } from 'vue'; - -export const designerCanvasProps = { - /** - * 组件值 - */ - modelValue: { type: Object, default: {} }, - componentId: { type: String, default: '' }, - components: { type: Array, default: null }, - -} as Record; - -export type DesignerCanvasPropsType = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-inner-item.props.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-inner-item.props.ts deleted file mode 100644 index 9c449ec8854f48ad5dc61f0a6dbfcb9ec2a0dfd2..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-inner-item.props.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ExtractPropTypes } from "vue"; - -export const designerInnerItemProps = { - id: { type: String, default: '' }, - componentId: { type: String, default: '' }, - canAdd: { type: Boolean, default: false }, - canDelete: { type: Boolean, default: false }, - canMove: { type: Boolean, default: false }, - contentKey: { type: String, default: 'contents' }, - childLabel: { type: String, default: '' }, - childType: { type: String, default: '' }, - /** - * 组件值 - */ - modelValue: { type: Object }, -} as Record; - -export type DesignerInnerItemPropsType = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-item.props.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-item.props.ts deleted file mode 100644 index a674600f00b8102af205824a112d4e6dc8db5238..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-item.props.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ExtractPropTypes } from "vue"; - -export const designerItemProps = { - id: { type: String, default: '' }, - componentId: { type: String, default: '' }, - type: { type: String, default: '' }, - canDelete: { type: Boolean, default: true }, - canMove: { type: Boolean, default: true }, - canSelectParent: { type: Boolean, default: true }, - customButtons: { type: Array, default: [] }, - customClass: { type: String, default: '' }, - customStyle: { type: String, default: '' }, - /** - * 组件值 - */ - modelValue: { type: Object }, - ignore: { type: Boolean, default: false } -} as Record; - -export type DesignerItemPropsType = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-placeholder.props.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-placeholder.props.ts deleted file mode 100644 index 3bde9b168af28b319722ce0dc732bcf312a9455b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/props/designer-placeholder.props.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ExtractPropTypes } from "vue"; - -export const designerPlaceholderProps = { - id: { type: String } -}; - -export type DesignerPlaceholderPropsType = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/drag-drop-rules.schema.json b/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/drag-drop-rules.schema.json deleted file mode 100644 index f524134d361ffe176334dc26ae2eb8e6a665c0cf..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/drag-drop-rules.schema.json +++ /dev/null @@ -1,646 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://farris-design.gitee.io/dragging-rules.schema.json", - "title": "Dragging Rules", - "description": "The rules of designer canvas", - "type": "object", - "properties": { - "f-page": { - "description": "The root class of page designed by farris.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-page-header": { - "description": "The class of page header designed by farris.", - "type": "string" - }, - "f-page-main": { - "description": "The class of page body designed by farris.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-struct-like-card": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-struct-form": { - "description": "The class of form component which has a hierarchical structure of component -> section -> respnse-form.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-section-form": { - "description": "The class of section which has wrapped a reponse-form component.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-form-layout": { - "description": "The class of reponse form", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": true - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": false - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": false - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-struct-wrapper": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-section-tabs": { - "description": "The class of section which has wrapped sub-grid tabs.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-tabs-in-card": { - "description": "The class of tabs which contains sub-grid.", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-struct-data-grid-in-card": { - "description": "The class of sub-grid component", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-grid-is-sub": { - "description": "The class of sub-grid", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": true - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": false - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": false - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-section-in-main": { - "description": "The class of section which has wrapped a reponse-form component.", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": true - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": false - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": false - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": true - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "object", - "const": { - "allOf": [ - { - "sibling": 0, - "parent": { - "f-page-main": true - } - } - ] - } - } - } - } - } - }, - "f-struct-data-grid": { - "description": "", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "object", - "const": true - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-page-main-content": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-page-content-nav": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-struct-data-grid-in-nav": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-page-content-nav-extend": { - "description": "", - "type": "object" - }, - "f-section-in-nav": { - "description": "", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": false - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": true - }, - "fixed": { - "type": "boolean", - "const": false - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - } - } - }, - "f-page-content-main": { - "description": "", - "type": "object", - "properties": {} - } - } - } - } - }, - "f-page-content": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-page-content-nav": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-list-nav": { - "description": "", - "type": "object" - }, - "f-list-nav-left": { - "description": "", - "type": "object" - }, - "f-struct-data-grid-in-nav": { - "description": "", - "type": "object", - "properties": { - "contents": { - "type": "object", - "properties": { - "f-section-form": { - "description": "", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-section-grid": { - "description": "", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - }, - "f-page-content-main": { - "description": "", - "type": "object", - "properties": { - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": false - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "object", - "const": { - "anyOf": [ - { - "children": 0 - }, - { - "children": { - "length": { - "not": 1 - }, - "f-struct-like-card": true - } - }, - { - "children": { - "scroll-spy": false, - "f-page-content": false, - "f-struct-like-card": false - } - } - ] - } - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-page-footer": { - "description": "The class of page footer designed by farris.", - "type": "string" - } - } - }, - "rules": { - "type": "object", - "properties": { - "canAccept": { - "type": "boolean", - "const": false - }, - "fixed": { - "type": "boolean", - "const": true - }, - "hidePadding": { - "type": "boolean", - "const": true - } - } - } - } - }, - "f-page-is-managelist": { - "description": "The root class of mangement list page.", - "type": "string" - }, - "f-page-card": { - "description": "", - "type": "object" - }, - "f-page-is-mainsubcard": { - "description": "", - "type": "object" - } - } -} \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-drag-drop-rules.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-drag-drop-rules.ts deleted file mode 100644 index 7af83dea3ad9450ebf4e74b64c2708c7d6335e03..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-drag-drop-rules.ts +++ /dev/null @@ -1,196 +0,0 @@ -import dragAndDropRules from './drag-drop-rules.schema.json'; - -interface DragDropRule { - canAccept: boolean; - fixed: boolean; - hidePadding: boolean; - [index: string]: boolean; -} - -interface Expression { - target: string; - operator: string; - param: any; - value: any; -} - -interface DragAndDropContext { - children: any; - parent: any; - slibing: any; - [index: string]: any; -} - -export type CalculateFunction = (target: string, param: any, value: any, context: DragAndDropContext) => boolean; - -export type RuleFunction = (context: DragAndDropContext) => DragDropRule; - -export interface UseDragAndDropRule { - getRuleValue: (componentToken: string, context: DragAndDropContext) => DragDropRule; -} - -const ruleMap = new Map(); - -export function useDragAndDropRules(): UseDragAndDropRule { - - function judgingElementCount(target: string, param: any, value: any, context: DragAndDropContext) { - if (typeof value === 'number') { - return context[target]?.length === value; - } - if (typeof value === 'object') { - const compare = Object.keys(value)[0]; - const targetValue = value[compare]; - if (compare === 'not') { - return Number(context[target].length) !== Number(targetValue); - } - if (compare === 'moreThan') { - return Number(context[target].length) >= Number(targetValue); - } - if (compare === 'lessThan') { - return Number(context[target].length) <= Number(targetValue); - } - } - return false; - } - - function hasChildren(target: string, param: any, value: any, context: DragAndDropContext) { - if (typeof value === 'boolean') { - return context.childrenClassList.includes(param) === Boolean(value); - } - return false; - } - - function hasParent(target: string, param: any, value: any, context: DragAndDropContext) { - if (typeof value === 'boolean') { - return context.parentClassList.includes(param) === Boolean(value); - } - return false; - } - - function hasSibling(target: string, param: any, value: any, context: DragAndDropContext) { - if (typeof value === 'boolean') { - return context.parentClassList.includes(param) === Boolean(value); - } - return false; - } - - const expressionCalculateFunctions = new Map([ - ['length', judgingElementCount], - ['hasChildren', hasChildren], - ['hasSibling', hasSibling], - ['hasParent', hasParent] - ]); - - function parseExpression(token: string, expression: Record): Expression[] { - const target = token; - if (typeof expression === 'number') { - return [{ target, operator: 'length', param: null, value: Number(expression) }]; - } - if (typeof expression === 'object') { - return Object.keys(expression).map((key: string) => { - if (key === 'length') { - return { target, operator: 'length', param: null, value: expression[key] }; - } - const param = key; - const value = expression[key]; - const operator = token === 'children' ? 'hasChildren' : (token === 'parent' ? 'hasParent' : 'hasSibling'); - return { target, operator, param, value }; - }); - } - return []; - } - - function calculateExpression(expression: Expression, context: DragAndDropContext) { - if (expressionCalculateFunctions.has(expression.operator)) { - const calculateFunction = expressionCalculateFunctions.get(expression.operator); - return calculateFunction && calculateFunction(expression.target, expression.param, expression.value, context) || false; - } - return false; - } - - function calculate(expression: Record, context: DragAndDropContext): boolean { - const expressionTokens = Object.keys(expression); - - const parsedExpression = expressionTokens.reduce((expressions: Expression[], token: string) => { - const result = parseExpression(token, expression[token]); - expressions.push(...result); - return expressions; - }, []); - const result = parsedExpression.reduce((parsingResult: boolean, expression: Expression) => { - return parsingResult && calculateExpression(expression, context); - }, true); - - return result; - } - - function parseValueSchema(valueSchema: Record, context: DragAndDropContext): boolean { - const schemaKeys = Object.keys(valueSchema); - const allOf = schemaKeys.includes('allOf'); - const anyOf = schemaKeys.includes('anyOf'); - const hasLogicalOperatorsInSchemaKey = allOf || anyOf; - const logicalOperator = hasLogicalOperatorsInSchemaKey ? (allOf ? 'allOf' : 'anyOf') : 'allOf'; - const expressions = (hasLogicalOperatorsInSchemaKey ? valueSchema[logicalOperator] : [valueSchema]) as Record[]; - const expressionValues = expressions.map((expression: Record) => calculate(expression, context)); - const result = allOf ? !expressionValues.includes(false) : expressionValues.includes(true); - return result; - } - - function resolveRuleValue(ruleValueSchema: Record, context: DragAndDropContext): boolean { - const valueSchema = ruleValueSchema.const; - if (!valueSchema) { - return false; - } - if (typeof valueSchema === 'boolean') { - return valueSchema; - } - if (typeof valueSchema === 'object') { - return parseValueSchema(valueSchema, context); - } - return false; - } - - function generateRuleFunction(rulesSchema: Record): RuleFunction { - return (context: DragAndDropContext) => { - const rulesInstance = { canAccept: true, fixed: false, hidePadding: false } as DragDropRule; - rulesSchema && rulesSchema.properties && - Object.keys(rulesSchema.properties).reduce((compoentRulesMap: DragDropRule, ruleItemKey: string) => { - const ruleItemSchema = rulesSchema.properties[ruleItemKey]; - compoentRulesMap[ruleItemKey] = resolveRuleValue(ruleItemSchema, context); - return compoentRulesMap; - }, rulesInstance); - return rulesInstance; - }; - } - - function resolveComponentRule(componentToken: string, componentSchema: Record, ruleMap: Map) { - if (componentSchema.type === 'object' && componentSchema.properties) { - const { rules: rulesSchema, contents } = componentSchema.properties; - ruleMap.set(componentToken, generateRuleFunction(rulesSchema)); - if (contents) { - Object.keys(contents.properties).forEach((subComponentToken: string) => - resolveComponentRule(subComponentToken, contents.properties[subComponentToken], ruleMap) - ); - } - } - } - - function resolveRuleSchema() { - const { properties: componentsSchema } = dragAndDropRules as Record; - Object.keys(componentsSchema).forEach((componentToken: string) => { - resolveComponentRule(componentToken, componentsSchema[componentToken], ruleMap); - }); - } - - function getRuleValue(componentToken: string, context: DragAndDropContext): DragDropRule { - const rulesInstance = { canAccept: true, fixed: false, hidePadding: true } as DragDropRule; - if (ruleMap.has(componentToken)) { - const ruleFuntions = ruleMap.get(componentToken) as RuleFunction; - return ruleFuntions(context); - } - return rulesInstance; - } - - resolveRuleSchema(); - - return { getRuleValue }; -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-dragula-common-rule.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-dragula-common-rule.ts deleted file mode 100644 index 7f6131d69135a84bbe457b8f63572c3598340a36..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-dragula-common-rule.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { DgControl } from "../dg-control"; -import { DesignerHostService, DraggingResolveContext } from "../types"; - -export function useDragulaCommonRule() { - - /** - * 容器类控件的基础控制规则 - */ - function basalDragulaRuleForContainer(draggingContext: DraggingResolveContext, designerHostService?: DesignerHostService): boolean { - if (!draggingContext) { - return false; - } - - /** 目标容器的组件实例 */ - const targetCmpInstance = draggingContext.targetContainer?.componentInstance && - draggingContext.targetContainer.componentInstance.value; - - if (!targetCmpInstance) { - return false; - } - const targetContainerType = targetCmpInstance.schema.type; - const belongedComponent = designerHostService?.formSchemaUtils.getComponentById(targetCmpInstance.belongedComponentId); - - // 限制输入类控件的可接收容器 - if (draggingContext.componentCategory === 'input' || draggingContext.componentType === 'form-group') { - if (![DgControl['response-layout-item'].type, DgControl['response-form'].type].includes(targetContainerType)) { - return false; - } - } - - // 限制标签页区域、分组面板的可接收容器 - if (draggingContext.componentType === DgControl.tabs.type || draggingContext.componentType === DgControl.section.type) { - const belongedComponentType = belongedComponent?.componentType; - if (belongedComponentType !== 'frame') { - return false; - } - if (![DgControl['content-container'].type, DgControl['splitter-pane'].type, DgControl['response-layout-item'].type].includes(targetContainerType)) { - return false; - } - } - // 限制筛选方案 - if (draggingContext.componentType === DgControl['query-solution'].type) { - return false; - } - return true; - } - - return { - basalDragulaRuleForContainer - }; -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-template-rule.ts b/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-template-rule.ts deleted file mode 100644 index 93c1c87835d2f8ac2f0d07ad33aa969e4d5f06b7..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/composition/rule/use-template-rule.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { DesignerItemContext } from "../../types"; -import { DesignerHostService } from "../types"; - -export interface DragDropRule { - canAccept: boolean; - canMove: boolean; - canDelete: boolean; - [index: string]: boolean; -} - -/** - * 解析模板拖拽控制规则 - */ -export class UseTemplateDragAndDropRules { - public getTemplateRule(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): DragDropRule { - - const formSchemaUtils = designerHostService?.formSchemaUtils; - const dragTemplateRules = formSchemaUtils?.getFormTemplateRule(); - const dragDropRule = { canAccept: true, canDelete: true, canMove: true }; - if (!dragTemplateRules) { - return dragDropRule; - } - const componentContext = this.getComponentContext(designItemContext); - const { componentClassList } = componentContext; - - componentClassList.forEach(componentClass => { - if (!componentClass || !dragTemplateRules[componentClass]) { - return; - } - - const { canMove: moveRule, canDelete: deleteRule, canAccept: acceptRule } = dragTemplateRules[componentClass]; - dragDropRule.canMove = dragDropRule.canMove && this.resolveRuleValue(moveRule, componentContext); - dragDropRule.canDelete = dragDropRule.canDelete && this.resolveRuleValue(deleteRule, componentContext); - dragDropRule.canAccept = dragDropRule.canAccept && this.resolveRuleValue(acceptRule, componentContext); - }); - - return dragDropRule; - } - - private resolveRuleValue(ruleSchema: any, componentContext: any): boolean { - - if (typeof ruleSchema === 'boolean') { - return ruleSchema; - } else { - return this.parseRuleValueSchema(ruleSchema, componentContext); - } - } - - private parseRuleValueSchema(ruleSchema: any, componentContext: any) { - const invalidContext = ruleSchema.invalidContext || []; - let isMatched = true; - for (const ruleContext of invalidContext) { - - // 判断子级节点是否匹配 - if (ruleContext.firstLevelChild) { - if (ruleContext.firstLevelChild.class) { - const { firstLevelChildClassList } = componentContext; - if (firstLevelChildClassList && !firstLevelChildClassList.includes(ruleContext.firstLevelChild.class)) { - isMatched = false; - continue; - } - } - if (ruleContext.firstLevelChild.type) { - const { firstLevelChildSchema } = componentContext; - if (!firstLevelChildSchema || firstLevelChildSchema.type !== ruleContext.firstLevelChild.type) { - isMatched = false; - continue; - } - } - - } - // 判断孙子节点是否匹配 - if (ruleContext.secondLevelChild) { - if (ruleContext.secondLevelChild.class) { - const { secondLevelChildClassList } = componentContext; - if (secondLevelChildClassList && !secondLevelChildClassList.includes(ruleContext.secondLevelChild.class)) { - isMatched = false; - continue; - } - } - if (ruleContext.secondLevelChild.type) { - const { secondLevelChildSchema } = componentContext; - if (!secondLevelChildSchema || secondLevelChildSchema.type !== ruleContext.secondLevelChild.type) { - isMatched = false; - continue; - } - } - - } - // 判断父级节点是否匹配 - if (ruleContext.parent) { - if (ruleContext.parent.class) { - const { parentClassList } = componentContext; - if (parentClassList && !parentClassList.includes(ruleContext.parent.class)) { - isMatched = false; - continue; - } - } - if (ruleContext.parent.type) { - const { parentSchema } = componentContext; - if (parentSchema && parentSchema.type !== ruleContext.parent.type) { - isMatched = false; - continue; - } - } - } - isMatched = true; - break; - } - return !isMatched; - - } - public getComponentContext(designItemContext: DesignerItemContext) { - const component = designItemContext.schema; - - // 控件本身 - const componentClass = component.appearance && component.appearance.class || ''; - const componentClassList = componentClass.split(' ') || []; - - // 控件子级节点 - const childContents = component.contents || []; - const firstLevelChildSchema = childContents.length ? childContents[0] : null; - const firstLevelChildClass = firstLevelChildSchema && firstLevelChildSchema.appearance ? firstLevelChildSchema.appearance.class : ''; - const firstLevelChildClassList = firstLevelChildClass ? firstLevelChildClass.split(' ') : []; - - // 控件孙子级节点 - const secondLevelChildSchema = firstLevelChildSchema?.contents?.length ? firstLevelChildSchema?.contents[0] : null; - const secondLevelChildClass = secondLevelChildSchema && secondLevelChildSchema.appearance ? secondLevelChildSchema.appearance.class : ''; - const secondLevelChildClassList = secondLevelChildClass ? secondLevelChildClass.split(' ') : []; - - // 控件父级节点 - const parentSchema = component.type === 'component' ? designItemContext.parent?.parent?.schema : designItemContext.parent?.schema; - const parentClass = parentSchema && parentSchema.appearance && parentSchema.appearance.class || ''; - const parentClassList = parentClass ? parentClass.split(' ') : []; - - return { - componentClass, - componentClassList, - childContents, - firstLevelChildSchema, - firstLevelChildClass, - firstLevelChildClassList, - secondLevelChildSchema, - secondLevelChildClass, - secondLevelChildClassList, - parentSchema, - parentClass, - parentClassList - }; - } -} diff --git a/packages/mobile-ui-vue/components/designer-canvas/src/designer-canvas.component.tsx b/packages/mobile-ui-vue/components/designer-canvas/src/designer-canvas.component.tsx deleted file mode 100644 index 841bb50d40135d43cc3f57444b00e860c5cee959..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-canvas/src/designer-canvas.component.tsx +++ /dev/null @@ -1,143 +0,0 @@ - -import { computed, defineComponent, inject, onMounted, onUnmounted, provide, ref, watch } from 'vue'; -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext } from './types'; -import { canvasChanged, setPositionOfButtonGroup } from './composition/designer-canvas-changed'; -import { designerCanvasProps, DesignerCanvasPropsType } from './composition/props/designer-canvas.props'; -import { useDragula } from './composition/function/use-dragula'; -import { DesignerHostService, UseDragula } from './composition/types'; -import FDesignerItem from './components/designer-item.component'; -import './composition/class/designer-canvas.css'; -import './composition/class/control.css'; -import { loadDesignerRegister } from './components/maps'; -import { FM_MODAL_SERVICE_TOKEN } from '../../modal'; -import { FM_UI_PROVIDER_SERVICE_TOKEN } from '@/components/common'; - -export default defineComponent({ - name: 'FDesignerCanvas', - props: designerCanvasProps, - emits: ['init', 'selectionChange', 'canvasChanged'], - setup(props: DesignerCanvasPropsType, context) { - const schema = ref(); - const componentSchema = ref(); - const designerCanvasElementRef = ref(); - const designerCanvasContainerElementRef = ref(); - const designerItemElementRef = ref(); - const componentInstance = ref(); - const componentId = ref(props.componentId); - let resizeObserver: ResizeObserver | null; - let resizeObserverTimer; - - const designerHostService = { - eventsEditorUtils: inject('eventsEditorUtils'), - formSchemaUtils: inject('useFormSchema'), - formMetadataConverter: inject('formMetadataConverter'), - designViewModelUtils: inject('designViewModelUtils'), - controlCreatorUtils: inject('controlCreatorUtils'), - metadataService: inject('Meatdata_Http_Service_Token'), - schemaService: inject('schemaService'), - useFormCommand: inject('useFormCommand'), - modalService: inject(FM_MODAL_SERVICE_TOKEN), - formStateMachineUtils: inject('useFormStateMachine'), - uiProviderService: inject(FM_UI_PROVIDER_SERVICE_TOKEN), - - }; - provide('designer-host-service', designerHostService); - - const useDragulaComposition = useDragula(designerHostService); - loadDesignerRegister(); - - provide('canvas-dragula', useDragulaComposition); - provide('design-item-context', { - designerItemElementRef, - componentInstance, - schema: componentSchema.value, - parent: undefined - }); - - const designerCanvasClass = computed(() => { - const classObject = { - 'd-flex': true, - 'flex-fill': true, - 'flex-column': true - } as Record; - return classObject; - }); - - /** - * 用于在设计器里 - * @param designerItem - */ - function updateDesignerItem(item: any, compId: string) { - schema.value = item; - componentId.value = compId; - } - - watch(canvasChanged, () => { - setPositionOfButtonGroup(designerCanvasElementRef.value); - - context.emit('canvasChanged'); - }, { flush: 'post' }); - - /** - * 监听画布尺寸变化,重新计算操作图标位置 - */ - function registerResizeListenner() { - resizeObserver = new ResizeObserver(() => { - if (resizeObserverTimer) { - clearTimeout(resizeObserverTimer); - } - - resizeObserverTimer = setTimeout(() => { - setPositionOfButtonGroup(designerCanvasElementRef.value); - }); - }); - resizeObserver.observe(designerCanvasElementRef.value); - } - - function onSelectionChange(schemaType: string, schemaValue: ComponentSchema, cmpId: string, componentInst: DesignerComponentInstance) { - context.emit('selectionChange', schemaType, schemaValue, cmpId, componentInst); - } - - /** - * 监听画布父容器横向滚动条的滚动,重新计算操作图标位置 - */ - function registerEditorPanelScrollEvent() { - designerCanvasContainerElementRef.value.addEventListener('scroll', (e) => { - setPositionOfButtonGroup(designerCanvasElementRef.value); - }); - } - onMounted(() => { - if (designerCanvasElementRef.value) { - useDragulaComposition.initializeDragula(designerCanvasElementRef.value); - } - schema.value = props.modelValue; - context.emit('init', useDragulaComposition); - registerResizeListenner(); - registerEditorPanelScrollEvent(); - }); - - onUnmounted(() => { - if (resizeObserver) { - resizeObserver.unobserve(designerCanvasElementRef.value); - resizeObserver.disconnect(); - resizeObserver = null; - } - }); - - context.expose({ - updateDesignerItem - }); - - return () => { - return ( -
-
-
- {schema.value && } -
-
-
- ); - }; - } -}); diff --git a/packages/mobile-ui-vue/components/designer-toolbox/index.ts b/packages/mobile-ui-vue/components/designer-toolbox/index.ts deleted file mode 100644 index 6616581e20bfa48ed03e175249a0639d29b3445c..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-toolbox/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import FDesignerToolbox from './src/toolbox.component'; - -export * from './src/types'; - -export { FDesignerToolbox }; diff --git a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.component.tsx b/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.component.tsx deleted file mode 100644 index b28fc46df04c79399c94d3ae8767d63ee4d793b8..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.component.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { defineComponent, ref, watch } from 'vue'; -import { ToolboxPropsType, toolboxProps } from './toolbox.props'; -import { ToolboxCategory, ToolboxItem } from './types'; - -import toolboxItems from './toolbox.json'; -import './toolbox.css'; - -export default defineComponent({ - name: 'FDesignerToolbox', - props: toolboxProps, - emits: [], - setup(props: ToolboxPropsType) { - const controlCategoryList = props.toolboxItems ? ref(props.toolboxItems as ToolboxCategory[]) : ref(toolboxItems); - const dragularCompostion = ref(props.dragula); - - function onClickCardHeader(payload: MouseEvent, category: any) { - category.isHide = !category.isHide; - } - - function getCardHeaderIconClass(category: any) { - const classObject = { - 'f-icon': true, - 'f-icon-arrow-60-down': !category.isHide, - 'f-icon-arrow-e': category.isHide - } as Record; - return classObject; - } - - function renderCategoryCardHeader(category: ToolboxCategory) { - return ( -
onClickCardHeader(payload, category)}> -
-
-
-
- -
-
- {category.name} -
-
-
-
-
- ); - } - - function getControlTileClass(toolboxItem: ToolboxItem) { - const classObject = { - 'd-none': toolboxItem.dependentParent || toolboxItem.hideInControlBox, - controlPanel: true, - 'drag-copy': true, - 'no-drag': toolboxItem.disable, - 'updating': toolboxItem.updating - } as Record; - return classObject; - } - - function getToolboxItemClass(toolboxItem: ToolboxItem) { - const classObject = { - farrisControlIcon: true, - 'fd-i-Family': true - } as Record; - const toolboxItemTypicalClassName = `fd_pc-${toolboxItem.icon || toolboxItem.type}`; - classObject[toolboxItemTypicalClassName] = true; - return classObject; - } - - function renderControlTile(toolboxItem: ToolboxItem, category: ToolboxCategory) { - return ( - - ); - } - - function renderCategoryCardBody(category: ToolboxCategory) { - return ( -
- {category.items.map((toolboxItem: any) => renderControlTile(toolboxItem, category))} -
- ); - } - - function renderCategoryCard(category: ToolboxCategory) { - return ( - !category.hideInControlBox && ( -
- {renderCategoryCardHeader(category)} - {renderCategoryCardBody(category)} -
- ) - ); - } - - /** - * 将工具箱各容器添加到dragula的拖拽列表中 - */ - function attachToolboxToDragulaContainer(dragulaInstance: any) { - if (!dragulaInstance) { - return; - } - const controlPanels = document.getElementsByClassName('controlCategory'); - if (!controlPanels) { - return; - } - - dragulaInstance.containers = dragulaInstance.containers.filter( - (element: HTMLElement) => !element.className.includes('controlCategory') - ); - - Array.from(controlPanels).forEach((panelElement) => { - dragulaInstance.containers.push(panelElement); - }); - - } - - watch( - () => props.dragula, - (newValue: any) => { - dragularCompostion.value = newValue; - if (dragularCompostion.value?.getDragulaInstance) { - attachToolboxToDragulaContainer(dragularCompostion.value?.getDragulaInstance()); - } - } - ); - - return () => { - return ( -
-
- {controlCategoryList.value.map((category: any) => { - return renderCategoryCard(category); - })} -
-
- ); - }; - } -}); diff --git a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.css b/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.css deleted file mode 100644 index bdc92e873071b54035094c2b119bce297452f7b2..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.css +++ /dev/null @@ -1,75 +0,0 @@ -.controlBox { - font-size: 13px !important; -} - -.controlBox .farris-panel { - border: none; -} - -.controlBox .farris-panel .card-header { - padding: 10px 0px !important; - background-color: #fcfdff !important; -} - -.controlBox .farris-panel .card-header .col-form-label { - font-size: 13px; - margin-bottom: 0px; - color: #3f4764; - opacity: 0.65; -} - -.controlBox .farris-panel .card-header .col-form-label .f-icon { - font-size: 10.8px; - color: #3f4764; -} - -.controlBox .farris-panel .card-body { - display: flex; - flex-wrap: wrap; - background: #fcfdff !important; -} - -.controlPanel:nth-child(-n + 3) { - margin-top: 0 !important; -} - -.controlPanel .farrisControlIcon { - font-size: 27px; -} - -.controlPanel { - font-size: 13px; - cursor: grab; - display: flex; - background: #fff; - align-items: center; - width: 33.333%; - background-color: #fcfdff; - border: 1px solid #edf1f5; - height: 76px !important; - text-align: center; - margin: -1px 0 0 -1px !important; - color: #6080ad; - /* overflow: hidden; */ - text-overflow: ellipsis; - word-break: keep-all; - -webkit-user-select: none; - user-select: none; -} - -.controlPanel.updating { - color: #707070; -} - -.controlPanel > div { - margin: auto; - overflow: hidden; -} - -.gu-mirror.undroppable.controlPanel { - cursor: no-drop; -} - -.controlBox .farris-panel .card-header .col-form-label .icon-panel .f-icon { - font-size: 16px; -} diff --git a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.props.ts b/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.props.ts deleted file mode 100644 index ddf9559cc143543589252b546eeb68e7e25dd251..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-toolbox/src/toolbox.props.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ExtractPropTypes } from 'vue'; - -export const toolboxProps = { - id: { type: String, default: '' }, - dragula: { type: Object }, - toolboxItems: { type: Object } - -}; - -export type ToolboxPropsType = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/designer-toolbox/src/types.ts b/packages/mobile-ui-vue/components/designer-toolbox/src/types.ts deleted file mode 100644 index 52436075af57540988492f1f7cca86ef4aaeb42b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/designer-toolbox/src/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export interface ToolboxItem { - id: string; - type: string; - name: string; - category: string; - icon?: string; - feature?: any; - dependentParent?: boolean; - hideInControlBox?: boolean; - disable?: boolean; - fieldType?: string; - templateCategory?: string; - updating?: boolean; -} - -export interface ToolboxCategory { - type: string; - name: string; - items: ToolboxItem[]; - hideInControlBox?: boolean; - isHide?: boolean; -}; diff --git a/packages/mobile-ui-vue/components/designer.ts b/packages/mobile-ui-vue/components/designer.ts index 6118ec98be8d097fe4a94da73f69048413d0c67f..13f136e5afd9ce00c68512e25b51c01c9fab14e5 100644 --- a/packages/mobile-ui-vue/components/designer.ts +++ b/packages/mobile-ui-vue/components/designer.ts @@ -1,5 +1,2 @@ -export * from './designer-canvas'; export * from './dynamic-resolver'; -export { FDesignerToolbox } from './designer-toolbox'; -export { default as FModal, FModalService, FM_MODAL_SERVICE_TOKEN } from './modal'; -export { FM_UI_PROVIDER_SERVICE_TOKEN } from './common'; +export * from './register-designer'; diff --git a/packages/mobile-ui-vue/components/dialog/src/dialog.component.tsx b/packages/mobile-ui-vue/components/dialog/src/dialog.component.tsx index cdec3aca7e2414880309df69721d314b84e174ee..d36a898da388ee88391823d179228f78b0b5f0f4 100644 --- a/packages/mobile-ui-vue/components/dialog/src/dialog.component.tsx +++ b/packages/mobile-ui-vue/components/dialog/src/dialog.component.tsx @@ -15,9 +15,9 @@ */ import { SetupContext, computed, defineComponent, ref, toRef, watch } from 'vue'; import { DialogProps, dialogProps } from './dialog.props'; -import { preventDefault, useBem } from '@components/common'; -import Popup from '@components/popup'; -import FmButton from '@components/button'; +import { preventDefault, useBem } from '@farris/mobile-ui-vue/common'; +import Popup from '@farris/mobile-ui-vue/popup'; +import FmButton from '@farris/mobile-ui-vue/button'; const name = 'fm-dialog'; diff --git a/packages/mobile-ui-vue/components/dialog/src/index.tsx b/packages/mobile-ui-vue/components/dialog/src/index.tsx index 599a3b59bca7fc6ea110f3ea9888097786790197..0c884b16e7ae8e1601fc756f0b2317a970c8f2cd 100644 --- a/packages/mobile-ui-vue/components/dialog/src/index.tsx +++ b/packages/mobile-ui-vue/components/dialog/src/index.tsx @@ -14,9 +14,9 @@ * limitations under the License. */ import { App, ref } from 'vue'; -import { mountComponent, usePopupState, isObject, inBrowser } from '@components/common'; +import { mountComponent, usePopupState, isObject, inBrowser } from '@farris/mobile-ui-vue/common'; import FMDialog from './dialog.component'; -import FMInput from '@/components/input-group'; +import FMInput from '@farris/mobile-ui-vue/input-group'; let instance; function defaultOptions() { diff --git a/packages/mobile-ui-vue/components/dynamic-form/index.ts b/packages/mobile-ui-vue/components/dynamic-form/index.ts deleted file mode 100644 index 4eee3a7964841de2fd0304225a0b81de5b707ff2..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/dynamic-form/index.ts +++ /dev/null @@ -1,4 +0,0 @@ - - -export * from './src/types'; -export * from './src/composition/types'; diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/composition/response-form-component-creator.service.ts b/packages/mobile-ui-vue/components/dynamic-form/src/composition/response-form-component-creator.service.ts deleted file mode 100644 index 296ef9ed7657279978d3ede36021c65900dc636e..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/dynamic-form/src/composition/response-form-component-creator.service.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { inject } from 'vue'; -import { DesignerHostService } from '../../../designer-canvas/src/composition/types'; -import { DynamicResolver } from '../../../../components/dynamic-resolver'; -import { ComponentBuildInfo } from '../../../component/src/composition/inner-component-build-info'; -import { ComponentSchema } from '../../../../components/designer-canvas'; -import { FormSchemaEntityFieldTypeName } from '../../../common/entity/entity-schema'; -import { cloneDeep } from 'lodash-es'; - -const ROOT_VIEW_MODEL_ID = 'root-viewmodel'; -/** - * 创建卡片类组件服务类 - */ -export class ResponseFormComponentCreatorService { - - private formSchemaUtils: any; - private controlCreatorUtils: any; - private designViewModelUtils: any; - - constructor( - private resolver: DynamicResolver, - private designerHostService: DesignerHostService - ) { - this.formSchemaUtils = this.designerHostService.formSchemaUtils; - this.controlCreatorUtils = this.designerHostService.controlCreatorUtils; - this.designViewModelUtils = this.designerHostService.designViewModelUtils; - } - - public createComponent(buildInfo: ComponentBuildInfo) { - const componentRefNode = this.createComponentRefNode(buildInfo); - - const componentNode = this.createComponentNode(buildInfo); - - const viewModelNode = this.createViewModeNode(buildInfo); - - const formSchema = this.formSchemaUtils.getFormSchema(); - formSchema.module.viewmodels.push(viewModelNode); - formSchema.module.components.push(componentNode); - - this.designViewModelUtils.assembleDesignViewModel(); - - return componentRefNode; - } - createComponentRefNode(buildInfo: ComponentBuildInfo): any { - const componentRefNode = this.resolver.getSchemaByType('component-ref') as ComponentSchema; - Object.assign(componentRefNode, { - id: `${buildInfo.componentId}-component-ref`, - component: `${buildInfo.componentId}-component`, - }); - return componentRefNode; - } - - createComponentNode(buildInfo: ComponentBuildInfo): any { - const componentNode = this.resolver.getSchemaByType('component') as ComponentSchema; - const contents = this.createFormComponentContents(buildInfo); - Object.assign(componentNode, { - id: `${buildInfo.componentId}-component`, - viewModel: `${buildInfo.componentId}-component-viewmodel`, - componentType: buildInfo.componentType, - appearance: { - class: this.getFormComponentClass() - }, - formColumns: buildInfo.formColumns, - contents - }); - return componentNode; - } - - - /** - * 获取卡片组件层级的class样式 - */ - private getFormComponentClass(): string { - const {templateId} = this.formSchemaUtils.getFormSchema().module; - - // 双列表标签页模板中拖入卡片 - if (templateId === 'double-list-in-tab-template') { - return 'f-struct-wrapper f-utils-fill-flex-column'; - } - return 'f-struct-wrapper'; - - } - - private createFormComponentContents(buildInfo: ComponentBuildInfo) { - // 1、创建section - const section = this.resolver.getSchemaByType('section') as ComponentSchema; - Object.assign(section, { - id: buildInfo.componentId + '-form-section', - appearance: { - class: 'f-section-form f-section-in-mainsubcard' - }, - mainTitle: buildInfo.componentName - }); - - // 2、创建form(默认控件标签独占一列) - const responseForm = this.resolver.getSchemaByType('response-form') as ComponentSchema; - const controls: any[] = []; - Object.assign(responseForm, { - id: buildInfo.componentId + '-form', - appearance: { - class: 'f-form-layout farris-form farris-form-controls-inline' - }, - contents: controls - }); - section.contents = [responseForm]; - - // 3、创建字段 - const { selectedFields } = buildInfo; - selectedFields?.forEach(field => { - const dgVMField = cloneDeep(field); - const resolvedControlClass = this.resolveControlClassByFormColumns(buildInfo); - const fieldMetadata = this.controlCreatorUtils.setFormFieldProperty(dgVMField, '', resolvedControlClass); - - if (fieldMetadata) { - controls.push(fieldMetadata); - } - }); - - // 双列表标签页模板中拖入卡片,要求卡片要填充 - const {templateId} = this.formSchemaUtils.getFormSchema().module; - if (templateId === 'double-list-in-tab-template') { - section.appearance.class = 'f-section-grid f-section-in-main px-0 pt-0'; - section.fill = true; - } - - return [section]; - } - - private resolveControlClassByFormColumns(buildInfo: ComponentBuildInfo) { - let className = ''; - switch (buildInfo.formColumns) { - case 1: { - className = 'col-12'; - break; - } - case 2: { - className = 'col-12 col-md-6 col-xl-6 col-el-6'; - break; - } - case 3: { - className = 'col-12 col-md-6 col-xl-4 col-el-4'; - break; - } - case 4: { - className = 'col-12 col-md-6 col-xl-3 col-el-2'; - break; - } - } - - return className; - } - /** - * 添加viewModel节点 - */ - createViewModeNode(buildInfo: ComponentBuildInfo): any { - const viewModelNode = { - id: `${buildInfo.componentId}-component-viewmodel`, - code: `${buildInfo.componentId}-component-viewmodel`, - name: buildInfo.componentName, - bindTo: buildInfo.bindTo, - parent: ROOT_VIEW_MODEL_ID, - fields: this.assembleViewModelFields(buildInfo), - commands: [], - states: [], - enableValidation: true - }; - return viewModelNode; - } - - /** - * 组装viewModel fields 节点 - */ - private assembleViewModelFields(buildInfo: ComponentBuildInfo) { - - const vmFields: any[] = []; - const { selectedFields } = buildInfo; - selectedFields?.forEach(field => { - let updateOn = 'blur'; - const type = field.type.name; - if (type === FormSchemaEntityFieldTypeName.Enum || type === FormSchemaEntityFieldTypeName.Boolean) { - updateOn = 'change'; - } - - vmFields.push({ - type: 'Form', - id: field.id, - fieldName: field.bindingField, - groupId: null, - groupName: null, - updateOn, - fieldSchema: {} - }); - }); - return vmFields; - } - -} diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-response-form-layout-setting.ts b/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-response-form-layout-setting.ts deleted file mode 100644 index b562cf68f49c677bd3f9c1707286fab91da80af7..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-response-form-layout-setting.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { ResponseFormLayoutContext } from "@/components/response-layout-editor"; -import { FormUnifiedColumnLayout, UseResponseFormLayoutSetting } from "../types"; -import { DgControl } from "@/components/designer-canvas"; -import { useResponseLayoutEditorSetting } from - "../../../response-layout-editor/src/composition/converter/use-response-layout-editor-setting"; - -export function useResponseFormLayoutSetting(formShemaService, componentId: string): UseResponseFormLayoutSetting { - function getFormNode(formSchemaId, formNode = null): any { - if (formNode) { return formNode; } - const componentNode = formShemaService.getComponentById(componentId); - return formShemaService.selectNode(componentNode, item => item.id === formSchemaId); - } - function checkIsInFormComponent(componentId: string): boolean { - const componentNode = formShemaService.getComponentById(componentId); - if (!componentNode || !componentNode.componentType || !componentNode.componentType.startsWith('form')) { - return false; - } - return true; - - } - /** - * 组装每种屏幕下的宽度样式值,例如col-md-6,则uniqueColClassInMD为6 - */ - function assembleUnifiedLayoutContext(propertyData: any): FormUnifiedColumnLayout { - - const formNode = getFormNode(propertyData.id); - const responseLayoutService = useResponseLayoutEditorSetting(formShemaService); - const responseLayoutConfig: ResponseFormLayoutContext[] = []; - responseLayoutService.getResonseFormLayoutConfig(formNode, responseLayoutConfig, 1); - - - // 收集每种屏幕下的列数 - const columnInSMArray = responseLayoutConfig.map(config => config.columnInSM); - const columnInMDArray = responseLayoutConfig.map(config => config.columnInMD); - const columnInLGArray = responseLayoutConfig.map(config => config.columnInLG); - const columnInELArray = responseLayoutConfig.map(config => config.columnInEL); - - /** - * 校验宽度样式值是否一致 - */ - function checkIsUniqueColumn(columnsInScreen: number[]) { - const keySet = new Set(columnsInScreen); - const exclusiveKeys = Array.from(keySet); - - if (exclusiveKeys.length === 1) { - return true; - } - return false; - } - - // 只有每个控件的宽度都一样时,才认为form上有统一宽度,否则认为是自定义的控件宽度,此处传递null - const uniqueColClassInSM = checkIsUniqueColumn(columnInSMArray) ? columnInSMArray[0] : 0; - const uniqueColClassInMD = checkIsUniqueColumn(columnInMDArray) ? columnInMDArray[0] : 0; - const uniqueColClassInLG = checkIsUniqueColumn(columnInLGArray) ? columnInLGArray[0] : 0; - const uniqueColClassInEL = checkIsUniqueColumn(columnInELArray) ? columnInELArray[0] : 0; - - return { - uniqueColClassInSM, - uniqueColClassInMD, - uniqueColClassInLG, - uniqueColClassInEL - }; - } - - /** - * 校验宽度样式值是否一致 - */ - function checkIsUniqueColumn(columnsInScreen: number[]) { - const keySet = new Set(columnsInScreen); - const exclusiveKeys = Array.from(keySet); - - if (exclusiveKeys.length === 1) { - return true; - } - return false; - } - - /** - * 根据统一配置值,修改某一个控件的class样式 - */ - function changeControlClassInByColumn(controlClass: string, unifiedLayout: FormUnifiedColumnLayout) { - let originColClass; - let originColMDClass; - let originColXLClass; - let originColELClass; - let otherClassItems = [] as any; - if (controlClass) { - const controlClassArray = controlClass.split(' '); - const colClassItems = controlClassArray.filter(classItem => classItem.startsWith('col-')); - originColClass = colClassItems.find(item => /^col-([1-9]|10|11|12)$/.test(item)); - originColMDClass = colClassItems.find(item => /^col-md-([1-9]|10|11|12)$/.test(item)); - originColXLClass = colClassItems.find(item => /^col-xl-([1-9]|10|11|12)$/.test(item)); - originColELClass = colClassItems.find(item => /^col-el-([1-9]|10|11|12)$/.test(item)); - otherClassItems = controlClassArray.filter(classItem => !classItem.startsWith('col-')); - } - const colClass = unifiedLayout.uniqueColClassInSM ? 'col-' + unifiedLayout.uniqueColClassInSM : originColClass; - const colMDClass = unifiedLayout.uniqueColClassInMD ? 'col-md-' + unifiedLayout.uniqueColClassInMD : originColMDClass; - const colXLClass = unifiedLayout.uniqueColClassInLG ? 'col-xl-' + unifiedLayout.uniqueColClassInLG : originColXLClass; - const colELClass = unifiedLayout.uniqueColClassInEL ? 'col-el-' + unifiedLayout.uniqueColClassInEL : originColELClass; - - const newClassItems = [colClass, colMDClass, colXLClass, colELClass].concat(otherClassItems); - - return newClassItems.join(' '); - } - - /** - * 根据统一配置值,修改卡片区域内所有控件的class样式 - * @param formNode dom节点 - * @param unifiedLayout 统一配置值 - */ - function changeFormControlsByUnifiedLayoutConfig(formNode: any, unifiedLayout: FormUnifiedColumnLayout, formSchemaId) { - formNode = getFormNode(formSchemaId, formNode); - formNode.contents.forEach(control => { - if (control.type === DgControl['fieldset'].type) { - changeFormControlsByUnifiedLayoutConfig(control, unifiedLayout, control.id); - return; - } - if (!control.appearance) { - control.appearance = {}; - } - const controlClass = control.appearance.class; - control.appearance.class = changeControlClassInByColumn(controlClass, unifiedLayout); - - }); - } - - return { checkIsInFormComponent, assembleUnifiedLayoutContext, changeFormControlsByUnifiedLayoutConfig }; -} diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/types.ts b/packages/mobile-ui-vue/components/dynamic-form/src/types.ts deleted file mode 100644 index e5029eeff4ca03ccb65d39d4ba1832f9333342bd..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/dynamic-form/src/types.ts +++ /dev/null @@ -1,33 +0,0 @@ -export type EditorType = 'button-edit' | 'check-box' | 'check-group' | 'combo-list' | 'combo-lookup' | 'combo-tree' | - 'date-picker' | 'date-range' | 'datetime-picker' | 'datetime-range' | 'events-editor' | 'month-picker' | 'month-range' | - 'year-picker' | 'year-range' | 'input-group' | 'lookup' | 'number-range' | 'number-spinner' | 'radio-group' | 'text' | - 'response-layout-editor-setting' | 'switch' | 'grid-field-editor' | 'field-selector' | 'schema-selector' | 'mapping-editor' | - 'textarea' | 'response-form-layout-setting'|'binding-selector' | 'query-solution-config' | 'solution-preset' | 'item-collection-editor'; - -export interface EditorConfig { - /** 编辑器类型 */ - type: EditorType; - /** 自定义样式 */ - customClass?: string; - /** 禁用 */ - disabled?: boolean; - /** 只读 */ - readonly?: boolean; - /** 必填 */ - required?: boolean; - /** 提示文本 */ - placeholder?: string; - /** 其他属性 */ - [key: string]: any; -} -export interface FormUnifiedColumnLayout { - uniqueColClassInSM: number; - uniqueColClassInMD: number; - uniqueColClassInLG: number; - uniqueColClassInEL: number; -} -export interface UseResponseFormLayoutSetting { - checkIsInFormComponent: (componentId: string) => boolean; - assembleUnifiedLayoutContext: (propertyData: any) => FormUnifiedColumnLayout; - changeFormControlsByUnifiedLayoutConfig: (formNode: any, unifiedLayout: FormUnifiedColumnLayout, formSchemaId: string) => void; -} diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/index.ts b/packages/mobile-ui-vue/components/dynamic-resolver/index.ts index 78edba9a400b180aaa2cf7c8804cb320a9212efa..e53b6e8e712046aebdad579a11cb18db9d77071f 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/index.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/index.ts @@ -9,7 +9,12 @@ export * from './src/selection-item-resolver'; export * from './src/editor-resolver'; export * from './src/visible-prop-resolver'; export * from './src/event-handler-resolver'; -export * from './src/schema-resolver'; +export * from './src/resolver/schema/schema-resolver'; +export * from './src/resolver/schema/schema-resolver-design'; export * from './src/update-columns-resolver'; +export * from './src/resolver/type-resolver/types'; +export * from './src/resolver/type-resolver/use-type-resolver-design'; +export * from './src/resolver/type-resolver/use-type-resolver'; -export { propertyConfigSchemaMap,getPropertyConfigBySchema } from './src/property-config-resolver'; +export { propertyConfigSchemaMap, getPropertyConfigBySchema } from './src/resolver/property-config/property-config-resolver'; +export { propertyConfigSchemaMapForDesigner, getPropertyConfigBySchemaForDesigner } from './src/resolver/property-config/property-config-resolver-design'; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/appearance.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/appearance.converter.ts index b6ca97b8dff89c0bce1fd44020c8388e552d2428..b197eb6c32c85d949dda840205b16376c7e30722 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/appearance.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/appearance.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/buttons.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/buttons.converter.ts index abfb60a4d295ffa47437e918cd566e80e7908a4d..1eb5a9f3b6d22c9415a20a4bf91bad058977b592 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/buttons.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/buttons.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/change-editor.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/change-editor.converter.ts index 61e5ef06b48fb0060091dc693d490bb44c31df24..72f511cefe1b2ebbb460330f042b5a2837def0be 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/change-editor.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/change-editor.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/enum-data.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/enum-data.converter.ts index 3b1a445ef2fa3bf474069910e903c293a16c3266..aec811359a71ae0e65201aca313583ef1c75b282 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/enum-data.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/enum-data.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/grid-selection.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/grid-selection.converter.ts index b37faa1b46e3dd9b97dd5b8c7183e7202b03f226..7c5e0797417cbe4db98bba063fbc5ce12aa4982f 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/grid-selection.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/grid-selection.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/items-count.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/items-count.converter.ts index 288438ef0f2b17a5b63d26388c4f6ec65589a75e..b23f948d25d240e52160612eecc78a49d7f341b9 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/items-count.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/items-count.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/pagination.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/pagination.converter.ts index ebf0e2bb56a5c1011f6ff81f0dffdd9aebe1a5d4..6cdde30711a4a02d2580e005d16a04c6714a4f01 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/pagination.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/pagination.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; /** * NG版,此处pagination类型是布尔 diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/property-editor.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/property-editor.converter.ts index e6e83cae987d6437ee8e7a1879641f845a0b9f0d..4c724568e9f65ce3f198fefc77cbf8925bd33d49 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/property-editor.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/property-editor.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/right-toolbar.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/right-toolbar.converter.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8047af63d4ce7aff16a299936f8065a3632d383 --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/right-toolbar.converter.ts @@ -0,0 +1,14 @@ +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; +import { PropertyConverter, SchemaService } from "../types"; + +export default { + convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { + if (!schema.rightToolbar) { + schema.rightToolbar = []; + } + schema.rightToolbar[propertyKey] = propertyValue; + }, + convertFrom: (schema: ComponentSchema, propertyKey: string, schemaService: SchemaService) => { + return schema.rightToolbar ? schema.rightToolbar[propertyKey] : schema[propertyKey]; + } +} as PropertyConverter; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/row-number.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/row-number.converter.ts index 929fb4e037af6a0ecd1de5b07549c82212a7d849..94a4e5c8711002e22cab3abc23f7d4303fdf0f07 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/row-number.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/row-number.converter.ts @@ -1,4 +1,4 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; import { PropertyConverter, SchemaService } from "../types"; export default { convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/type.converter.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/type.converter.ts index f3e2f4c71f0671f8aca0b0dd26fba07948ed1648..805dabf1907bb3469c1ad4ebc3a7a819a703fa55 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/type.converter.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/converter/type.converter.ts @@ -1,5 +1,5 @@ -import { ComponentSchema } from "../../../designer-canvas/src/types"; -import { DgControl } from "../../../designer-canvas/src/composition/dg-control"; +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; +import { DgControl } from "../../../common/src/properties/dg-control"; import { PropertyConverter, SchemaService } from "../types"; export default { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/property-config-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/property-config-resolver.ts index e28ab5abe929d292771cda41989730d90e71d015..ccf969fd64af0944e0a3af6c2baf06d6478caaab 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/property-config-resolver.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/property-config-resolver.ts @@ -1,9 +1,8 @@ import { computed, ref } from "vue"; import { EffectFunction, PropertyConverter, SchemaService } from './types'; -import { EditorConfig } from "../../dynamic-form"; +import { resolveSchemaWithDefaultValue } from "@farris/mobile-ui-vue/dynamic-resolver"; import { useObjectExpression } from './object-expression'; -import { ComponentSchema } from "../../designer-canvas/src/types"; -import { resolveSchemaWithDefaultValue } from "./schema-resolver"; +import { ComponentSchema, EditorConfig } from "@farris/mobile-ui-vue/common"; import appearanceConverter from './converter/appearance.converter'; import buttonsConverter from "./converter/buttons.converter"; import propertyEditorConverter from "./converter/property-editor.converter"; @@ -16,7 +15,7 @@ import gridSelectionConverter from "./converter/grid-selection.converter"; import itemsCountConverter from "./converter/items-count.converter"; import enumDataConverter from "./converter/enum-data.converter"; import formGroupLabelConverter from "./converter/form-group-label.converter"; -import { ElementPropertyConfig, PropertyEntity } from "@/components/property-panel"; +import { ElementPropertyConfig, PropertyEntity } from "@farris/mobile-ui-vue/common"; const propertyConfigSchemaMap = {} as Record; const propertyConverterMap = new Map([ diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/props-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/props-resolver.ts index c1d99b457bf0cb0c00f9f6c6c1ab6842b11f833d..1bfce6447bde7e46965037575d7dffbb67fae3af 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/props-resolver.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/props-resolver.ts @@ -1,9 +1,26 @@ -import { DesignerHostService } from './../../designer-canvas/src/composition/types'; -import { resolveSchemaToProps, schemaMap, schemaResolverMap } from './schema-resolver'; +import { DesignerHostService } from '@farris/mobile-ui-vue/common'; +import { resolveSchemaToProps } from './resolver/schema/schema-resolver'; import { DynamicResolver, EffectFunction, MapperFunction, SchemaResolverFunction } from './types'; -import { propertyConfigSchemaMap, propertyEffectMap } from './property-config-resolver'; +import { RegisterContext } from '@farris/mobile-ui-vue/common'; -export function createPropsResolver>( +/** + * 注册schema和props + */ +function registerSchemaAndProps( + defaultSchema: Record, + schemaResolver: SchemaResolverFunction, + propertyConfig: Record, + propertyEffect: EffectFunction, + registerContext: any +) { + const { schemaMap, schemaResolverMap, propertyConfigSchemaMap, propertyEffectMap } = registerContext; + schemaMap[defaultSchema.title] = defaultSchema; + schemaResolverMap[defaultSchema.title] = schemaResolver; + propertyConfigSchemaMap[defaultSchema.title] = propertyConfig; + propertyEffectMap[defaultSchema.title] = propertyEffect; +} + +export function getPropsResolverGenerator>( componentPropsObject: T, defaultSchema: Record, schemaMapper: Map = new Map(), @@ -16,16 +33,17 @@ export function createPropsResolver>( propertyConfig: Record = {}, propertyEffect: EffectFunction = (properties: Record) => properties ) { - schemaMap[defaultSchema.title] = defaultSchema; - schemaResolverMap[defaultSchema.title] = schemaResolver; - propertyConfigSchemaMap[defaultSchema.title] = propertyConfig; - propertyEffectMap[defaultSchema.title] = propertyEffect; - return (schemaValue: Record = {}) => { - const resolvedPropsValue = resolveSchemaToProps(schemaValue, defaultSchema, schemaMapper); - const defaultProps = Object.keys(componentPropsObject).reduce((propsObject: Record, propKey: string) => { - propsObject[propKey] = componentPropsObject[propKey].default; - return propsObject; - }, {}); - return Object.assign(defaultProps, resolvedPropsValue); + + return (registerContext: RegisterContext) => { + registerSchemaAndProps(defaultSchema, schemaResolver, propertyConfig, propertyEffect, registerContext); + + return (schemaValue: Record = {}) => { + const resolvedPropsValue = resolveSchemaToProps(schemaValue, defaultSchema, schemaMapper); + const defaultProps = Object.keys(componentPropsObject).reduce((propsObject: Record, propKey: string) => { + propsObject[propKey] = componentPropsObject[propKey].default; + return propsObject; + }, {}); + return Object.assign(defaultProps, resolvedPropsValue); + } }; } diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver-design.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver-design.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4fba29a4a83b4e77fca6b4c9903f0b8e05d06ad --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver-design.ts @@ -0,0 +1,13 @@ +import { EffectFunction } from '../../types'; +import { usePropertyConfigResolver } from './use-property-config-resolver'; + +const propertyConfigSchemaMapForDesigner = {} as Record; +const propertyEffectMapForDesigner = {} as Record; + +const { getPropertyConfigBySchema, getPropertyConfigByType, propertyConverterMap } = + usePropertyConfigResolver(propertyConfigSchemaMapForDesigner, propertyEffectMapForDesigner); + +export { + getPropertyConfigBySchema as getPropertyConfigBySchemaForDesigner, getPropertyConfigByType as getPropertyConfigByTypeForDesigner, + propertyConfigSchemaMapForDesigner, propertyConverterMap as propertyConverterMapForDesigner, propertyEffectMapForDesigner +}; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver.ts new file mode 100644 index 0000000000000000000000000000000000000000..199cbf45c5e922f3b483cc0b9f5d50b30b45c1f8 --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/property-config-resolver.ts @@ -0,0 +1,10 @@ +import { EffectFunction} from '../../types'; +import { usePropertyConfigResolver } from './use-property-config-resolver'; + +const propertyConfigSchemaMap = {} as Record; +const propertyEffectMap = {} as Record; + +const { getPropertyConfigBySchema, getPropertyConfigByType, propertyConverterMap } = + usePropertyConfigResolver(propertyConfigSchemaMap, propertyEffectMap); + +export { getPropertyConfigBySchema, getPropertyConfigByType, propertyConfigSchemaMap, propertyConverterMap, propertyEffectMap }; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/use-property-config-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/use-property-config-resolver.ts new file mode 100644 index 0000000000000000000000000000000000000000..c2ca508936d7df88967ae9f2750cd9c9bdec4468 --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/property-config/use-property-config-resolver.ts @@ -0,0 +1,248 @@ +import { computed, ref } from "vue"; +import { EffectFunction, PropertyConverter, SchemaService } from '../../types'; +import { useObjectExpression } from '../../object-expression'; +import { ComponentSchema,EditorConfig } from "@farris/mobile-ui-vue/common"; +import { resolveSchemaWithDefaultValue } from "../schema/schema-resolver"; +import appearanceConverter from '../../converter/appearance.converter'; +import buttonsConverter from "../../converter/buttons.converter"; +import propertyEditorConverter from "../../converter/property-editor.converter"; +import typeConverter from "../../converter/type.converter"; +import changeEditorConverter from "../../converter/change-editor.converter"; +import fieldSelectorConverter from "../../converter/field-selector.converter"; +import paginationConverter from "../../converter/pagination.converter"; +import rowNumberConverter from "../../converter/row-number.converter"; +import gridSelectionConverter from "../../converter/grid-selection.converter"; +import { ElementPropertyConfig, PropertyEntity } from "@farris/mobile-ui-vue/common"; +import itemsCountConverter from "../../converter/items-count.converter"; +import formGroupLabelConverter from "../../converter/form-group-label.converter"; + +export function usePropertyConfigResolver(propertyConfigSchemaMap: Record, propertyEffectMap: Record) { + const propertyConverterMap = new Map([ + ['/converter/appearance.converter', appearanceConverter], + ['/converter/buttons.converter', buttonsConverter], + ['/converter/property-editor.converter', propertyEditorConverter], + ['/converter/items-count.converter', itemsCountConverter], + ['/converter/type.converter', typeConverter], + ['/converter/change-editor.converter', changeEditorConverter], + ['/converter/form-group-label.converter', formGroupLabelConverter], + ['/converter/field-selector.converter', fieldSelectorConverter], + ['/converter/pagination.converter', paginationConverter], + ['/converter/row-number.converter', rowNumberConverter], + ['/converter/grid-selection.converter', gridSelectionConverter] + ]); + const propertyEditorMap = new Map([ + ['string', { type: 'input-group', enableClear: false }], + ['boolean', { + "type": "combo-list", + "textField": "name", + "valueField": "value", + "idField": "value", + "enableClear": false, + "editable": false, + "maxHeight": 64, + "data": [ + { + "value": true, + "name": "是" + }, + { + "value": false, + "name": "否" + } + ] + }], + ['enum', { "type": "combo-list", "maxHeight": 350, "enableClear": false, "editable": false }], + ['array', { "type": "button-edit" }], + ['number', { "type": "number-spinner", "placeholder": "" }], + ['events-editor', { "type": "events-editor", hide: true }] + ]); + + const useObjectExpressionComponstion = useObjectExpression(); + + function generateBooleanValue(pvalueSchema: Record, propertyConfigMap: Record) { + return () => useObjectExpressionComponstion.parseValueSchema(pvalueSchema, propertyConfigMap); + } + + function isVisible(propertySchemaKeys: string[], propertySchema: Record, propertyConfigMap: Record) + : boolean | (() => boolean) { + if (propertySchemaKeys.includes('visible') && propertySchema.visible !== undefined) { + return typeof propertySchema.visible === 'boolean' ? + () => Boolean(propertySchema.visible) : + propertySchema.visible === undefined ? true : generateBooleanValue(propertySchema.visible, propertyConfigMap); + } + return () => true; + } + + function isReadonly(propertySchemaKeys: string[], propertySchema: Record, propertyConfigMap: Record) { + if (propertySchemaKeys.includes('readonly') && propertySchema.readonly !== undefined) { + return typeof propertySchema.readonly === 'boolean' ? + () => Boolean(propertySchema.readonly) : + generateBooleanValue(propertySchema.readonly, propertyConfigMap); + } + return () => false; + } + + function tryGetPropertyConverter(propertySchema: Record, categoryConverter): PropertyConverter | null { + const $converter = propertySchema['$converter'] || categoryConverter; + if (typeof $converter === 'string') { + if ($converter && propertyConverterMap.has($converter)) { + return propertyConverterMap.get($converter) || null; + } + } + return $converter || null; + } + + /** + * + * @param propertiesInCategory + * 举例: + * visible: { + description: "运行时组件是否可见", + title: "是否可见", + type: "boolean" + } + 其中type属性 这个属性用来控制编辑器是哪一种,对应关系在propertyEditorMap中定义,boolean指定了下拉 + * @param propertyConfigMap + * @param editingSchema + * @param rawSchema + * @param schemaService + * @returns + */ + function getPropertyEntities( + propertiesInCategory: Record, + propertyConfigMap: Record, + editingSchema: ComponentSchema, + rawSchema: ComponentSchema, + schemaService: SchemaService, + componentId = '', + categoryConverter: any = '' + ): PropertyEntity[] { + const propertyEntities = Object.keys(propertiesInCategory).map((propertyKey: string) => { + const updateCount = ref(1); + const propertyID = propertyKey; + const propertySchema = propertiesInCategory[propertyKey]; + const propertySchemaKeys = Object.keys(propertySchema); + const propertyName = propertySchema.title; + const propertyType = propertySchema.type; + const defaultEditor = propertyEditorMap.get(propertyType) || { type: 'input-group', enableClear: false }; + const editor = propertySchema.editor ? Object.assign({}, defaultEditor, propertySchema.editor) as EditorConfig : Object.assign({}, defaultEditor); + const visible = isVisible(propertySchemaKeys, propertySchema, propertyConfigMap); + const readonly = isReadonly(propertySchemaKeys, propertySchema, propertyConfigMap); + editor.readonly = editor.readonly === undefined ? readonly() : editor.readonly; + const cascadeConfig = propertySchema.type === 'cascade' ? getPropertyEntities(propertySchema.properties, propertyConfigMap, editingSchema, rawSchema, schemaService, componentId, categoryConverter) : []; + const hideCascadeTitle = true; + let converter = tryGetPropertyConverter(propertySchema, categoryConverter); + // const propertyValue = ref(converter ? converter.convertFrom(schema, propertyKey) : schema[propertyKey]); + const propertyValue = computed({ + get() { + if (updateCount.value) { + // class、style 统一处理 + if (['class', 'style'].find(id => id === propertyID) && !converter) { + converter = propertyConverterMap.get('/converter/appearance.converter') || null; + } + if (converter && converter.convertFrom) { + return converter.convertFrom(editingSchema, propertyKey, schemaService, componentId); + } + // 获取属性时,如果没有convertForm,并且通过在Schema上获取得值是空,那就获取defaultValue属性值或者是空 + const editingSchemaValue = editingSchema[propertyKey]; + return Object.prototype.hasOwnProperty.call(propertySchema, 'defaultValue') && (editingSchemaValue === undefined || typeof editingSchemaValue == 'string' && editingSchemaValue === '') ? propertySchema['defaultValue'] || '' : editingSchemaValue; + } + return null; + }, + set(newValue) { + updateCount.value += 1; + if (converter && converter.convertTo) { + converter.convertTo(rawSchema, propertyKey, newValue, schemaService, componentId); + converter.convertTo(editingSchema, propertyKey, newValue, schemaService, componentId); + } else { + rawSchema[propertyKey] = newValue; + editingSchema[propertyKey] = newValue; + } + } + }); + const { refreshPanelAfterChanged, description, isExpand } = propertySchema; + const propertyEntity = { propertyID, propertyName, propertyType, propertyValue, editor, visible, readonly, cascadeConfig, hideCascadeTitle, refreshPanelAfterChanged, description, isExpand }; + propertyConfigMap[propertyID] = propertyEntity; + return propertyEntity; + }); + return propertyEntities; + } + + function getPropertyConfigByType(schemaType: string, schemaService: SchemaService, schema = {} as ComponentSchema): ElementPropertyConfig[] { + const propertyConfigMap = {} as Record; + const propertyConfigSchema = propertyConfigSchemaMap[schemaType]; + if (propertyConfigSchema && propertyConfigSchema.categories) { + const propertyConfigs = Object.keys(propertyConfigSchema.categories).map((categoryId: string) => { + const propertyCategory = propertyConfigSchema.categories[categoryId]; + const categoryName = propertyCategory?.title; + const properties = getPropertyEntities(propertyCategory.properties || {}, propertyConfigMap, {} as ComponentSchema, schema, schemaService); + return { categoryId, categoryName, properties }; + }); + return propertyConfigs; + } + return []; + } + + function tryToResolveReference(categoryId: string, propertyCategory: Record, rawSchema: ComponentSchema, schemaService: SchemaService, componentId = '') { + const refSchemaPath = propertyCategory.$ref.schema; + const $converter = propertyCategory.$ref.converter; + const refSchema = rawSchema[refSchemaPath]; + + const schemaType = refSchema.type; + const editingSchema = resolveSchemaWithDefaultValue(refSchema) as ComponentSchema; + const propertyConfigMap = {} as Record; + const propertyConfigSchema = propertyConfigSchemaMap[schemaType]; + if (propertyConfigSchema && propertyConfigSchema.categories) { + const propertyCategory = propertyConfigSchema.categories[categoryId]; + const categoryName = propertyCategory?.title; + if ($converter) { + Object.keys(propertyCategory.properties).forEach((propertyKey: any) => { + propertyCategory.properties[propertyKey].$converter = $converter; + }); + } + const propertiesInCategory = propertyCategory?.properties || {}; + const properties = getPropertyEntities(propertiesInCategory, propertyConfigMap, editingSchema, refSchema, schemaService, componentId); + return { categoryId, categoryName, properties }; + + } + return { categoryId, categoryName: '', properties: [] }; + } + + // jumphere + function getPropertyConfigBySchema(rawSchema: ComponentSchema, schemaService: SchemaService, designerItem: any, componentId: string, propertyConfig?: Record): ElementPropertyConfig[] { + const schemaType = rawSchema.type; + const editingSchema = resolveSchemaWithDefaultValue(rawSchema) as ComponentSchema; + const propertyConfigMap = {} as Record; + + // 先从ConfigMap中取简单类属性,若找不到,则在控件实例中取复杂属性 + let propertyConfigSchema = propertyConfig || propertyConfigSchemaMap[schemaType]; + if (propertyConfigSchema && Object.keys(propertyConfigSchema).length === 0 && designerItem && designerItem.getPropConfig) { + propertyConfigSchema = designerItem.getPropConfig(componentId); + } + if (propertyConfigSchema && propertyConfigSchema.categories) { + const propertyConfigs = [] as Array; + Object.keys(propertyConfigSchema.categories).map((categoryId: string) => { + const propertyCategory = propertyConfigSchema.categories[categoryId]; + if (propertyCategory.$ref) { + propertyConfigs.push(tryToResolveReference(categoryId, propertyCategory, rawSchema, schemaService, componentId) as ElementPropertyConfig); + return; + } + const categoryName = propertyCategory?.title; + const tabId = propertyCategory?.tabId; + const tabName = propertyCategory?.tabName; + const hide = propertyCategory?.hide; + const hideTitle = propertyCategory?.hideTitle; + const properties = getPropertyEntities(propertyCategory.properties || {}, propertyConfigMap, editingSchema, rawSchema, schemaService, componentId, propertyCategory['$converter']); + const { setPropertyRelates } = propertyCategory; + propertyConfigs.push({ categoryId, categoryName, tabId, tabName, hide, properties, hideTitle, setPropertyRelates }); + }); + return propertyConfigs; + } + return []; + } + + return { + getPropertyConfigBySchema, getPropertyConfigByType, propertyConverterMap + }; +} + diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver-design.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver-design.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5fe3e9316233858d0ab20262ba6ada7421b656d --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver-design.ts @@ -0,0 +1,14 @@ +import { SchemaResolverFunction } from "../../types"; +import { useSchemaResolver } from "./use-schema-resolver"; + +const schemaMapForDesigner = {} as Record; +const schemaResolverMapForDesigner = {} as Record; + +const { getSchemaByType, resolveSchemaWithDefaultValue, resolveSchemaToProps, mappingSchemaToProps } = + useSchemaResolver(schemaMapForDesigner, schemaResolverMapForDesigner); + +export { + getSchemaByType as getSchemaByTypeForDesigner, resolveSchemaWithDefaultValue as resolveSchemaWithDefaultValueForDesigner, + resolveSchemaToProps as resolveSchemaToPropsForDesigner, schemaMapForDesigner, schemaResolverMapForDesigner, + mappingSchemaToProps as mappingSchemaToPropsForDesigner +}; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver.ts new file mode 100644 index 0000000000000000000000000000000000000000..083e2015cd35a9579a6cccce71c5cf2120ae0367 --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/schema-resolver.ts @@ -0,0 +1,10 @@ +import { SchemaResolverFunction } from "../../types"; +import { useSchemaResolver } from "./use-schema-resolver"; + +const schemaMap = {} as Record; +const schemaResolverMap = {} as Record; + +const { getSchemaByType, resolveSchemaWithDefaultValue, resolveSchemaToProps, mappingSchemaToProps } = + useSchemaResolver(schemaMap, schemaResolverMap); + +export { getSchemaByType, resolveSchemaWithDefaultValue, resolveSchemaToProps, schemaMap, schemaResolverMap, mappingSchemaToProps }; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/use-schema-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/use-schema-resolver.ts new file mode 100644 index 0000000000000000000000000000000000000000..15a77a4a2251c1000fbf49a86db0535911d2340a --- /dev/null +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/schema/use-schema-resolver.ts @@ -0,0 +1,137 @@ +import { cloneDeep, isPlainObject } from "lodash-es"; +import { MapperFunction, SchemaResolverFunction } from "../../types"; +import { DesignerHostService } from "@farris/mobile-ui-vue/common"; + + +export function useSchemaResolver(schemaMap: Record, schemaResolverMap: Record) { + + function getSchemaValueByDefault(defaultSchema: Record): Record { + const { properties, title, ignore: ignoreList } = defaultSchema as Record; + const canIgnoreProperty = ignoreList && Array.isArray(ignoreList); + const resolvedSchema = Object.keys(properties).reduce((propsObject: Record, propKey: string) => { + if (!canIgnoreProperty || !ignoreList.find(item => item === propKey)) { + propsObject[propKey] = (properties[propKey].type === 'object' && !!properties[propKey].properties) ? + getSchemaValueByDefault(properties[propKey]) : cloneDeep(properties[propKey].default); + } + return propsObject; + }, {}); + if (title && (!canIgnoreProperty || !ignoreList.find(item => item === 'id'))) { + const typePrefix = title.toLowerCase().replace(/-/g, '_'); + resolvedSchema.id = `${typePrefix}_${Math.random().toString().slice(2, 6)}`; + } + return resolvedSchema; + } + + /** + * 获取控件元数据,只组装必填的字段 + */ + function getRequiredSchemaValueByDefault(defaultSchema: Record): Record { + const { properties, title, required: requiredProperty } = defaultSchema as Record; + if (requiredProperty && Array.isArray(requiredProperty)) { + const resolvedSchema = requiredProperty.reduce((propsObject: Record, propKey: string) => { + + propsObject[propKey] = (properties[propKey].type === 'object' && !!properties[propKey].properties) ? + getSchemaValueByDefault(properties[propKey]) : cloneDeep(properties[propKey].default); + + return propsObject; + }, {}); + if (title && requiredProperty.find(item => item === 'id')) { + const typePrefix = title.toLowerCase().replace(/-/g, '_'); + resolvedSchema.id = `${typePrefix}_${Math.random().toString().slice(2, 6)}`; + } + return resolvedSchema; + } + return { + type: title + }; + + } + + function getSchemaByType(componentType: string, resolveContext: Record = {}, designerHostService?: DesignerHostService) + : Record | null { + const defaultSchema = schemaMap[componentType]; + if (defaultSchema) { + let componentSchema = getRequiredSchemaValueByDefault(defaultSchema); + const schemaResolver = schemaResolverMap[componentType]; + componentSchema = schemaResolver ? schemaResolver({ getSchemaByType }, componentSchema, resolveContext, designerHostService) + : componentSchema; + return componentSchema; + } + return null; + } + + function resolveSchema(schemaValue: Record, defaultSchema: Record): Record { + + const resolvedSchema = getSchemaValueByDefault(defaultSchema); + + Object.keys(resolvedSchema).reduce((resolvedSchema: Record, propKey: string) => { + if (Object.prototype.hasOwnProperty.call(schemaValue, propKey)) { + // 解决属性是对象类型,默认值被冲掉的情况 + // 增加非判断,解决针对属性时对象,但是schemaValue=null或者undefined情况 + if (resolvedSchema[propKey] && isPlainObject(resolvedSchema[propKey]) && (isPlainObject(schemaValue[propKey] || !schemaValue[propKey]))) { + Object.assign(resolvedSchema[propKey], schemaValue[propKey] || {}); + } else { + resolvedSchema[propKey] = schemaValue[propKey]; + } + } + + return resolvedSchema; + }, resolvedSchema); + + return resolvedSchema; + }; + + function mappingSchemaToProps(resolvedSchema: Record, schemaMapper: Map) { + const props = Object.keys(resolvedSchema) + .filter((propKey: string) => resolvedSchema[propKey] != null) + .reduce((resolvedProps: Record, propKey: string) => { + if (schemaMapper.has(propKey)) { + const mapper = schemaMapper.get(propKey) as string | MapperFunction; + if (typeof mapper === 'string') { + resolvedProps[mapper] = resolvedSchema[propKey]; + } else { + const mapperResult = (mapper as MapperFunction)(propKey, resolvedSchema[propKey], resolvedSchema); + Object.assign(resolvedProps, mapperResult); + } + } else { + resolvedProps[propKey] = resolvedSchema[propKey]; + } + return resolvedProps; + }, {}); + return props; + } + + function resolveSchemaToProps( + schemaValue: Record, + defaultSchema: Record, + schemaMapper: Map = new Map() + ): Record { + const resolvedSchema = resolveSchema(schemaValue, defaultSchema); + const props = mappingSchemaToProps(resolvedSchema, schemaMapper); + return props; + } + + function resolveSchemaWithDefaultValue(schemaValue: Record): Record { + const componentType = schemaValue.type; + if (componentType) { + const defaultSchema = schemaMap[componentType]; + if (!defaultSchema) { + return schemaValue; + } + const resolvedSchema = resolveSchema(schemaValue, defaultSchema); + const editorType = schemaValue.editor?.type || ''; + /* 解决schemeValue结构如下图场景,在editor下,获取不到date-picker类型的默认值的问题 + * {type:'input-group',...,editor:{type:'date-picker',...}} + */ + if (editorType) { + const defaulEditorSchema = schemaMap[editorType]; + const resolvedEditorSchema = resolveSchema(schemaValue.editor, defaulEditorSchema); + resolvedSchema.editor = resolvedEditorSchema; + } + return resolvedSchema; + } + return schemaValue; + } + + return { getSchemaByType, resolveSchemaWithDefaultValue, resolveSchemaToProps, mappingSchemaToProps }; +} diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/composition/types.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/types.ts similarity index 80% rename from packages/mobile-ui-vue/components/dynamic-form/src/composition/types.ts rename to packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/types.ts index 6963eb1869721853f90e07126f2d450f0aeca887..e849360777a18919f0d83ee845e739b17f3bb387 100644 --- a/packages/mobile-ui-vue/components/dynamic-form/src/composition/types.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/types.ts @@ -1,4 +1,5 @@ -import { EditorConfig } from "../types"; +import { EditorConfig } from "@farris/mobile-ui-vue/common"; + export interface UseTypeResolver { @@ -9,4 +10,4 @@ export interface UseTypeResolver { getChangeFunctionName(type: string): any; getClearFunctionName(type: string): any; -} +} \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver-design.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver-design.ts similarity index 57% rename from packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver-design.ts rename to packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver-design.ts index 9777e1d6971d455e0180f85b90c8275647984a6a..b8d7996447d268488179fc0e05ba61aa7ee56e19 100644 --- a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver-design.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver-design.ts @@ -1,18 +1,18 @@ -import { componentMap, componentPropsConverter } from '../../../../components/designer-canvas/src/components/maps'; -import FInputGroupDesign from '../../../input-group/src/designer/input-group.design.component'; -import { EditorType, EditorConfig } from "../types"; +import { componentMapForDesigner,componentPropsConverterForDesigner } from '@farris/mobile-ui-vue/register-designer'; +import FInputGroupDesign from '../../../../input-group/src/designer/input-group.design.component'; import { UseTypeResolver } from "./types"; +import { EditorConfig, EditorType } from '@farris/mobile-ui-vue/common'; export function useTypeResolverDesign(): UseTypeResolver { function resolveEditorProps(type: EditorType, config: EditorConfig): Record { - const propsConverter = componentPropsConverter[type]; + const propsConverter = componentPropsConverterForDesigner[type]; const viewProps = propsConverter ? propsConverter(config) : {}; return viewProps; } function resolveEditorType(type: EditorType) { - return componentMap[type] || FInputGroupDesign; + return componentMapForDesigner[type] || FInputGroupDesign; } function getChangeFunctionName(type: EditorType) { diff --git a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver.ts similarity index 94% rename from packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts rename to packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver.ts index 2845948f29e29b93bde7cd46555c1a674e997f77..dc0fb311dd853281d6fe3daa5f9daddc029592fc 100644 --- a/packages/mobile-ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/resolver/type-resolver/use-type-resolver.ts @@ -1,8 +1,8 @@ -import FInputGroup from '../../../input-group/src/input-group.component'; -import { EditorType, EditorConfig } from "../types"; +import FInputGroup from '../../../../input-group/src/input-group.component'; import { UseTypeResolver } from "./types"; -import { componentMap, propsConverterMap, registerComponents } from '../../../register'; +import { componentMap, propsConverterMap, registerComponents } from '../../../../register'; +import { EditorConfig, EditorType } from '@farris/mobile-ui-vue/common'; export function useTypeResolver(): UseTypeResolver { diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/schema-resolver.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/schema-resolver.ts deleted file mode 100644 index d2dada2e4dce345c0469384e651956d9fed0c453..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/schema-resolver.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { cloneDeep, isPlainObject } from "lodash-es"; -import { DesignerHostService } from "../../designer-canvas/src/composition/types"; -import { MapperFunction, SchemaResolverFunction } from "./types"; - -const schemaMap = {} as Record; -const schemaResolverMap = {} as Record; - -function getSchemaValueByDefault(defaultSchema: Record): Record { - const { properties, title, ignore: ignoreList } = defaultSchema as Record; - const canIgnoreProperty = ignoreList && Array.isArray(ignoreList); - const resolvedSchema = Object.keys(properties).reduce((propsObject: Record, propKey: string) => { - if (!canIgnoreProperty || !ignoreList.find(item => item === propKey)) { - propsObject[propKey] = (properties[propKey].type === 'object' && !!properties[propKey].properties) ? - getSchemaValueByDefault(properties[propKey]) : cloneDeep(properties[propKey].default); - } - return propsObject; - }, {}); - if (title && (!canIgnoreProperty || !ignoreList.find(item => item === 'id'))) { - const typePrefix = title.toLowerCase().replace(/-/g, '_'); - resolvedSchema.id = `${typePrefix}_${Math.random().toString().slice(2, 6)}`; - } - return resolvedSchema; -} -/** - * 获取控件元数据,只组装必填的字段 - */ -function getRequiredSchemaValueByDefault(defaultSchema: Record): Record { - const { properties, title, required: requiredProperty } = defaultSchema as Record; - if (requiredProperty && Array.isArray(requiredProperty)) { - const resolvedSchema = requiredProperty.reduce((propsObject: Record, propKey: string) => { - - propsObject[propKey] = (properties[propKey].type === 'object' && !!properties[propKey].properties) ? - getSchemaValueByDefault(properties[propKey]) : cloneDeep(properties[propKey].default); - - return propsObject; - }, {}); - if (title && requiredProperty.find(item => item === 'id')) { - const typePrefix = title.toLowerCase().replace(/-/g, '_'); - resolvedSchema.id = `${typePrefix}_${Math.random().toString().slice(2, 6)}`; - } - return resolvedSchema; - } - return { - type: title - }; - -} -function getSchemaByType(componentType: string, resolveContext: Record = {}, designerHostService?: DesignerHostService) - : Record | null { - const defaultSchema = schemaMap[componentType]; - if (defaultSchema) { - let componentSchema = getRequiredSchemaValueByDefault(defaultSchema); - const schemaResolver = schemaResolverMap[componentType]; - componentSchema = schemaResolver ? schemaResolver({ getSchemaByType }, componentSchema, resolveContext, designerHostService) - : componentSchema; - return componentSchema; - } - return null; -} - -function resolveSchema(schemaValue: Record, defaultSchema: Record): Record { - - const resolvedSchema = getSchemaValueByDefault(defaultSchema); - - Object.keys(resolvedSchema).reduce((resolvedSchema: Record, propKey: string) => { - if (Object.prototype.hasOwnProperty.call(schemaValue, propKey)) { - // 解决属性是对象类型,默认值被冲掉的情况 - // 增加非判断,解决针对属性时对象,但是schemaValue=null或者undefined情况 - if (resolvedSchema[propKey] && isPlainObject(resolvedSchema[propKey]) && (isPlainObject(schemaValue[propKey] || !schemaValue[propKey]))) { - Object.assign(resolvedSchema[propKey], schemaValue[propKey] || {}); - } else { - resolvedSchema[propKey] = schemaValue[propKey]; - } - } - - return resolvedSchema; - }, resolvedSchema); - - return resolvedSchema; -}; - -function mappingSchemaToProps(resolvedSchema: Record, schemaMapper: Map) { - const props = Object.keys(resolvedSchema) - .filter((propKey: string) => resolvedSchema[propKey] != null) - .reduce((resolvedProps: Record, propKey: string) => { - if (schemaMapper.has(propKey)) { - const mapper = schemaMapper.get(propKey) as string | MapperFunction; - if (typeof mapper === 'string') { - resolvedProps[mapper] = resolvedSchema[propKey]; - } else { - const mapperResult = (mapper as MapperFunction)(propKey, resolvedSchema[propKey], resolvedSchema); - Object.assign(resolvedProps, mapperResult); - } - } else { - resolvedProps[propKey] = resolvedSchema[propKey]; - } - return resolvedProps; - }, {}); - return props; -} - -function resolveSchemaToProps( - schemaValue: Record, - defaultSchema: Record, - schemaMapper: Map = new Map() -): Record { - const resolvedSchema = resolveSchema(schemaValue, defaultSchema); - const props = mappingSchemaToProps(resolvedSchema, schemaMapper); - return props; -} - -function resolveSchemaWithDefaultValue(schemaValue: Record): Record { - const componentType = schemaValue.type; - if (componentType) { - const defaultSchema = schemaMap[componentType]; - if (!defaultSchema) { - return schemaValue; - } - const resolvedSchema = resolveSchema(schemaValue, defaultSchema); - const editorType = schemaValue.editor?.type || ''; - /* 解决schemeValue结构如下图场景,在editor下,获取不到date-picker类型的默认值的问题 - * {type:'input-group',...,editor:{type:'date-picker',...}} - */ - if (editorType) { - const defaulEditorSchema = schemaMap[editorType]; - const resolvedEditorSchema = resolveSchema(schemaValue.editor, defaulEditorSchema); - resolvedSchema.editor = resolvedEditorSchema; - } - return resolvedSchema; - } - return schemaValue; -} - -export { getSchemaByType, resolveSchemaWithDefaultValue, resolveSchemaToProps, schemaMap, schemaResolverMap }; diff --git a/packages/mobile-ui-vue/components/dynamic-resolver/src/types.ts b/packages/mobile-ui-vue/components/dynamic-resolver/src/types.ts index c82d887f40275fab8f939ec07e52a24219feb9f5..6eeaa174453212eaf24b02ecef027aab41dadea0 100644 --- a/packages/mobile-ui-vue/components/dynamic-resolver/src/types.ts +++ b/packages/mobile-ui-vue/components/dynamic-resolver/src/types.ts @@ -1,5 +1,5 @@ -import { DesignerHostService } from "../../designer-canvas/src/composition/types"; +import { DesignerHostService } from "@farris/mobile-ui-vue/common"; export type MapperFunction = (key: string, value: any, resolvedSchema?: any) => Record; diff --git a/packages/mobile-ui-vue/components/dynamic-view/src/composition/use-render-component.ts b/packages/mobile-ui-vue/components/dynamic-view/src/composition/use-render-component.ts index 45d32b2260fdd810cb68311857cb0bf95af5ba08..08134f1b9ea8c9f30f460af430470171c183853f 100644 --- a/packages/mobile-ui-vue/components/dynamic-view/src/composition/use-render-component.ts +++ b/packages/mobile-ui-vue/components/dynamic-view/src/composition/use-render-component.ts @@ -1,8 +1,8 @@ /* eslint-disable no-use-before-define */ import { createVNode, VNode } from 'vue'; -import { registerComponents } from '@components/register'; -import { componentMap, propsConverterMap } from '@components/register'; -import { schemaMap } from '@components/dynamic-resolver'; +import { registerComponents } from '@farris/mobile-ui-vue/register'; +import { componentMap, propsConverterMap } from '@farris/mobile-ui-vue/register'; +import { schemaMap } from '@farris/mobile-ui-vue/dynamic-resolver'; import { DynamicViewContext } from './use-context'; export function useRenderComponent(context: DynamicViewContext) { diff --git a/packages/mobile-ui-vue/components/filter/index.ts b/packages/mobile-ui-vue/components/filter/index.ts index 999a8428e0ee1c8a8836a7ba0772f63b079bfdef..80b94141d0095da5f187f4144a559143b9cea47c 100644 --- a/packages/mobile-ui-vue/components/filter/index.ts +++ b/packages/mobile-ui-vue/components/filter/index.ts @@ -1,4 +1,4 @@ -import { withInstall, } from '@components/common'; +import { withInstall, } from '@farris/mobile-ui-vue/common'; import FilterInstallless from './src/filter.component'; import { ControlType } from './src/compositions'; const Filter = withInstall(FilterInstallless); diff --git a/packages/mobile-ui-vue/components/filter/src/components/field-list.component.tsx b/packages/mobile-ui-vue/components/filter/src/components/field-list.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..66c345464d2cbe8d00eb931f81e690426a0fad75 --- /dev/null +++ b/packages/mobile-ui-vue/components/filter/src/components/field-list.component.tsx @@ -0,0 +1,58 @@ +import { computed, defineComponent, PropType, ref, watch } from 'vue'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { FILTER_PANEL_NAME } from '../filter-panel.props'; + +export default defineComponent({ + props: { + modelValue: { type: Array as PropType, default: () => [] }, + data: { type: Array as PropType>, default: () => [] }, + valueField: { type: String, default: '' }, + textField: { type: String, default: '' }, + multiSelect: { type: Boolean, default: false }, + }, + setup(props, context) { + const { emit } = context; + + const { bem } = useBem(FILTER_PANEL_NAME); + + const modelValue = ref(props.modelValue); + watch(()=>props.modelValue, ()=>{ + modelValue.value = props.modelValue; + }); + + const isSelected = (item: Record)=>{ + return modelValue.value.includes(item[props.valueField]); + }; + + const getListItemClass = (item: Record)=>{ + const classList = [bem(['field', 'list', 'item'])]; + isSelected(item) && classList.push(bem(['field', 'list', 'item'], 'selected')); + return classList; + }; + + const handleClick = (item: Record) => { + const value = item[props.valueField]; + if(props.multiSelect) { + if(!isSelected(item)) { + modelValue.value.push(value); + } else { + modelValue.value = modelValue.value.filter(el=> el !== value); + } + } else { + modelValue.value = [value]; + } + + emit('change', modelValue.value); + }; + + return () => ( +
+ {props.data.map((item: Record) => ( +
handleClick(item)}> + {item[props.textField]} +
+ ))} +
+ ); + } +}); diff --git a/packages/mobile-ui-vue/components/filter/src/components/field.component.tsx b/packages/mobile-ui-vue/components/filter/src/components/field.component.tsx index 19f0065771ef532d93457bb00ea53505e7784ffd..9f51c5da61ab08e715a2b2d064aa6d53c67570cc 100644 --- a/packages/mobile-ui-vue/components/filter/src/components/field.component.tsx +++ b/packages/mobile-ui-vue/components/filter/src/components/field.component.tsx @@ -1,4 +1,4 @@ -import { useBem } from '@/components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { defineComponent } from 'vue'; import { FILTER_PANEL_NAME } from '../filter-panel.props'; diff --git a/packages/mobile-ui-vue/components/filter/src/compositions/type.ts b/packages/mobile-ui-vue/components/filter/src/compositions/type.ts index 476a532cb63ba3d533f46c7efa0c11bdce426803..bbd65ecb51e76781babcad500c1f3539bf1f8839 100644 --- a/packages/mobile-ui-vue/components/filter/src/compositions/type.ts +++ b/packages/mobile-ui-vue/components/filter/src/compositions/type.ts @@ -1,8 +1,9 @@ -import { FilterCondition } from "@/components/common"; +import { FilterCondition } from "@farris/mobile-ui-vue/common"; export enum ControlType { InputGroup = 'input-group', DatePicker = 'date-picker', + DatePickerRange = 'date-picker-range', DateTimePicker = 'datetime-picker', Number = 'number', NumberRange = 'number-range', diff --git a/packages/mobile-ui-vue/components/filter/src/compositions/use-condition.ts b/packages/mobile-ui-vue/components/filter/src/compositions/use-condition.ts index 03b90d3d45b34517b90235a36ddc5d31325bb98d..bdac33e4fb4e72160f61a56156422a20093c291f 100644 --- a/packages/mobile-ui-vue/components/filter/src/compositions/use-condition.ts +++ b/packages/mobile-ui-vue/components/filter/src/compositions/use-condition.ts @@ -1,4 +1,4 @@ -import { FilterCondition, FilterCompareType, FilterExpressType, FilterRelation, isDef, isString } from "@/components/common"; +import { FilterCondition, FilterCompareType, FilterExpressType, FilterRelation, isDef, isString } from "@farris/mobile-ui-vue/common"; import { ControlType, FieldConfig } from "./type"; export const userCondition = () => { const ConditionTemplate: FilterCondition = { @@ -37,15 +37,16 @@ export const userCondition = () => { const { code, controlType } = config; const conditions: FilterCondition[] = []; switch (controlType) { + case ControlType.Number: case ControlType.DatePicker: case ControlType.DateTimePicker: - case ControlType.Number: case ControlType.RadioGroup:{ const condition = { ...ConditionTemplate, FilterField: code, Value: value, Compare: FilterCompareType.Equal }; conditions.push(condition); break; } - case ControlType.NumberRange:{ + case ControlType.NumberRange: + case ControlType.DatePickerRange:{ const { start, end } = value; const startCondition = { ...ConditionTemplate, FilterField: code, Value: start, Compare: FilterCompareType.GreaterOrEqual }; @@ -67,6 +68,19 @@ export const userCondition = () => { break; } case ControlType.List:{ + const listConditions: FilterCondition[] = []; + value.forEach((itemValue: string, index: number) => { + const condition = { + ...ConditionTemplate, + FilterField: code, + Value: itemValue, + Compare: FilterCompareType.Equal, + Relation: index === value.length - 1 ? FilterRelation.And : FilterRelation.Or + }; + listConditions.push(condition); + }); + addBrackets(listConditions); + conditions.push(...listConditions); break; } default:{ diff --git a/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-panel-state.ts b/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-panel-state.ts index 3348291182d661def4f19dd0f6898b2e3345199d..7d24064d8778620d02418801bc8b3200202d9a3b 100644 --- a/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-panel-state.ts +++ b/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-panel-state.ts @@ -1,6 +1,7 @@ import { computed, reactive, watch } from "vue"; import { FilterPanelProps } from "../filter-panel.props"; import { userCondition } from "./use-condition"; +import { omitProperty } from "@farris/mobile-ui-vue/common"; export const useFilterPanelState = (props: FilterPanelProps)=>{ const filterData = reactive({}); @@ -15,8 +16,18 @@ export const useFilterPanelState = (props: FilterPanelProps)=>{ return props.modelValue ? props.modelValue[name] : undefined; }; + const fieldConfigs = computed(() => { + return props.configs.map(config=>{ + const { editor } = config; + return { + ...config, + editor: omitProperty(editor, 'type') + }; + }); + }); + const initFilterData = ()=>{ - props.configs.map(config=>{ + fieldConfigs.value.map(config=>{ const { code } = config; filterData[code] = getModelValue(code); }); @@ -39,6 +50,7 @@ export const useFilterPanelState = (props: FilterPanelProps)=>{ return { filterData, filterConditions, + fieldConfigs, resetData, getFilterPanelState }; diff --git a/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-state.ts b/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-state.ts index f14420dbedc00eaa2394b62db00daff7580685f9..7f6f6317fdb8d530b49ef563c8b73087a024cf52 100644 --- a/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-state.ts +++ b/packages/mobile-ui-vue/components/filter/src/compositions/use-filter-state.ts @@ -2,7 +2,7 @@ import { computed, onMounted, reactive, ref, SetupContext, shallowRef, watch } f import { userCondition } from "./use-condition"; import { FilterProps } from "../filter.props"; import { ChangePayload, ConfirmPayload, FilterEmits } from "./type"; -import { FilterCondition } from "@/components/common"; +import { FilterCondition } from "@farris/mobile-ui-vue/common"; export const useFilterState = (props: FilterProps, context: SetupContext)=>{ const { emit } = context; diff --git a/packages/mobile-ui-vue/components/filter/src/compositions/use-render-field-item.tsx b/packages/mobile-ui-vue/components/filter/src/compositions/use-render-field-item.tsx index dcf0685e275864c2cae8ade242612dbf1993dbbe..dd33a6ddca467488e2d0b38502c0218ae1e54c54 100644 --- a/packages/mobile-ui-vue/components/filter/src/compositions/use-render-field-item.tsx +++ b/packages/mobile-ui-vue/components/filter/src/compositions/use-render-field-item.tsx @@ -1,8 +1,10 @@ -import { InputGroup } from "@/components/input-group"; +import { SetupContext } from "vue"; +import { InputGroup } from "@farris/mobile-ui-vue/input-group"; +import { getValue, setValue, useBem } from "@farris/mobile-ui-vue/common"; +import DatePicker from "@farris/mobile-ui-vue/date-picker"; import { ControlType, FieldConfig, FilterPanelEmits } from "./type"; -import { getValue, setValue, useBem } from "@/components/common"; import { FILTER_PANEL_NAME } from "../filter-panel.props"; -import { SetupContext } from "vue"; +import FieldList from '../components/field-list.component'; export const useRenderFieldItem = (filterData: Record, context: SetupContext) => { const { emit } = context; @@ -14,37 +16,31 @@ export const useRenderFieldItem = (filterData: Record, context: Set emit('change', { code, value, data: filterData }); }; - const renderInput = (inputProps = {}) => { + const getFieldProps = (config: FieldConfig)=>{ + const { code, editor = {} } = config; + return { + ...editor, + modelValue: getValue(code, filterData), + onChange: (value: any) => handleChange(code, value), + onConfirm: (value: any) => handleChange(code, value), + }; + }; + + const renderInputGroup = (config: FieldConfig) =>{ + const inputProps = getFieldProps(config); + return ( ); }; - const renderInputGroup = (config: FieldConfig) =>{ - const { code, editor = {} } = config; - const inputProps = { - ...editor, - modelValue: getValue(code, filterData), - onChange: (value: any) => handleChange(code, value) - }; - - return renderInput(inputProps); - }; - const renderNumber = (config: FieldConfig) => { - const { code, editor = {} } = config; - const inputProps = { - ...editor, - type: 'number', - modelValue: getValue(code, filterData), - onChange: (value: any) => handleChange(code, value) - }; + const { editor = {} } = config; - return renderInput(inputProps); + return renderInputGroup({...config, editor: { ...editor, type: 'number' }}); }; const renderNumberRange = (config: FieldConfig) => { @@ -60,36 +56,55 @@ export const useRenderFieldItem = (filterData: Record, context: Set ); }; + const renderDatePicker = (config: FieldConfig) => { - const { code, editor = {} } = config; - const inputProps = { - ...editor, - type: 'number', - modelValue: getValue(code, filterData), - onChange: (value: any) => handleChange(code, value) - }; + const inputProps = getFieldProps(config); - return renderInput(inputProps); + return ( + + ); + }; + + const renderDatePickerRange = (config: FieldConfig) => { + const { code } = config; + const startCode = `${code}.start`; + const endCode = `${code}.end`; + + return ( +
+ {renderDatePicker({...config, code: startCode})} + + {renderDatePicker({...config, code: endCode})} +
+ ); + }; + + const renderList = (config: FieldConfig) =>{ + const inputProps = getFieldProps(config); + + return ( + + ); }; const renderFieldItem = (config: FieldConfig) => { const { controlType } = config; switch (controlType) { case ControlType.DatePicker: - - break; - case ControlType.DateTimePicker: - - break; + return renderDatePicker(config); + case ControlType.DatePickerRange: + return renderDatePickerRange(config); case ControlType.Number: return renderNumber(config); - break; case ControlType.NumberRange: return renderNumberRange(config); - break; case ControlType.List: - - break; + return renderList(config); case ControlType.RadioGroup: break; diff --git a/packages/mobile-ui-vue/components/filter/src/filter-panel.component.tsx b/packages/mobile-ui-vue/components/filter/src/filter-panel.component.tsx index 2b797eee385121d0baf9b0556a42f8a253df1dc1..dd8cf08d945d95339123463bcd109b3c1feb17b8 100644 --- a/packages/mobile-ui-vue/components/filter/src/filter-panel.component.tsx +++ b/packages/mobile-ui-vue/components/filter/src/filter-panel.component.tsx @@ -1,6 +1,6 @@ import { computed, defineComponent, SetupContext, watch } from 'vue'; -import { useBem } from '@/components/common'; -import ButtonGroup from '@/components/button-group'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import ButtonGroup from '@farris/mobile-ui-vue/button-group'; import { FILTER_PANEL_NAME, filterPanelProps } from './filter-panel.props'; import { FieldConfig, FilterPanelEmits, useFilterPanelState, useRenderFieldItem } from './compositions'; import FieldComponent from './components/field.component'; @@ -13,14 +13,11 @@ export default defineComponent({ const { bem } = useBem(FILTER_PANEL_NAME); - const { filterData, filterConditions, resetData, getFilterPanelState } = useFilterPanelState(props); + const { filterData, fieldConfigs, filterConditions, resetData, getFilterPanelState } = useFilterPanelState(props); expose({ getFilterPanelState }); /* content */ - const fieldConfigs = computed(() => { - return props.configs; - }); const { renderFieldItem } = useRenderFieldItem(filterData, context); const getFieldSlots = (config: FieldConfig)=>{ return { diff --git a/packages/mobile-ui-vue/components/filter/src/filter-panel.props.ts b/packages/mobile-ui-vue/components/filter/src/filter-panel.props.ts index 6a7e52b2dc1cc9a16bf674fddffd71777dce9c3f..9f97a433015a7c5496399e89b3118bb58de26d32 100644 --- a/packages/mobile-ui-vue/components/filter/src/filter-panel.props.ts +++ b/packages/mobile-ui-vue/components/filter/src/filter-panel.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { PopupPosition } from '@/components/popup'; +import { PopupPosition } from '@farris/mobile-ui-vue/popup'; import { FieldConfig } from './compositions/type'; export const FILTER_PANEL_NAME = "FmFilterPanel"; diff --git a/packages/mobile-ui-vue/components/filter/src/filter-panel.scss b/packages/mobile-ui-vue/components/filter/src/filter-panel.scss index 317bf32379b93b07f6ad5aaac4fcf911dc4a027b..42f4f318147e6dc97a3e10dc997a94a8139006c5 100644 --- a/packages/mobile-ui-vue/components/filter/src/filter-panel.scss +++ b/packages/mobile-ui-vue/components/filter/src/filter-panel.scss @@ -32,16 +32,38 @@ border: 1px solid #999; } } + @include e(list, true) { + display: flex; + flex-wrap: wrap; + margin: 0 -5px; + @include e(item, true){ + height: 30px; + width: 89px; + font-size: 13px; + text-align: center; + overflow: hidden; + padding: 6px 8px; + margin: 0 5px 10px 5px; + background: var(--fm-background); + border-radius: var(--fm-radius-md); + color: var(--fm-primary-color); + @include m(selected) { + background: var(--fm-primary-color); + color: var(--fm-background-white); + } + } + } + + .fm-input-group .fm-input-group__body{ + padding: 6px 8px; + line-height: 18px; + font-size: 13px; + color: var(--fm-primary-color); + background: var(--fm-background); + border-radius: var(--fm-radius-md); + overflow: hidden; + } } - @include e(input) { - padding: 6px 8px; - line-height: 18px; - font-size: 13px; - color: var(--fm-primary-color); - background: var(--fm-background); - border-radius: var(--fm-radius-md); - overflow: hidden; - } } \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/filter/src/filter.component.tsx b/packages/mobile-ui-vue/components/filter/src/filter.component.tsx index 218daa9df049bc0dded79c29aa88ef60b9e5c37e..d41385085d73bdca8fd25054bfb57c8116e71d34 100644 --- a/packages/mobile-ui-vue/components/filter/src/filter.component.tsx +++ b/packages/mobile-ui-vue/components/filter/src/filter.component.tsx @@ -1,8 +1,8 @@ import { computed, defineComponent, ref, SetupContext } from 'vue'; -import { useBem } from '@/components/common'; -import Icon from '@/components/icon'; -import Search from '@/components/search'; -import Popup from '@/components/popup'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import Icon from '@farris/mobile-ui-vue/icon'; +import Search from '@farris/mobile-ui-vue/search'; +import Popup from '@farris/mobile-ui-vue/popup'; import { FILTER_NAME, filterProps } from './filter.props'; import FilterPanel from './filter-panel.component'; import { FilterEmits } from './compositions'; diff --git a/packages/mobile-ui-vue/components/float-container/index.ts b/packages/mobile-ui-vue/components/float-container/index.ts index 3b6178781c26d2707068a7a7d96858283f454cf2..0a6b3139a450c33dd39b43cea7fa34bf42f3d1d5 100644 --- a/packages/mobile-ui-vue/components/float-container/index.ts +++ b/packages/mobile-ui-vue/components/float-container/index.ts @@ -1,6 +1,6 @@ import { Plugin } from 'vue'; -import { withInstall } from '@components/common'; -import { propsResolver } from './src/float-container.props'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; +import { propsResolverGenerator } from './src/float-container.props'; import FloatContainerInstallless from './src/float-container.component'; import FloatContainerDesign from './src/designer/float-container.design.component'; @@ -10,18 +10,18 @@ const FloatContainer = withInstall(FloatContainerInstallless); FloatContainer.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record, resolverMap: Record,registerContext: RegisterContext ) => { componentMap[FLOAT_CONTAINER_REGISTERED_NAME] = FloatContainer; - propsResolverMap[FLOAT_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[FLOAT_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; FloatContainer.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record,registerContext: RegisterContext ) => { componentMap[FLOAT_CONTAINER_REGISTERED_NAME] = FloatContainerDesign; - propsResolverMap[FLOAT_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[FLOAT_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; diff --git a/packages/mobile-ui-vue/components/float-container/src/designer/float-container.design.component.tsx b/packages/mobile-ui-vue/components/float-container/src/designer/float-container.design.component.tsx index 959f7cde474d1ce06d7ea676d7f4a8f490a1df77..9188260bc53fe2801b6b1bf536db575c7004b7fe 100644 --- a/packages/mobile-ui-vue/components/float-container/src/designer/float-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/float-container/src/designer/float-container.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, onMounted, ref } from 'vue'; import { FloatContainerProps, floatContainerProps } from '../float-container.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FmFloatContainerDesign', diff --git a/packages/mobile-ui-vue/components/float-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/float-container/src/designer/use-designer-rules.ts index 9053cbf3e7e8ec8f7f5c6ba9532a709f695b06c5..aba42f8187a64045363deb98b8ffe062b9eddad9 100644 --- a/packages/mobile-ui-vue/components/float-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/float-container/src/designer/use-designer-rules.ts @@ -15,8 +15,8 @@ * limitations under the License. */ import { ref } from "vue"; -import { ComponentSchema, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { ComponentSchema, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; import { FloatContainerProperty } from "../property-config/float-container.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/float-container/src/float-container.component.tsx b/packages/mobile-ui-vue/components/float-container/src/float-container.component.tsx index ebb255014a8ae2bbcf7a1879e0bd6ad1ed66f99e..159f9933d50375f86b6d34ab12629f24494eb9a2 100644 --- a/packages/mobile-ui-vue/components/float-container/src/float-container.component.tsx +++ b/packages/mobile-ui-vue/components/float-container/src/float-container.component.tsx @@ -1,5 +1,5 @@ import { SetupContext, defineComponent, computed } from 'vue'; -import { useBem } from '@components/common/index'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { FLOAT_CONTAINER_NAME, floatContainerProps, FloatContainerProps } from './float-container.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/float-container/src/float-container.props.ts b/packages/mobile-ui-vue/components/float-container/src/float-container.props.ts index e3d5c77dd14d7630c938d978a13131156b7b2415..c5da6f3797f321b4fc649d7d07c57954adc00756 100644 --- a/packages/mobile-ui-vue/components/float-container/src/float-container.props.ts +++ b/packages/mobile-ui-vue/components/float-container/src/float-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import floatContainerSchema from './schema/float-container.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -12,7 +12,7 @@ export const floatContainerProps = { export type FloatContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( floatContainerProps, floatContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/float-container/src/property-config/float-container.property-config.ts b/packages/mobile-ui-vue/components/float-container/src/property-config/float-container.property-config.ts index 3ad2a788fe1dc092c4ed177813f09a7097237a1b..fd661a5ff67602d28c5c7512f8a0f92a71b91cde 100644 --- a/packages/mobile-ui-vue/components/float-container/src/property-config/float-container.property-config.ts +++ b/packages/mobile-ui-vue/components/float-container/src/property-config/float-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class FloatContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/form-item/index.ts b/packages/mobile-ui-vue/components/form-item/index.ts index 9257fcac6a21acbd481ae0a150a7050f381ecff8..3a7475c17aca0605f87ac7d20ebc14fb7f760e21 100644 --- a/packages/mobile-ui-vue/components/form-item/index.ts +++ b/packages/mobile-ui-vue/components/form-item/index.ts @@ -1,5 +1,5 @@ -import { withInstall } from '@components/common'; -import { propsResolver } from './src/form-item.props'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; +import { propsResolverGenerator } from './src/form-item.props'; import FormItemInstallless from './src/form-item.component'; import FormItemDesign from './src/designer/form-item.design.component'; @@ -7,21 +7,8 @@ const FORM_ITEM_REGISTERED_NAME = 'form-group'; const FormItem = withInstall(FormItemInstallless); -FormItem.register = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[FORM_ITEM_REGISTERED_NAME] = FormItem; - propsResolverMap[FORM_ITEM_REGISTERED_NAME] = propsResolver; -}; - -FormItem.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[FORM_ITEM_REGISTERED_NAME] = FormItemDesign; - propsResolverMap[FORM_ITEM_REGISTERED_NAME] = propsResolver; -}; +withRegister(FormItem, { name: FORM_ITEM_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(FormItem, { name: FORM_ITEM_REGISTERED_NAME, propsResolverGenerator, designerComponent: FormItemDesign }); export * from './src/form-item.props'; export { FormItem }; diff --git a/packages/mobile-ui-vue/components/form-item/src/composition/use-form-item-label.ts b/packages/mobile-ui-vue/components/form-item/src/composition/use-form-item-label.ts index ec6c22c7bb77baa318b2acb3339072a916514958..392a95c24ed864d4ea7ee54f62699be2661b0169 100644 --- a/packages/mobile-ui-vue/components/form-item/src/composition/use-form-item-label.ts +++ b/packages/mobile-ui-vue/components/form-item/src/composition/use-form-item-label.ts @@ -1,5 +1,5 @@ import { computed, toRefs } from 'vue'; -import { addUnit } from '@components/common'; +import { addUnit } from '@farris/mobile-ui-vue/common'; import { FormContext } from '../types'; import { FormItemProps } from '../form-item.props'; import { UseFormItemLabel } from './types'; diff --git a/packages/mobile-ui-vue/components/form-item/src/consts.ts b/packages/mobile-ui-vue/components/form-item/src/consts.ts index b88518838ebab697fe4568fb2194896a812c0e2f..8224f193cceaf8efc8d540d66a2e612cb3edde9c 100644 --- a/packages/mobile-ui-vue/components/form-item/src/consts.ts +++ b/packages/mobile-ui-vue/components/form-item/src/consts.ts @@ -1,5 +1,5 @@ import { InjectionKey } from 'vue'; -import { ParentProvideValue } from '@components/common'; +import { ParentProvideValue } from '@farris/mobile-ui-vue/common'; import { FormContext, FormItemContext } from './types'; export const FORM_KEY: InjectionKey> = Symbol('FORM'); diff --git a/packages/mobile-ui-vue/components/form-item/src/designer/form-item-use-designer-rules.ts b/packages/mobile-ui-vue/components/form-item/src/designer/form-item-use-designer-rules.ts index 305fcbdbd8563a200b3cbd48f9f267f544724ee1..6a9344e98d4b39267438febafef14c44e12211fc 100644 --- a/packages/mobile-ui-vue/components/form-item/src/designer/form-item-use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/form-item/src/designer/form-item-use-designer-rules.ts @@ -1,4 +1,4 @@ -import { DesignerItemContext, DesignerHostService, UseDesignerRules, DesignerComponentInstance, ComponentSchema } from "@/components/designer-canvas"; +import { DesignerItemContext, DesignerHostService, UseDesignerRules, DesignerComponentInstance, ComponentSchema } from "@farris/mobile-ui-vue/common"; import { FormGroupProperty } from "../property-config/form-group.property-config"; export function useDesignerRulesForFormItem(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/form-item/src/designer/form-item.design.component.tsx b/packages/mobile-ui-vue/components/form-item/src/designer/form-item.design.component.tsx index 09d05afe1328fbeb5383b74633ea1f4034e57850..c4af84c0f3d34afa12c5821fdcaed902769c4750 100644 --- a/packages/mobile-ui-vue/components/form-item/src/designer/form-item.design.component.tsx +++ b/packages/mobile-ui-vue/components/form-item/src/designer/form-item.design.component.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ import { computed, defineComponent, inject, onMounted, ref, SetupContext, watch } from 'vue'; -import { useBem } from '@components/common'; -import FmCell from '@components/cell'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import FmCell from '@farris/mobile-ui-vue/cell'; import { FORM_ITEM_NAME, FormItemProps, formItemProps } from '../form-item.props'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; -import { propertyConfigSchemaMap } from '@/components/dynamic-resolver'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; +import { propertyConfigSchemaMapForDesigner } from '@farris/mobile-ui-vue/dynamic-resolver'; import { useDesignerRulesForFormItem } from './form-item-use-designer-rules'; -import { useTypeResolverDesign } from '@/components/dynamic-form/src/composition/use-type-resolver-design'; +import { useTypeResolverDesign } from '@farris/mobile-ui-vue/dynamic-resolver'; export default defineComponent({ name: 'FmFormItemDesign', @@ -94,7 +94,7 @@ export default defineComponent({ elementRef.value.componentInstance = componentInstance; componentInstance.value.getPropConfig = (...args) => { - let propertyConfigSchema = propertyConfigSchemaMap[props.editor.type]; + let propertyConfigSchema = propertyConfigSchemaMapForDesigner[props.editor.type]; if (propertyConfigSchema && Object.keys(propertyConfigSchema).length === 0 && editorRef && editorRef.value && editorRef.value?.getPropConfig) { propertyConfigSchema = editorRef.value.getPropConfig(...args, componentInstance.value); } diff --git a/packages/mobile-ui-vue/components/form-item/src/designer/response-form-use-designer-rules.ts b/packages/mobile-ui-vue/components/form-item/src/designer/response-form-use-designer-rules.ts index c6badd84df8effccc8b033158cfb9e03d5543cc5..f018052888428dc1a17a03236f34f700a3808d2d 100644 --- a/packages/mobile-ui-vue/components/form-item/src/designer/response-form-use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/form-item/src/designer/response-form-use-designer-rules.ts @@ -1,6 +1,6 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerHostService, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; -import { getSchemaByType } from "@/components/dynamic-resolver"; +import { ComponentSchema, DesignerComponentInstance, DesignerHostService, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; +import { getSchemaByTypeForDesigner } from "@farris/mobile-ui-vue/dynamic-resolver"; import { ref } from "vue"; import { ResponseFormProperty } from "../property-config/response-form.property-config"; @@ -58,14 +58,14 @@ export function useDesignerRules(designItemContext: DesignerItemContext, designe // 控件若有绑定信息,则根据绑定信息创建控件 if (resolveContext.bindingSourceContext?.entityFieldNode) { const controlCreatorUtils = designerHostService?.controlCreatorUtils; - formGroupElementSchema = controlCreatorUtils.setFormFieldProperty(resolveContext.bindingSourceContext?.entityFieldNode, componentSchema.type); + formGroupElementSchema = controlCreatorUtils.setFormFieldProperty(resolveContext.bindingSourceContext?.entityFieldNode, componentSchema?.type); } else { - formGroupElementSchema = getSchemaByType('form-item') as ComponentSchema; + formGroupElementSchema = getSchemaByTypeForDesigner('form-group') as ComponentSchema; formGroupElementSchema.editor = componentSchema; formGroupElementSchema.label = label; } - syncFieldToViewModel(resolveContext, componentSchema.type); + syncFieldToViewModel(resolveContext, componentSchema?.type); return formGroupElementSchema; } diff --git a/packages/mobile-ui-vue/components/form-item/src/designer/response-form.design.component.tsx b/packages/mobile-ui-vue/components/form-item/src/designer/response-form.design.component.tsx index 47b8f94a3998ff0e117264815dc91776bff02982..eec6f5d64debe8a88b322c6633e7d022ea284eff 100644 --- a/packages/mobile-ui-vue/components/form-item/src/designer/response-form.design.component.tsx +++ b/packages/mobile-ui-vue/components/form-item/src/designer/response-form.design.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent, inject, onMounted, ref } from 'vue'; import { useDesignerRules } from './response-form-use-designer-rules'; import { FormProps, formProps } from '../form.props'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FResponseFormDesign', diff --git a/packages/mobile-ui-vue/components/form-item/src/form-item.component.tsx b/packages/mobile-ui-vue/components/form-item/src/form-item.component.tsx index 825fb7bf5f66b305cc8f8f6e9d1b391f9f78926a..4dfb55249a2d814a627a1a494c58829b571c570b 100644 --- a/packages/mobile-ui-vue/components/form-item/src/form-item.component.tsx +++ b/packages/mobile-ui-vue/components/form-item/src/form-item.component.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import { computed, defineComponent, SetupContext } from 'vue'; -import { useParentContext, useBem } from '@components/common'; -import FmCell from '@components/cell'; +import { useParentContext, useBem } from '@farris/mobile-ui-vue/common'; +import FmCell from '@farris/mobile-ui-vue/cell'; import { FORM_KEY } from './consts'; import { FormContext, FormItemContext } from './types'; diff --git a/packages/mobile-ui-vue/components/form-item/src/form-item.props.ts b/packages/mobile-ui-vue/components/form-item/src/form-item.props.ts index 2952c339967d50a92dd1ea98c79058ce86aee3bc..7c8c29a4f9a5111508d596715ba0a558af39c943 100644 --- a/packages/mobile-ui-vue/components/form-item/src/form-item.props.ts +++ b/packages/mobile-ui-vue/components/form-item/src/form-item.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { createPropsResolver } from '@components/dynamic-resolver'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import formItemSchema from './schema/form-item.schema.json'; import { schemaMapper } from './schema/form-item-schema-mapper'; import { schemaResolver } from './schema/form-item-schema-resolver'; @@ -43,7 +43,7 @@ export const formItemProps = { export type FormItemProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( formItemProps, formItemSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/form-item/src/form.component.tsx b/packages/mobile-ui-vue/components/form-item/src/form.component.tsx index cd74b2d15d2dc88a55a2ad6bde2f4f4ac7e41a5d..10f2b4d95b30ee1a5b9822b45d2e569b5ea7c08e 100644 --- a/packages/mobile-ui-vue/components/form-item/src/form.component.tsx +++ b/packages/mobile-ui-vue/components/form-item/src/form.component.tsx @@ -15,11 +15,11 @@ */ import { defineComponent, SetupContext } from 'vue'; -import { useBem, preventDefault, useChildrenContexts } from '@components/common'; -import { useFormValidation, useFormContext } from '@components/form-item/src/composition'; -import { FORM_KEY } from '@components/form-item/src/consts'; +import { useBem, preventDefault, useChildrenContexts } from '@farris/mobile-ui-vue/common'; +import { useFormValidation, useFormContext } from '@farris/mobile-ui-vue/form-item/src/composition'; +import { FORM_KEY } from '@farris/mobile-ui-vue/form-item/src/consts'; -import { FormContext, FormItemContext } from '@components/form-item/src/types'; +import { FormContext, FormItemContext } from '@farris/mobile-ui-vue/form-item/src/types'; import { FORM_NAME, formProps, FormProps } from './form.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/form-item/src/form.props.ts b/packages/mobile-ui-vue/components/form-item/src/form.props.ts index f5000a12301454a2eb99ba169120305b09b677e6..c0c8a0b2b072cf2330133d1c455c591700ea0328 100644 --- a/packages/mobile-ui-vue/components/form-item/src/form.props.ts +++ b/packages/mobile-ui-vue/components/form-item/src/form.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { LabelAlign, ContentAlign, FormData } from '@components/form-item/src/types'; -import { ValidationRules } from '@components/form-item/src/validation'; -import { createPropsResolver } from '@components/dynamic-resolver'; +import { LabelAlign, ContentAlign, FormData } from '@farris/mobile-ui-vue/form-item/src/types'; +import { ValidationRules } from '@farris/mobile-ui-vue/form-item/src/validation'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import formSchema from './schema/form.schema.json'; import { schemaMapper } from './schema/form-schema-mapper'; import { schemaResolver } from './schema/form-schema-resolver'; @@ -38,7 +38,7 @@ export const formProps = { export type FormProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( formProps, formSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/form-item/src/property-config/form-group.property-config.ts b/packages/mobile-ui-vue/components/form-item/src/property-config/form-group.property-config.ts index 46c7790226cc47b929729384b0c75c52242b5d2c..a09b668a00e703074b130b1c31e39ae0cc386e09 100644 --- a/packages/mobile-ui-vue/components/form-item/src/property-config/form-group.property-config.ts +++ b/packages/mobile-ui-vue/components/form-item/src/property-config/form-group.property-config.ts @@ -1,5 +1,5 @@ -import { DesignerComponentInstance } from "@/components/designer-canvas"; -import { BaseControlProperty } from "@/components/property-panel"; +import { DesignerComponentInstance } from "@farris/mobile-ui-vue/common"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class FormGroupProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/form-item/src/property-config/response-form.property-config.ts b/packages/mobile-ui-vue/components/form-item/src/property-config/response-form.property-config.ts index d035881f762987cfe7844b1dd255dbc0e1f6e9cb..7b4fee85c2deb1095a1df01f0e5693ffceeda58b 100644 --- a/packages/mobile-ui-vue/components/form-item/src/property-config/response-form.property-config.ts +++ b/packages/mobile-ui-vue/components/form-item/src/property-config/response-form.property-config.ts @@ -1,5 +1,5 @@ -import { DesignerComponentInstance } from "@/components/designer-canvas"; -import { BaseControlProperty } from "@/components/property-panel"; +import { DesignerComponentInstance } from "@farris/mobile-ui-vue/common"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class ResponseFormProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/form-item/src/schema/form-item.schema.json b/packages/mobile-ui-vue/components/form-item/src/schema/form-item.schema.json index 57c71e280332e102addfa3e3ea1d3a983d15110b..82f34c27ccf448a6c0bab0dc8eee66cc390b2758 100644 --- a/packages/mobile-ui-vue/components/form-item/src/schema/form-item.schema.json +++ b/packages/mobile-ui-vue/components/form-item/src/schema/form-item.schema.json @@ -62,7 +62,5 @@ "editor" ], "ignore": [ - "id", - "type" ] } \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/form-item/src/validation/validation.service.ts b/packages/mobile-ui-vue/components/form-item/src/validation/validation.service.ts index 18682fc39f5525069c716da680623f1474ccfee3..e623bb3c3cc9e4b30e4a045cd9e52487918b81bc 100644 --- a/packages/mobile-ui-vue/components/form-item/src/validation/validation.service.ts +++ b/packages/mobile-ui-vue/components/form-item/src/validation/validation.service.ts @@ -1,4 +1,4 @@ -import { isPromise } from "@components/common"; +import { isPromise } from "@farris/mobile-ui-vue/common"; import { ValidationRule, ValidationError } from "./types"; import { ValidatorFactory } from "./validator.factory"; diff --git a/packages/mobile-ui-vue/components/form-item/src/validation/validators/custom-fn.validator.ts b/packages/mobile-ui-vue/components/form-item/src/validation/validators/custom-fn.validator.ts index 6ffd1c4bb31fe51200725c097a691557c1b9fcd4..c6931ab6c77d53ed674789d14508b97b8ef2cf5d 100644 --- a/packages/mobile-ui-vue/components/form-item/src/validation/validators/custom-fn.validator.ts +++ b/packages/mobile-ui-vue/components/form-item/src/validation/validators/custom-fn.validator.ts @@ -1,4 +1,4 @@ -import { isFunction, isPromise } from "@components/common"; +import { isFunction, isPromise } from "@farris/mobile-ui-vue/common"; import { ValidationError, ValidationRule, Validator } from '../types'; /** diff --git a/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-max-value.validator.ts b/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-max-value.validator.ts index 2fe0cc558e5de07f8be01b35f5cf7b77a310b30c..4f670f90d466d999feb4ce8045fe16ada4917ead 100644 --- a/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-max-value.validator.ts +++ b/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-max-value.validator.ts @@ -1,5 +1,5 @@ import { ValidationError, ValidationRule, Validator } from '../types'; -import { compareDate } from '@components/common'; +import { compareDate } from '@farris/mobile-ui-vue/common'; /** * 正则验证器 diff --git a/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-min-value.validator.ts b/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-min-value.validator.ts index dcea36fc58c30dfc1dcbcafb9bc90bac8b84dcce..793949d53eb3073a7453221f5f9cce90e62e1779 100644 --- a/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-min-value.validator.ts +++ b/packages/mobile-ui-vue/components/form-item/src/validation/validators/date-min-value.validator.ts @@ -1,5 +1,5 @@ import { ValidationError, ValidationRule, Validator } from '../types'; -import { compareDate } from '@components/common'; +import { compareDate } from '@farris/mobile-ui-vue/common'; /** * 正则验证器 diff --git a/packages/mobile-ui-vue/components/form/index.ts b/packages/mobile-ui-vue/components/form/index.ts index f7cb3ad778c858201bedc13485a6cd933cfd6d3e..b91f4f8ab504128ee10444cb60901b63ec843091 100644 --- a/packages/mobile-ui-vue/components/form/index.ts +++ b/packages/mobile-ui-vue/components/form/index.ts @@ -15,31 +15,18 @@ * limitations under the License. */ import { Plugin } from 'vue'; -import { withInstall } from '@components/common'; -import { propsResolver } from '@components/form-item/src/form.props'; -import FormInstallless from '@components/form-item/src/form.component'; -import FormInstalllessDesign from '../form-item/src/designer/response-form.design.component'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; +import { propsResolverGenerator } from '@farris/mobile-ui-vue/form-item/src/form.props'; +import FormInstallless from '@farris/mobile-ui-vue/form-item/src/form.component'; +import FormDesign from '../form-item/src/designer/response-form.design.component'; const FORM_REGISTERED_NAME = 'form'; const Form = withInstall(FormInstallless); -Form.register = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[FORM_REGISTERED_NAME] = Form; - propsResolverMap[FORM_REGISTERED_NAME] = propsResolver; -}; +withRegister(Form, { name: FORM_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(Form, { name: FORM_REGISTERED_NAME, propsResolverGenerator, designerComponent: FormDesign }); -Form.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[FORM_REGISTERED_NAME] = FormInstalllessDesign; - propsResolverMap[FORM_REGISTERED_NAME] = propsResolver; -}; - -export * from '@components/form-item/src/form.props'; +export * from '@farris/mobile-ui-vue/form-item/src/form.props'; export { Form }; export default Form as typeof Form & Plugin; diff --git a/packages/mobile-ui-vue/components/icon/index.ts b/packages/mobile-ui-vue/components/icon/index.ts index 2f67a8759f8846ca168590d51f32c85654af9cf7..385bbc9295a1e9715c1b07259a1e470f698d4d6e 100644 --- a/packages/mobile-ui-vue/components/icon/index.ts +++ b/packages/mobile-ui-vue/components/icon/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import IconInstallless from './src/icon.component'; const Icon = withInstall(IconInstallless); diff --git a/packages/mobile-ui-vue/components/icon/src/icon.component.tsx b/packages/mobile-ui-vue/components/icon/src/icon.component.tsx index 98f0c4797fa079ab36187be71e1581d4b1d090ec..c0981a693204712537692722fd1d96c740d8eb6c 100644 --- a/packages/mobile-ui-vue/components/icon/src/icon.component.tsx +++ b/packages/mobile-ui-vue/components/icon/src/icon.component.tsx @@ -15,7 +15,7 @@ */ import { defineComponent, computed, CSSProperties, ComputedRef, SetupContext } from 'vue'; -import { addUnit } from '@components/common'; +import { addUnit } from '@farris/mobile-ui-vue/common'; import { IconProps, iconProps } from './icon.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/index.ts b/packages/mobile-ui-vue/components/index.ts index 80654fb44c81b2ef72aa7b99ee8c07d57b0bafe7..c9268ed1ad066f652e5752800fcd71bd0fcc81d7 100644 --- a/packages/mobile-ui-vue/components/index.ts +++ b/packages/mobile-ui-vue/components/index.ts @@ -31,7 +31,7 @@ import { TimePicker,TimePickerPanel } from './time-picker'; import Loading from './loading'; import PullRefresh from './pull-refresh'; import List from './list'; -import { ListView } from './list-view'; +import ListView from './list-view'; import TabBar from "./tab-bar"; import SwipeCell from './swipe-cell'; import ActionSheet from './action-sheet'; @@ -48,13 +48,9 @@ import FloatContainer from './float-container'; import Filter from './filter'; import * as Utils from './common/src/utils'; -import Modal from './modal'; import DynamicView from './dynamic-view'; -import FDesignerCanvas from './designer-canvas'; - export * from './register'; export * from './designer'; -export { schemaMap } from './dynamic-resolver'; export { type DynamicViewContext, DYNAMIC_VIEW_CONTEXT, DefaultDynamicViewContext } from './dynamic-view'; const components = [ @@ -110,10 +106,7 @@ const components = [ Component, ContentContainer, FloatContainer, - - Modal, - DynamicView, - FDesignerCanvas + DynamicView ]; const install = (app: App): void => { @@ -176,9 +169,7 @@ export { FloatContainer, Utils, - Modal, DynamicView, - FDesignerCanvas }; export default { diff --git a/packages/mobile-ui-vue/components/input-group/index.ts b/packages/mobile-ui-vue/components/input-group/index.ts index 30385677fe3df8f3ebe6ea0593bbe157e94b3ce8..e7494d76fdb338d3f11647902a7b2dd00893dc67 100644 --- a/packages/mobile-ui-vue/components/input-group/index.ts +++ b/packages/mobile-ui-vue/components/input-group/index.ts @@ -1,5 +1,5 @@ -import { withInstall } from '@components/common'; -import { propsResolver } from './src/input-group.props'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; +import { propsResolverGenerator } from './src/input-group.props'; import InputGroupInstallless from './src/input-group.component'; import InputGroupDesign from './src/designer/input-group.design.component'; @@ -7,21 +7,8 @@ const INPUT_GROUP_REGISTERED_NAME = 'input-group'; const InputGroup = withInstall(InputGroupInstallless); -InputGroup.register = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[INPUT_GROUP_REGISTERED_NAME] = InputGroup; - propsResolverMap[INPUT_GROUP_REGISTERED_NAME] = propsResolver; -}; - -InputGroup.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[INPUT_GROUP_REGISTERED_NAME] = InputGroupDesign; - propsResolverMap[INPUT_GROUP_REGISTERED_NAME] = propsResolver; -}; +withRegister(InputGroup, { name: INPUT_GROUP_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(InputGroup, { name: INPUT_GROUP_REGISTERED_NAME, propsResolverGenerator, designerComponent: InputGroupDesign }); export * from './src/input-group.props'; export * from './src/types'; diff --git a/packages/mobile-ui-vue/components/input-group/src/composition/use-input-state.ts b/packages/mobile-ui-vue/components/input-group/src/composition/use-input-state.ts index 6f1fe83499db832b598fddf5f4c6aa499a6fb438..624df23a19d8fa4461ca94135a427a38216a8571 100644 --- a/packages/mobile-ui-vue/components/input-group/src/composition/use-input-state.ts +++ b/packages/mobile-ui-vue/components/input-group/src/composition/use-input-state.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { Ref, computed, ref, watch } from 'vue'; -import { isFunction } from '@components/common'; +import { isFunction } from '@farris/mobile-ui-vue/common'; import { useCommon } from './use-common'; import { useNumber } from './use-number'; import { useTextarea } from './use-textarea'; diff --git a/packages/mobile-ui-vue/components/input-group/src/composition/use-number.ts b/packages/mobile-ui-vue/components/input-group/src/composition/use-number.ts index 6b842a9eb482bc71c04431301fbbb04d1ed9da7b..98ff4314120d3f4415f1328e7abb4a335d56eacc 100644 --- a/packages/mobile-ui-vue/components/input-group/src/composition/use-number.ts +++ b/packages/mobile-ui-vue/components/input-group/src/composition/use-number.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { InputProps } from '../input-group.props'; -import { formatToNumber, isDef, parseFloat } from '@components/common'; +import { formatToNumber, isDef, parseFloat } from '@farris/mobile-ui-vue/common'; import { Instance } from './types'; import { InputTypeMap, InputUpdateOn, InputUpdateOnMap } from '../types'; diff --git a/packages/mobile-ui-vue/components/input-group/src/composition/use-textarea.ts b/packages/mobile-ui-vue/components/input-group/src/composition/use-textarea.ts index f65bcdf4ff8bbbfdc5cad6117c346737972b65d7..62f5441e55d20bd1ac2d062df55ad3953713fd95 100644 --- a/packages/mobile-ui-vue/components/input-group/src/composition/use-textarea.ts +++ b/packages/mobile-ui-vue/components/input-group/src/composition/use-textarea.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { Ref, onMounted, unref } from 'vue'; -import { addUnit } from '@components/common'; +import { addUnit } from '@farris/mobile-ui-vue/common'; import { InputProps } from '../input-group.props'; import { Instance } from './types'; import { useCommon } from './use-common'; @@ -27,7 +27,7 @@ export function useTextarea(props: InputProps, inputRef: Ref { const input = unref(inputRef); - if (!(props.type === InputTypeMap.textarea && props.autoSize) || !input) { + if (!(props.type === InputTypeMap.textarea && props.autoHeight) || !input) { return; } diff --git a/packages/mobile-ui-vue/components/input-group/src/designer/input-group.design.component.tsx b/packages/mobile-ui-vue/components/input-group/src/designer/input-group.design.component.tsx index e4f7d71dfe269b73631b5bc6cb1b3fcda57116fc..c61c695f5f842fb41901ed5c065145c95c137a3c 100644 --- a/packages/mobile-ui-vue/components/input-group/src/designer/input-group.design.component.tsx +++ b/packages/mobile-ui-vue/components/input-group/src/designer/input-group.design.component.tsx @@ -15,9 +15,11 @@ * limitations under the License. */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; -import { InputGroup, InputProps, inputProps } from '../..'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; import { useInputGroupDesignerRules } from './use-designer-rules'; +import { InputProps, inputProps } from '../input-group.props'; +import { InputGroup } from '@farris/mobile-ui-vue'; + export default defineComponent({ name: 'FmInputGroupDesign', diff --git a/packages/mobile-ui-vue/components/input-group/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/input-group/src/designer/use-designer-rules.ts index f2aa639178505907991663094b64efd116166620..9de599c140bd3205e8759f271a8c7c40a93be7c4 100644 --- a/packages/mobile-ui-vue/components/input-group/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/input-group/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { InputGroupProperty } from "../property-config/input-group.property-config"; export function useInputGroupDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/input-group/src/input-group.component.tsx b/packages/mobile-ui-vue/components/input-group/src/input-group.component.tsx index 292eb1adb46db201ebe0a359c69bb8104457fb6a..06291c23313e4b6db06d78fb67f9c0a4ac089d8e 100644 --- a/packages/mobile-ui-vue/components/input-group/src/input-group.component.tsx +++ b/packages/mobile-ui-vue/components/input-group/src/input-group.component.tsx @@ -15,8 +15,8 @@ */ import { SetupContext, computed, defineComponent } from 'vue'; -import { preventDefault, stopPropagation, useBem } from '@components/common'; -import { Icon } from '@components/icon'; +import { preventDefault, stopPropagation, useBem } from '@farris/mobile-ui-vue/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; import { INPUT_NAME, InputProps, inputProps } from './input-group.props'; import { useInputState, useInputEvent, useInputExpose } from './composition'; import { InputTypeMap } from './types'; @@ -55,7 +55,7 @@ export default defineComponent({ placeholder: placeholder.value, disabled: props.disabled, readonly: props.readonly || !props.editable, - maxlength: props.maxlength, + maxLength: props.maxLength, onChange: stopPropagation, }; }); @@ -109,9 +109,9 @@ export default defineComponent({ const renderWordLimit = () => props.showWordLimit && - props.maxlength && ( + props.maxLength && (
- {String(innerValue.value).length}/{props.maxlength} + {String(innerValue.value).length}/{props.maxLength}
); diff --git a/packages/mobile-ui-vue/components/input-group/src/input-group.props.ts b/packages/mobile-ui-vue/components/input-group/src/input-group.props.ts index bd08263d37caa7a6a442c75ecf24e1c6321b66e8..13a26c3e1d64570454e37a03af9389da8104db64 100644 --- a/packages/mobile-ui-vue/components/input-group/src/input-group.props.ts +++ b/packages/mobile-ui-vue/components/input-group/src/input-group.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes, PropType } from 'vue'; import { InputTextAlign, InputTextAlignMap, InputType, InputTypeMap, InputUpdateOn } from "./types"; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import inputGroupSchema from './schema/input-group.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -36,7 +36,7 @@ export const inputCommonProps = { formatter: { type: Function as PropType<(v: string | number) => string | number> }, - maxlength: { type: Number, default: undefined }, + maxLength: { type: Number, default: undefined }, bodyClass: { type: String, default: '' }, }; @@ -50,7 +50,7 @@ const inputNumberProps = { }; const inputTextAreaProps = { - autoSize: { type: Boolean, default: undefined }, + autoHeight: { type: Boolean, default: undefined }, rows: { type: Number, default: undefined }, @@ -69,7 +69,7 @@ export const inputProps = { export type InputCommonProps = ExtractPropTypes; export type InputProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( inputProps, inputGroupSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/input-group/src/property-config/converter/input.converter.ts b/packages/mobile-ui-vue/components/input-group/src/property-config/converter/input.converter.ts new file mode 100644 index 0000000000000000000000000000000000000000..183b249eac93868f063993402382e2ed7c7de4b0 --- /dev/null +++ b/packages/mobile-ui-vue/components/input-group/src/property-config/converter/input.converter.ts @@ -0,0 +1,86 @@ +import { ComponentSchema } from "@farris/mobile-ui-vue/common"; +import { PropertyConverter, SchemaService } from "../../../../dynamic-resolver/src/types"; + +const inputFormatValidationTypes = [ + { key: 'none', value: '无'}, + { key: 'cellNumber', value: '手机号' }, + { key: 'tel', value: '座机号/传真号' }, + { key: 'telOrCell', value: '手机号/座机号/传真号' }, + { key: 'postCode', value: '邮编' }, + { key: 'email', value: '电子邮箱' }, + { key: 'idCode', value: '身份证号' }, + { key: 'carCode', value: '车牌号' }, + { key: 'subjectCode', value: '10位数字会计科目代码' }, + { key: 'custom', value: '自定义' }, +]; + +function getInputExByInputType(inputTypeKey: string): string { + switch (inputTypeKey) { + case 'none': { + return ''; + } + case 'cellNumber': { + return '^1[0-9]{10}$'; + } + case 'tel': { + return '^(0[0-9]{2,3}\\-)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?$'; + } + case 'telOrCell': { + return '^(0[0-9]{2,3}\\-)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?$|^1[0-9]{10}$'; + } + case 'postCode': { + return '^[1-9]\\d{5}(?!\\d)$'; + } + case 'workCode': { + return '^\\d{8}$'; + } + case 'email': { + return '^[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z]{2,5}$'; + } + case 'idCode': { + return '^[1-9]\\d{5}[1-9]\\d{3}((0[1-9])|(1[0-2]))(0[1-9]|([1|2][0-9])|3[0-1])((\\d{4})|\\d{3}X)$'; + } + case 'carCode': { + return '[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}'; + } + case 'carCodeNew': { + return '[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))'; + } + case 'subjectCode': { + return '^\\d{10}$'; + } + } + return ''; +} + +function getMessage(propertyValue) { + return "请输入正确的" + inputFormatValidationTypes.find(type => type.key === propertyValue)?.value; +} +const typeConverter = { + convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { + if (!schema.editor.formatValidation) { + schema.editor.formatValidation={type:'none'}; + } + schema.editor.formatValidation.type = propertyValue; + schema.editor.formatValidation.expression = getInputExByInputType(propertyValue); + schema.editor.formatValidation.message = getMessage(propertyValue); + + }, + convertFrom: (schema: ComponentSchema, propertyKey: string, schemaService: SchemaService) => { + return schema.editor.formatValidation ? schema.editor.formatValidation[propertyKey] : schema.editor[propertyKey]; + } +} as PropertyConverter; + +const commonConverter = { + convertTo: (schema: ComponentSchema, propertyKey: string, propertyValue: any, schemaService: SchemaService) => { + if (!schema.editor.formatValidation) { + schema.editor.formatValidation={type:'none'}; + } + schema.editor.formatValidation[propertyKey] = propertyValue; + }, + convertFrom: (schema: ComponentSchema, propertyKey: string, schemaService: SchemaService) => { + return schema.editor.formatValidation ? schema.editor.formatValidation[propertyKey] : schema.editor[propertyKey]; + } +} as PropertyConverter; + +export { typeConverter, commonConverter, inputFormatValidationTypes }; diff --git a/packages/mobile-ui-vue/components/input-group/src/property-config/input-group.property-config.ts b/packages/mobile-ui-vue/components/input-group/src/property-config/input-group.property-config.ts index 34037ac64d86a5db5c201f995969a8abb982bb08..7cfd630ed8035c2beb21dee5fdb70f3ac0f62998 100644 --- a/packages/mobile-ui-vue/components/input-group/src/property-config/input-group.property-config.ts +++ b/packages/mobile-ui-vue/components/input-group/src/property-config/input-group.property-config.ts @@ -1,34 +1,91 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { DesignerComponentInstance, InputBaseProperty } from '@farris/mobile-ui-vue/common'; +import { + typeConverter, + commonConverter, + inputFormatValidationTypes +} from './converter/input.converter'; export class InputGroupProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } + public getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { + super.getPropertyConfig(propertyData, componentInstance); + // 输入格式校验 + this.propertyConfig.categories['formatValidation'] = this.getFormatValidation(propertyData); + return this.propertyConfig; + } + + getEditorProperties(propertyData: any) { + const self = this; + const editorProperties = self.getComponentConfig( + propertyData, + {}, + { + maxLength: { + description: '文本字数最大长度', + title: '最大长度', + type: 'number', + editor: { + nullable: true, + min: 0, + useThousands: false + } + } + }, + (changeObject) => { + if (!changeObject) { + return; + } + } + ); - - getEditorProperties(propertyData: any) { - const self = this; - const editorProperties = self.getComponentConfig(propertyData, { type: "radio-group" }, { - placeholder: { - description: "空值时,输入控件内的占位文本", - title: "提示文本", - type: "string" - } - }); - editorProperties['setPropertyRelates'] = function (changeObject) { - if (!changeObject) { - return; - } - switch (changeObject.propertyID) { - case 'data': { + return editorProperties; + } - break; - } - } - }; - return editorProperties; + public getFormatValidation(propertyData) { + const formatValidationSchema: any = { + title: '输入格式校验', + description: 'formatValidation', + properties: { + type: { + title: '输入类型', + type: 'enum', + description: '输入类型', + editor: { + type: 'combo-list', + textField: 'value', + valueField: 'key', + idField: 'key', + editable: false, + data: inputFormatValidationTypes + }, + refreshPanelAfterChanged: true, + $converter: typeConverter + } + } + }; + if ( + propertyData.editor.formatValidation?.type && + propertyData.editor.formatValidation?.type !== 'none' + ) { + formatValidationSchema.properties.message = { + title: '输入错误提示', + type: 'string', + description: '输入错误提示', + $converter: commonConverter + }; } + if (propertyData.editor.formatValidation?.type === 'custom') { + formatValidationSchema.properties.expression = { + title: '匹配正则', + type: 'string', + description: '匹配正则', - + $converter: commonConverter + }; + } + return formatValidationSchema; + } } diff --git a/packages/mobile-ui-vue/components/list-view/index.ts b/packages/mobile-ui-vue/components/list-view/index.ts index dc245320aec488e5eccc7b341a92d9dca5ba858d..4205610eb326d4f124e92edd620d55aeda09d648 100644 --- a/packages/mobile-ui-vue/components/list-view/index.ts +++ b/packages/mobile-ui-vue/components/list-view/index.ts @@ -1,7 +1,7 @@ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import ListViewInstallless from './src/list-view.component'; import ListViewDesign from './src/designer/list-view.design.component'; -import { propsResolver } from './src/list-view.props'; +import { propsResolverGenerator } from './src/list-view.props'; const LIST_VIEW_REGISTER_NAME = 'list-view'; const ListView = withInstall(ListViewInstallless); @@ -10,19 +10,19 @@ export * from './src/list-view.props'; ListView.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record, resolverMap: Record,registerContext: RegisterContext ) => { componentMap[LIST_VIEW_REGISTER_NAME] = ListView; - propsResolverMap[LIST_VIEW_REGISTER_NAME] = propsResolver; -}; + propsResolverMap[LIST_VIEW_REGISTER_NAME] = propsResolverGenerator(registerContext); +} ListView.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record + configresolverMap: Record,registerContext: RegisterContext ) => { componentMap[LIST_VIEW_REGISTER_NAME] = ListViewDesign; - propsResolverMap[LIST_VIEW_REGISTER_NAME] = propsResolver; -}; + propsResolverMap[LIST_VIEW_REGISTER_NAME] = propsResolverGenerator(registerContext); +} export { ListView }; diff --git a/packages/mobile-ui-vue/components/list-view/src/components/list-view-item.component.tsx b/packages/mobile-ui-vue/components/list-view/src/components/list-view-item.component.tsx index 25e7b6a3891932b5ba853285afdcc705aaf4f135..02979089547e7fd9c1f098fbdafbdb7c91f06c95 100644 --- a/packages/mobile-ui-vue/components/list-view/src/components/list-view-item.component.tsx +++ b/packages/mobile-ui-vue/components/list-view/src/components/list-view-item.component.tsx @@ -1,8 +1,8 @@ import { SetupContext, toRefs } from "vue"; import { LIST_VIEW_NAME, ListViewProps } from '../list-view.props'; import { UseData, UseSelection } from '../composition/types'; -import { useBem } from '@components/common'; -import { Checkbox } from '@components/checkbox'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { Checkbox } from '@farris/mobile-ui-vue/checkbox'; export default function ( props: ListViewProps, diff --git a/packages/mobile-ui-vue/components/list-view/src/composition/use-selection.ts b/packages/mobile-ui-vue/components/list-view/src/composition/use-selection.ts index eb97d25f80f4c8bcac96934618b748b44836f4c5..0d7f65391401a15e50de1801b0cb91c3270e3db8 100644 --- a/packages/mobile-ui-vue/components/list-view/src/composition/use-selection.ts +++ b/packages/mobile-ui-vue/components/list-view/src/composition/use-selection.ts @@ -1,7 +1,7 @@ import { SetupContext, computed, Ref, ref, watch } from 'vue'; import { ListViewProps } from '../list-view.props'; import { UseSelection, UseData } from './types'; -import { isDef } from '@components/common'; +import { isDef } from '@farris/mobile-ui-vue/common'; export function useSelection( props: ListViewProps, diff --git a/packages/mobile-ui-vue/components/list-view/src/designer/list-view.design.component.tsx b/packages/mobile-ui-vue/components/list-view/src/designer/list-view.design.component.tsx index 613a425325fa7dfee2699a2aa362be2b99ca27f8..a55e3ca50bac4b4bf2249d6dc48c2ca981846bf5 100644 --- a/packages/mobile-ui-vue/components/list-view/src/designer/list-view.design.component.tsx +++ b/packages/mobile-ui-vue/components/list-view/src/designer/list-view.design.component.tsx @@ -1,9 +1,9 @@ import { SetupContext, defineComponent, inject, onMounted, ref, computed } from 'vue'; import { LIST_VIEW_NAME, ListViewProps, listViewProps } from '../list-view.props'; import { useDesignerRules } from './use-designer-rules'; -import List from '@/components/list'; -import { useBem } from '@/components/common'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas'; +import List from '@farris/mobile-ui-vue/list'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: 'FmListViewDesign', @@ -47,7 +47,7 @@ export default defineComponent({ finished={true} >
-
+
diff --git a/packages/mobile-ui-vue/components/list-view/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/list-view/src/designer/use-designer-rules.ts index 66f9e80cd93c0d7e1fe4f3420277aeb812b78501..d2b71120a11de6ff7df62b4ab2f8fbfbac9d1aa5 100644 --- a/packages/mobile-ui-vue/components/list-view/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/list-view/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { ref } from "vue"; -import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "../../../designer-canvas/src/composition/types"; +import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { ComponentProperty } from "../property-config/component.property-config"; -import { DesignerItemContext } from "@/components/designer-canvas"; +import { DesignerItemContext } from "@farris/mobile-ui-vue/common"; export function useDesignerRules(designItemContext: DesignerItemContext,designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/list-view/src/list-view.component.tsx b/packages/mobile-ui-vue/components/list-view/src/list-view.component.tsx index a3ec5488852a54974a8002aaffc990a5481b10f7..792ddb8527b79ae3fb3327493d9c068e9d00f672 100644 --- a/packages/mobile-ui-vue/components/list-view/src/list-view.component.tsx +++ b/packages/mobile-ui-vue/components/list-view/src/list-view.component.tsx @@ -15,10 +15,10 @@ */ import { defineComponent, SetupContext, computed, withDirectives, toRefs, ref } from 'vue'; import { LIST_VIEW_NAME, listViewProps, ListViewProps } from './list-view.props'; -import { useBem, vOnLongPress } from '@components/common'; -import List from '@components/list'; -import PullRefresh from '@components/pull-refresh'; -import Button from '@components/button'; +import { useBem, vOnLongPress } from '@farris/mobile-ui-vue/common'; +import List from '@farris/mobile-ui-vue/list'; +import PullRefresh from '@farris/mobile-ui-vue/pull-refresh'; +import Button from '@farris/mobile-ui-vue/button'; import { useData } from './composition/use-data'; import { useSelection } from './composition/use-selection'; import getListViewItemRender from './components/list-view-item.component'; diff --git a/packages/mobile-ui-vue/components/list-view/src/list-view.props.ts b/packages/mobile-ui-vue/components/list-view/src/list-view.props.ts index 229a5883e355a58ddb128877eb406f084b1fbb96..26512af3ede635336bbad5f7112f933661b0d602 100644 --- a/packages/mobile-ui-vue/components/list-view/src/list-view.props.ts +++ b/packages/mobile-ui-vue/components/list-view/src/list-view.props.ts @@ -15,13 +15,12 @@ * limitations under the License. */ import { ExtractPropTypes, PropType } from 'vue'; -import { ListProps } from '@components/list'; -import { PullRefreshProps } from '@components/pull-refresh'; -import { CheckboxProps } from '@components/checkbox/src/checkbox.props'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { ListProps } from '@farris/mobile-ui-vue/list'; +import { PullRefreshProps } from '@farris/mobile-ui-vue/pull-refresh'; +import { CheckboxProps } from '@farris/mobile-ui-vue/checkbox/src/checkbox.props'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import listViewSchema from './schema/list-view.schema.json'; -import listViewPropertyConfig from './property-config/list-view.property-config.json'; import { schemaResolver } from './schema/schema-resolver'; export const LIST_VIEW_NAME = 'fm-list-view'; @@ -107,10 +106,9 @@ export interface ListViewToolbarItem { export type ListViewProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( listViewProps, listViewSchema, schemaMapper, - schemaResolver, - listViewPropertyConfig, + schemaResolver ); diff --git a/packages/mobile-ui-vue/components/list-view/src/property-config/component.property-config.ts b/packages/mobile-ui-vue/components/list-view/src/property-config/component.property-config.ts index b1ea32df73850877997edd2d900d8ac770f8bc97..1304cda2a52d2b7f4d5a3b7ebc1cb59e5f2c21ac 100644 --- a/packages/mobile-ui-vue/components/list-view/src/property-config/component.property-config.ts +++ b/packages/mobile-ui-vue/components/list-view/src/property-config/component.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class ComponentProperty extends BaseControlProperty { diff --git a/packages/mobile-ui-vue/components/list-view/src/property-config/list-view.property-config.json b/packages/mobile-ui-vue/components/list-view/src/property-config/list-view.property-config.json deleted file mode 100644 index 75c9494bb38f45b67ab5dd580d47377788251bc8..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/list-view/src/property-config/list-view.property-config.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "title": "list-view", - "description": "A Farris Component", - "type": "object", - "categories": { - "basic": { - "description": "Basic Infomation", - "title": "基本信息", - "properties": { - "id": { - "description": "组件标识", - "title": "标识", - "type": "string", - "readonly": true - }, - "type": { - "description": "组件类型", - "title": "控件类型", - "type": "string" - } - } - }, - "behavior": { - "description": "", - "title": "行为", - "properties": { - "visible": { - "description": "运行时组件是否可见", - "type": "boolean", - "title": "是否可见", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "enablePullRefresh": { - "description": "是否启用下拉刷新列表数据", - "type": "boolean", - "title": "是否启用下拉刷新", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "enableMultiSelect": { - "description": "是否启用多选功能,启用后长按列表条目进入多选状态", - "type": "boolean", - "title": "是否启用多选功能", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "multiSelect": { - "description": "是否默认处于多选状态", - "type": "boolean", - "title": "是否默认处于多选状态", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "fill": { - "description": "是否填充页面下方剩余区域", - "type": "boolean", - "title": "是否填充", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "split": { - "description": "是否在列表条目之间显示分隔线", - "type": "boolean", - "title": "是否显示分隔线", - "editor": { - "type": "combo-list", - "data": [ - { - "value": true, - "name": "是" - }, - { - "value": false, - "name": "否" - } - ] - } - }, - "emptyMessage": { - "description": "列表数据为空时显示的占位文本", - "title": "空数据提示文本", - "type": "string" - } - } - } - } -} \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/list/index.ts b/packages/mobile-ui-vue/components/list/index.ts index 76080d0f3669d3877983a68c71e17d4247a414bd..ac8bc91553cec1ca80e49038743867f180b1d460 100644 --- a/packages/mobile-ui-vue/components/list/index.ts +++ b/packages/mobile-ui-vue/components/list/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import ListInstallless from './src/list.component'; export * from './src/list.props'; diff --git a/packages/mobile-ui-vue/components/list/src/composition/use-scroll-reach-edge-check.ts b/packages/mobile-ui-vue/components/list/src/composition/use-scroll-reach-edge-check.ts index 984d69c74b60c000163bc4038c1f5f1ed8d28d81..4103b4d174fe894e4ae34cdc66c801587ce06412 100644 --- a/packages/mobile-ui-vue/components/list/src/composition/use-scroll-reach-edge-check.ts +++ b/packages/mobile-ui-vue/components/list/src/composition/use-scroll-reach-edge-check.ts @@ -1,7 +1,7 @@ import { nextTick, onMounted, Ref, ref, isRef, computed } from 'vue'; import type { ListDirection, UseScrollReachEdgeCheckOptions, UseScrollReachEdgeCheck } from './types'; -import { useScrollParent, useEventListener, useResizeObserver } from '@components/common'; -import { inBrowser, isNumber } from '@components/common'; +import { useScrollParent, useEventListener, useResizeObserver } from '@farris/mobile-ui-vue/common'; +import { inBrowser, isNumber } from '@farris/mobile-ui-vue/common'; const DEFAULT_OFFSET = 30; diff --git a/packages/mobile-ui-vue/components/list/src/list.component.tsx b/packages/mobile-ui-vue/components/list/src/list.component.tsx index 23e832dadf9d42befc1f4ec36cc3aac2c6523c93..530cd7a44edc5c2394f95226df0c113c7c9fca1a 100644 --- a/packages/mobile-ui-vue/components/list/src/list.component.tsx +++ b/packages/mobile-ui-vue/components/list/src/list.component.tsx @@ -16,8 +16,8 @@ import { defineComponent, SetupContext, ref, watch, onMounted, toRefs, computed } from 'vue'; import { LIST_NAME, listProps, ListProps } from './list.props'; import { useScrollReachEdgeCheck } from './composition/use-scroll-reach-edge-check'; -import { useBem } from '@components/common'; -import Loading from '@components/loading'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import Loading from '@farris/mobile-ui-vue/loading'; export default defineComponent({ name: LIST_NAME, diff --git a/packages/mobile-ui-vue/components/loading/index.ts b/packages/mobile-ui-vue/components/loading/index.ts index b3f4b57281397af2654c3c39d38e440b4668ee4d..9f039c347e7ed94b7168eceae82185246e9b9b9f 100644 --- a/packages/mobile-ui-vue/components/loading/index.ts +++ b/packages/mobile-ui-vue/components/loading/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import LoadingInstallless from './src/loading.component'; export * from './src/loading.props'; diff --git a/packages/mobile-ui-vue/components/loading/src/loading.component.tsx b/packages/mobile-ui-vue/components/loading/src/loading.component.tsx index 8320d90ad17b295e5ecde148224f460bd65b9a4f..a98eeb2c6178a82d3d31a04ae18e0d00caf48b3a 100644 --- a/packages/mobile-ui-vue/components/loading/src/loading.component.tsx +++ b/packages/mobile-ui-vue/components/loading/src/loading.component.tsx @@ -15,7 +15,7 @@ */ import { defineComponent, SetupContext, h, computed, toRefs } from 'vue'; import { LOADING_NAME, loadingProps, LoadingProps } from './loading.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: LOADING_NAME, diff --git a/packages/mobile-ui-vue/components/lookup/index.ts b/packages/mobile-ui-vue/components/lookup/index.ts index 63781f93d205a13c899e2c6b60d488693901a96c..f51566db69f31b3d86ab9b0093c3172a4b89e107 100644 --- a/packages/mobile-ui-vue/components/lookup/index.ts +++ b/packages/mobile-ui-vue/components/lookup/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import LookupInstallless from './src/lookup.component'; import { LOOKUP_HTTP_SERVICE_TOKEN } from './src/lookup.props'; import { LookupDisplayType } from './src/composition'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/content-list-nav.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/content-list-nav.component.tsx index c56c9007392849ea7321acee2ad5eac8a178c6a8..25033e37243970022620ba77051ab4349d45ec7f 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/content-list-nav.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/content-list-nav.component.tsx @@ -1,6 +1,6 @@ import { defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import List from '@/components/list'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import List from '@farris/mobile-ui-vue/list'; import { ListDataItem, useLookupPanelState, useRenderComponent } from '../composition'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/content-list-tree.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/content-list-tree.component.tsx index 84b1583b0d7de8434c5107abb75c99f23d854f59..63de77f36c0908c55a2c73981721acbee35a20ed 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/content-list-tree.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/content-list-tree.component.tsx @@ -1,6 +1,6 @@ import { defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import List from '@/components/list'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import List from '@farris/mobile-ui-vue/list'; import { ListDataItem, useLookupPanelState, useRenderComponent } from '../composition'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/content-list.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/content-list.component.tsx index e698a366fceeaf7766fcabdfe941621ff68e6bd2..72c4f3c5417ea435b5dfaf06d18873387ea6e813 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/content-list.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/content-list.component.tsx @@ -1,6 +1,6 @@ import { defineComponent } from 'vue'; -import List from '@/components/list'; -import { useBem } from '@/components/common'; +import List from '@farris/mobile-ui-vue/list'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { useLookupPanelState, useRenderComponent } from '../composition'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/content-search.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/content-search.component.tsx index 9ed8fbe66132e5266dfe9be3201037ed22b87c14..aace38c8a4bb53058c50680d4ba8106e31a0fdae 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/content-search.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/content-search.component.tsx @@ -1,6 +1,6 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import List from '@/components/list'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import List from '@farris/mobile-ui-vue/list'; import { useLookupPanelState, useRenderComponent } from '../composition'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/content.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/content.component.tsx index 0048b3ace466cab8e928b41c7f71c6d2bb6ba3bd..a0c5ba3d519156c808ad4a6e10146b6646d06c7e 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/content.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/content.component.tsx @@ -1,5 +1,5 @@ import { computed, CSSProperties, defineComponent } from 'vue'; -import { useBem } from '@/components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { LookupDisplayType } from '../composition/types'; import { useLookupPanelState } from '../composition'; import ListComponent from './content-list.component'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/footer.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/footer.component.tsx index 657273c1ab3fe9b21fd013ae150c588f2a940b22..b5da66bcc9e22cb860dbb3fe0731a52025d4aa89 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/footer.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/footer.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import { Checker, CheckerShapeMap } from '@/components/checker'; -import Button from '@/components/button'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { Checker, CheckerShapeMap } from '@farris/mobile-ui-vue/checker'; +import Button from '@farris/mobile-ui-vue/button'; import { useLookupPanelState } from '../composition'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/header.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/header.component.tsx index e3deac7be7bba35e5d7e2d2ba420197f5ad79260..ff3da3d60b686cfdc456b2250b904200e39e9baf 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/header.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/header.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import Navbar from '@/components/navbar'; -import Search from '@/components/search'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import Navbar from '@farris/mobile-ui-vue/navbar'; +import Search from '@farris/mobile-ui-vue/search'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; import { useLookupPanelState } from '../composition'; diff --git a/packages/mobile-ui-vue/components/lookup/src/components/selected.component.tsx b/packages/mobile-ui-vue/components/lookup/src/components/selected.component.tsx index e24798bf426f2976980620440bedf5dd4f75c276..39080fc0a255f703b183987d5fef1469895ba8e4 100644 --- a/packages/mobile-ui-vue/components/lookup/src/components/selected.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/components/selected.component.tsx @@ -1,9 +1,9 @@ import { defineComponent } from 'vue'; -import { useBem } from '@/components/common'; -import List from '@/components/list'; -import Cell from '@/components/cell'; -import Popup from '@/components/popup'; -import Navbar from '@/components/navbar'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import List from '@farris/mobile-ui-vue/list'; +import Cell from '@farris/mobile-ui-vue/cell'; +import Popup from '@farris/mobile-ui-vue/popup'; +import Navbar from '@farris/mobile-ui-vue/navbar'; import { LOOKUP_PANEL_NAME } from '../lookup-panel.props'; import { ListDataItem, useLookupPanelState } from '../composition'; import FooterComponent from './footer.component'; diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/types.ts b/packages/mobile-ui-vue/components/lookup/src/composition/types.ts index e5764f12e29fe1a9ed773bf3ba79692ee2c9b31d..74b824b6f7ece8ada80cf6a5a16d15df8b5f141e 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/types.ts +++ b/packages/mobile-ui-vue/components/lookup/src/composition/types.ts @@ -229,7 +229,7 @@ export interface TreeDataServie { export type LookupPanelState = { panelProps: LookupPanelProps, - panelContext: SetupContext<['change', 'confirm', 'close', 'update:modelValue']>, + panelContext: SetupContext<['change', 'confirm', 'close']>, dataService: DataService, seletedService: SeletedService, searchService: SearchService, diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/use-data-service.ts b/packages/mobile-ui-vue/components/lookup/src/composition/use-data-service.ts index d66ff43a83df2c38eafd4ec4ef2074c0fa9a3aa6..8ba33ce3f6dbd84d7d7d34a2dae5a9b10b8a7406 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/use-data-service.ts +++ b/packages/mobile-ui-vue/components/lookup/src/composition/use-data-service.ts @@ -1,5 +1,5 @@ import { reactive } from "vue"; -import { isFunction } from "@/components/common"; +import { isFunction } from "@farris/mobile-ui-vue/common"; import { LookupPanelProps } from "../lookup-panel.props"; import { BeforeLoadDataContext, LookupDisplayType, LookupListData, SeletedService, TreeDataServie } from "./types"; import { useLoadListData } from "./use-load-list-data"; diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/use-lookup-state.ts b/packages/mobile-ui-vue/components/lookup/src/composition/use-lookup-state.ts index b3fb1b6b7bd6e056efab42a4cb9afd1c04631a91..1905f39d74c87fe2e6bc7982985a337336236cc0 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/use-lookup-state.ts +++ b/packages/mobile-ui-vue/components/lookup/src/composition/use-lookup-state.ts @@ -1,5 +1,5 @@ import { SetupContext, computed, onMounted, shallowRef, watch } from 'vue'; -import { ButtonEditProps, useButtonEditProps } from '@/components/button-edit'; +import { ButtonEditProps, useButtonEditProps } from '@farris/mobile-ui-vue/button-edit'; import { lookupPanelProps } from '../lookup-panel.props'; import { ListDataItem } from './types'; @@ -24,10 +24,6 @@ export const useLookupState = ( inputValue.value = getTextValue(); }; - onMounted(() => { - updateInputValue(); - }); - const handleConfirm = (value: string) => { showPopup.value = false; updateInputValue(); diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/use-render-component.tsx b/packages/mobile-ui-vue/components/lookup/src/composition/use-render-component.tsx index 3b80136c0dfdc6f4180a4a57d2270014c9ad4c21..3dbd6e6523fd49c9f9cd54a171f793778fbbed00 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/use-render-component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/composition/use-render-component.tsx @@ -1,8 +1,8 @@ import { computed } from "vue"; -import { getValue, stopPropagation, useBem } from "@/components/common"; -import { Checker, CheckerShapeMap } from "@/components/checker"; -import Icon from "@/components/icon"; -import Cell from "@/components/cell"; +import { getValue, stopPropagation, useBem } from "@farris/mobile-ui-vue/common"; +import { Checker, CheckerShapeMap } from "@farris/mobile-ui-vue/checker"; +import Icon from "@farris/mobile-ui-vue/icon"; +import Cell from "@farris/mobile-ui-vue/cell"; import { ListDataItem, LookupDisplayType, UseRenderComponent } from "./types"; import { useLookupPanelState } from "./use-lookup-panel-state"; import { LOOKUP_PANEL_NAME } from "../lookup-panel.props"; diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/use-selcted-service.ts b/packages/mobile-ui-vue/components/lookup/src/composition/use-selcted-service.ts index 60ee378870b1f5fa568c7f3e9a56cd02f7654d6d..4ecf0c533c492cb57c87cf9dd5a1e4bd200d806f 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/use-selcted-service.ts +++ b/packages/mobile-ui-vue/components/lookup/src/composition/use-selcted-service.ts @@ -1,5 +1,5 @@ import { computed, reactive } from "vue"; -import { getValue } from "@/components/common"; +import { getValue } from "@farris/mobile-ui-vue/common"; import { ListDataItem, SelectedListData, SeletedService } from "./types"; import { LookupPanelProps } from "../lookup-panel.props"; @@ -84,8 +84,9 @@ export const useSelectedService = (props: LookupPanelProps): SeletedService => { }; const getSelectedInfo = ()=>{ + const idValue = getIdValue(); return { - selectedIds: getIdValue().split(','), + selectedIds: (idValue ? idValue : props.idValue).split(props.separator), selected: true }; }; diff --git a/packages/mobile-ui-vue/components/lookup/src/composition/use-tree-data-service.ts b/packages/mobile-ui-vue/components/lookup/src/composition/use-tree-data-service.ts index 207267ee0f9cf15a9ac8037d67084b296e1888a3..afc846e550e8b32fd86511ae7673dcebc5d56519 100644 --- a/packages/mobile-ui-vue/components/lookup/src/composition/use-tree-data-service.ts +++ b/packages/mobile-ui-vue/components/lookup/src/composition/use-tree-data-service.ts @@ -1,6 +1,6 @@ import { reactive } from "vue"; import { ListDataItem, LookupTreeData, NavListLookupHttpResult, TreeInfo, TreeLookupHttpResult } from "./types"; -import { getValue } from "@/components/common"; +import { getValue } from "@farris/mobile-ui-vue/common"; export const useTreeDataServie = () => { const treeDataMap: Map }> = new Map(); const treeData = reactive({ diff --git a/packages/mobile-ui-vue/components/lookup/src/lookup-panel.component.tsx b/packages/mobile-ui-vue/components/lookup/src/lookup-panel.component.tsx index db0c75e1ba7a82a192aee28d978cdbdee6a70674..e2e9ffd8caebfab86bcd10fc10dcec50d36221fd 100644 --- a/packages/mobile-ui-vue/components/lookup/src/lookup-panel.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/lookup-panel.component.tsx @@ -1,5 +1,5 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@/components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { LOOKUP_PANEL_NAME, lookupPanelProps } from './lookup-panel.props'; import { useDataService, useLookupPanelState, useSearchService, useSelectedService, useTreeDataServie } from './composition'; import HeaderComponent from './components/header.component'; @@ -10,7 +10,7 @@ import SelectedListComponent from './components/selected.component'; export default defineComponent({ name: LOOKUP_PANEL_NAME, props: lookupPanelProps, - emits: ['change', 'confirm', 'close', 'update:modelValue'], + emits: ['change', 'confirm', 'close'], setup(props, context) { const { expose } = context; diff --git a/packages/mobile-ui-vue/components/lookup/src/lookup-panel.props.ts b/packages/mobile-ui-vue/components/lookup/src/lookup-panel.props.ts index 6b89af9d7b95ba78e90431b8ba083f59a88bbf7b..db30223217cedc286684a2d0af512f689f03d0c6 100644 --- a/packages/mobile-ui-vue/components/lookup/src/lookup-panel.props.ts +++ b/packages/mobile-ui-vue/components/lookup/src/lookup-panel.props.ts @@ -10,6 +10,8 @@ export const commonLookupProps = { displayType: { type: String as PropType, default: LookupDisplayType.List }, + idValue: { type: String, default: '' }, + data: { type: Array as PropType[]>, default: () => [] }, uri: { type: String, default: '' }, diff --git a/packages/mobile-ui-vue/components/lookup/src/lookup.component.tsx b/packages/mobile-ui-vue/components/lookup/src/lookup.component.tsx index a59fa12dc86dc35e2672fd32a7f3ef6b5f4da091..d9eda4752c91f8985662d700ec9c5ab85f568a34 100644 --- a/packages/mobile-ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/mobile-ui-vue/components/lookup/src/lookup.component.tsx @@ -14,10 +14,10 @@ * limitations under the License. */ -import { defineComponent } from 'vue'; +import { defineComponent, onMounted } from 'vue'; import { LOOKUP_NAME, lookupProps } from './lookup.props'; -import { useBem } from '@/components/common'; -import ButtonEdit from '@/components/button-edit'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import ButtonEdit from '@farris/mobile-ui-vue/button-edit'; import LookupPanel from './lookup-panel.component'; import { useLookupState } from './composition'; @@ -30,6 +30,10 @@ export default defineComponent({ const { buttonEditProps, lookupPanelSlotProps, inputValue, showPopup } = useLookupState(props, context); + onMounted(() => { + inputValue.value = props.modelValue; + }); + return () => { return ( VNode) => () => void; -} -export default defineComponent({ - name: 'FModalContextHolder', - setup(props: any, context: SetupContext) { - const modals = shallowRef<(() => VNode)[]>([]); - const addModal = (modal: () => VNode) => { - modals.value.push(modal); - modals.value = modals.value.slice(); - return () => { - // 删除当前模态框 - modals.value = modals.value.filter(currentModal => currentModal !== modal); - }; - }; - context.expose({ addModal }); - return () => { - return modals.value.map(modal => modal()); - }; - } -}); diff --git a/packages/mobile-ui-vue/components/modal/src/composition/destroy.ts b/packages/mobile-ui-vue/components/modal/src/composition/destroy.ts deleted file mode 100644 index e68523fb9e051802488672d432b5cf8554e952c0..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/destroy.ts +++ /dev/null @@ -1 +0,0 @@ -export const destroyFunctionList: any[] = []; diff --git a/packages/mobile-ui-vue/components/modal/src/composition/modal.service.tsx b/packages/mobile-ui-vue/components/modal/src/composition/modal.service.tsx deleted file mode 100644 index ff8a7dc10cf9a99b557d3814e769b5b467ac6435..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/modal.service.tsx +++ /dev/null @@ -1,263 +0,0 @@ -import { ref, h, render, VNode, cloneVNode, shallowRef, nextTick, App, AppContext, createApp, onUnmounted, onMounted, computed } from "vue"; -import { ModalFunctions, ModalOptions } from "./type"; -import FModal from '../modal.component'; -// import FarrisPlugin from '../../../plugin'; - -function getContentRender(props: ModalOptions) { - if (props.content && props.content.render) { - return props.content.render; - } - if (props.render && typeof props.render === 'function') { - return props.render; - } -} - -function createModalInstance(options: ModalOptions) { - const container = document.createElement('div'); - container.style.display = 'contents'; - - const app: App = createApp({ - setup(props, context) { - - onUnmounted(() => { - document.body.removeChild(container); - }); - - const modalRef = ref(); - - const customClass = ref(options.class || ''); - const showButtons = ref(!!options.showButtons); - const showHeader = ref(!!options.showHeader); - const showCloseButton = ref(options.showCloseButton == null ? true : options.showCloseButton); - const showModal = ref(true); - const modalTitle = ref(options.title || ''); - const acceptCallback = options.acceptCallback || (() => { }); - const rejectCallback = options.rejectCallback || (() => { }); - - const modalClosedCallback = options.closedCallback || (($event: Event) => { }); - const modalResizedCallback = options.resizeHandle || (($event: Event) => { }); - - const contentRender = getContentRender(options); - - const onClosed = ($event: Event) => { - showModal.value = false; - app.unmount(); - modalClosedCallback($event); - }; - - onMounted(() => { - // console.log(modalRef); - }); - - context.expose({ - modalRef - }); - - return () => ( - - {contentRender && contentRender(app)} - - ); - } - }); - document.body.appendChild(container); - // if (FarrisPlugin && !!FarrisPlugin.install) { - // app.use(FarrisPlugin); - // } - - app.mount(container); - - return app; -} - -export default class ModalService { - private appContext: AppContext | null = null; - - private modalRef = ref(); - - private activeModalIndex = ref(0); - - private modalRefs: Record = {}; - - private isUseEscCloseModal = ref(false); - - private activeModalInstance = computed(() => { - return this.modalRefs[this.activeModalIndex.value]; - }); - - private app: App; - - constructor(currentApp: App) { - this.app = currentApp; - this.appContext = currentApp ? currentApp._context : null; - } - - getCurrentModal() { - return this.activeModalInstance.value; - } - - private adaptToWindow(width: number, height: number) { - // 可视区域尺寸 - const { width: winWidth, height: winHeight } = { - width: window.innerWidth, - height: window.innerHeight - }; - - if (winWidth < width) { - width = winWidth; - } - - if (winHeight < height) { - height = winHeight; - } - - return { - width, - height - }; - } - - static show(options: ModalOptions) { - const modalOptions = Object.assign({ - title: '', - showButtons: true, - showHeader: true - }, options); - const app: App = createModalInstance(modalOptions); - return app; - } - - open(options: ModalOptions): ModalFunctions { - // 创建一个空白文档作为模态框容器,空白文档不属于DOM树,比创建一般节点性能较好,且仅渲染子元素 - const container = document.createDocumentFragment(); - - if (options.showMaxButton && options.fitContent) { - options.showMaxButton = false; - } - - const modalOptions = shallowRef(Object.assign({ - title: '', - showButtons: true, - showHeader: true, - }, options)); - - const showModal = ref(true); - const acceptCallback = modalOptions.value.acceptCallback || (() => { }); - const rejectCallback = modalOptions.value.rejectCallback || (() => { }); - - const modalClosedCallback = modalOptions.value.closedCallback || (($event?: Event, from?: string) => { }); - const modalResizedCallback = modalOptions.value.resizeHandle || (($event: Event) => { }); - let modalInstance: VNode | null; - - const contentRender = getContentRender(modalOptions.value); - - const onClosed = ($event?: Event) => { - showModal.value = false; - - const isCloseIconClick = ($event?.target as any)?.classList.contains('modal_close'); - - modalClosedCallback($event, this.isUseEscCloseModal.value ? 'esc' : isCloseIconClick ? 'icon' : 'button'); - - }; - - const destroy = ($event?: Event) => { - onClosed($event); - if (modalInstance) { - nextTick(() => { - if (this.modalRefs[this.activeModalIndex.value]) { - delete this.modalRefs[this.activeModalIndex.value]; - } - render(null, container as any); - modalInstance = null; - this.modalRef.value = null; - - if (this.modalRefs) { - const modals = Object.keys(this.modalRefs).map((key: string) => Number(key)); - if (modals.length > 0) { - this.activeModalIndex.value = Math.max(...modals); - } else { - this.activeModalIndex.value = 0; - } - } - - this.isUseEscCloseModal.value = false; - }); - } - - }; - - const onEsc = (payload: any) => { - this.isUseEscCloseModal.value = true; - this.activeModalInstance && this.activeModalInstance.value?.close(payload?.event); - }; - - const { width: modalWidth, height: modalHeight } = modalOptions.value; - const adaptedSize = this.adaptToWindow(modalWidth || 500, modalHeight || 320); - Object.assign(modalOptions.value, adaptedSize); - - const ModalWrapper = () => ( - - {contentRender && contentRender(this.app)} - - ); - - const renderModal = (props: Partial): VNode => { - const vnode = h(ModalWrapper, props); - vnode.appContext = this.appContext; - // if (FarrisPlugin && !!FarrisPlugin.install) { - // vnode.appContext?.app.use(FarrisPlugin); - // } - render(vnode, container as any); - return vnode; - }; - modalInstance = renderModal( - { - ...modalOptions.value, - // 'onUpdate:modelValue': onUpdateModelValue, - } - ); - - this.activeModalIndex.value++; - this.modalRefs[this.activeModalIndex.value] = this.modalRef.value; - - const update = (updateConfig: ModalOptions) => { - modalOptions.value = { - ...modalOptions.value, - ...updateConfig - }; - if (modalInstance) { - render(cloneVNode(modalInstance, { ...modalOptions }), container as any); - } - }; - - return { - update, - destroy, - modalRef: this.activeModalInstance - }; - } -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/position.ts b/packages/mobile-ui-vue/components/modal/src/composition/resizeable/position.ts deleted file mode 100644 index 8aa65d4a5cd4b6cef9b9e09f51fa9b5cd6bfc658..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/position.ts +++ /dev/null @@ -1,104 +0,0 @@ -export interface IPosition { - x: number; - y: number; -} - -export class Position implements IPosition { - constructor(public x: number, public y: number) { } - - static getTransformInfo(target: Element) { - const styleInfo = window.getComputedStyle(target); - const transforms = styleInfo.getPropertyValue('transform').replace(/[^-\d,]/g, '').split(','); - if (transforms.length >= 6) { - const translateX = parseInt(transforms[4], 10); - const translateY = parseInt(transforms[5], 10); - return {x: translateX, y: translateY }; - } - - return {x: 0, y: 0 }; - } - - static fromEvent(e: MouseEvent | TouchEvent, el: any = null) { - - if (this.isMouseEvent(e)) { - return new Position(e.clientX, e.clientY); - } - - if (el === null || e.changedTouches.length === 1) { - return new Position(e.changedTouches[0].clientX, e.changedTouches[0].clientY); - } - - for (let i = 0; i < e.changedTouches.length; i++) { - if (e.changedTouches[i].target === el) { - return new Position(e.changedTouches[i].clientX, e.changedTouches[i].clientY); - } - } - } - - static isMouseEvent(e: MouseEvent | TouchEvent): e is MouseEvent { - return Object.prototype.toString.apply(e).indexOf('MouseEvent') === 8; - } - - static isIPosition(obj): obj is IPosition { - return !!obj && ('x' in obj) && ('y' in obj); - } - - static getCurrent(el: Element) { - const pos = new Position(0, 0); - - if (window) { - const computed = window.getComputedStyle(el); - if (computed) { - const x = parseInt(computed.getPropertyValue('left'), 10); - const y = parseInt(computed.getPropertyValue('top'), 10); - pos.x = isNaN(x) ? 0 : x; - pos.y = isNaN(y) ? 0 : y; - } - return pos; - } - - return null; - } - - static copy(p: IPosition) { - return new Position(0, 0).set(p); - } - - get value(): IPosition { - return { x: this.x, y: this.y }; - } - - add(p: IPosition) { - this.x += p.x; - this.y += p.y; - return this; - } - - subtract(p: IPosition) { - this.x -= p.x; - this.y -= p.y; - return this; - } - - multiply(n: number) { - this.x *= n; - this.y *= n; - } - - divide(n: number) { - this.x /= n; - this.y /= n; - } - - reset() { - this.x = 0; - this.y = 0; - return this; - } - - set(p: IPosition) { - this.x = p.x; - this.y = p.y; - return this; - } -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/resize-event.ts b/packages/mobile-ui-vue/components/modal/src/composition/resizeable/resize-event.ts deleted file mode 100644 index 6f3828a241b8f14aabb28ea63a2828b280dc9959..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/resize-event.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface IResizeEvent { - size: { - width?: number; - height?: number; - }; - position: { - x?: number; - y?: number; - }; - transform?: string; -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/size.ts b/packages/mobile-ui-vue/components/modal/src/composition/resizeable/size.ts deleted file mode 100644 index 10f028b9fabd2aa8b9264dece948c0c8679e54ca..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/resizeable/size.ts +++ /dev/null @@ -1,33 +0,0 @@ -export interface ISize { - width: number; - height: number; -} - -export class Size implements ISize { - constructor(public width: number, public height: number) {} - - static getCurrent(el: Element) { - const size = new Size(0, 0); - - if (window) { - const computed = window.getComputedStyle(el); - if (computed) { - size.width = parseInt(computed.getPropertyValue('width'), 10); - size.height = parseInt(computed.getPropertyValue('height'), 10); - } - return size; - } - - return null; - } - - static copy(s: Size) { - return new Size(0, 0).set(s); - } - - set(s: ISize) { - this.width = s.width; - this.height = s.height; - return this; - } -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/type.ts b/packages/mobile-ui-vue/components/modal/src/composition/type.ts deleted file mode 100644 index e39156ec691e10ca43277acca8e54bb1c7d91f8d..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/type.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { App, VNode } from "vue"; -import { JSX } from "vue/jsx-runtime"; -import { IResizeEvent } from "./resizeable/resize-event"; - -/** 自定义按钮结构 */ -export interface ModalButton { - name?: string; - class: string; - focusedByDefault?: boolean; - disable?: boolean; - iconClass?: string; - handle: ($event: MouseEvent, context: any) => any; - text: string; -} - -export interface ModalOptions { - class?: string; - title?: string; - width?: number; - height?: number; - minWidth?: number; - minHeight?: number; - showButtons?: boolean; - showHeader?: boolean; - showFloatingClose?: boolean; - content?: { render(): JSX.Element }; - render?: (app: App) => JSX.Element; - fitContent?: boolean; - buttons?: ModalButton[]; - draggable?: boolean; - showMaxButton?: boolean; - showCloseButton?: boolean; - acceptCallback?: () => void; - rejectCallback?: () => void; - closedCallback?: ($event?: Event, from?: 'esc' | 'icon' | 'button') => void; - resizeHandle?: (event: IResizeEvent) => void; - enableEsc?: boolean; -} - -export interface ModalFunctions { - update: (options: ModalOptions) => void; - destroy: () => void; - modalRef: any; -} - -export interface UseModal { - FModalContextHolder: () => VNode; - -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/use-draggable.ts b/packages/mobile-ui-vue/components/modal/src/composition/use-draggable.ts deleted file mode 100644 index 2a239d952c9d283574f033124f7768571db7710b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/use-draggable.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { Ref, ref, watch } from "vue"; -import { Position } from "./resizeable/position"; - -export function useDraggable(props: any, context: any, canMove: Ref) { - - const dragTarget = ref(); - const allowDrag = ref(props.draggable); - const lockAxis = ref(props.lockAxis); - - const dragHandle = ref(); - const boundingElement = ref(); - const moving = ref(false); - - const origPos = ref(new Position(0, 0)); - const oldTranslate = ref(new Position(0, 0)); - const movingPos= ref(new Position(0, 0)); - const currentPos= ref(new Position(0, 0)); - - watch(() => canMove.value, (move) => { - dragHandle.value.style.cursor = move ? 'move' : 'default'; - }); - - function checkHandleTarget(target: EventTarget, element: Element) { - // Checks if the target is the element clicked, then checks each child element of element as well - // Ignores button clicks - - // Ignore elements of type button - if (element.tagName === 'BUTTON') { - return false; - } - - // If the target was found, return true (handle was found) - if (element === target) { - return true; - } - - // Recursively iterate this elements children - - for (const child in element.children) { - if (Object.prototype.hasOwnProperty.call(element.children, child)) { - if (checkHandleTarget(target, element.children[child])) { - return true; - } - } - } - - // Handle was not found in this lineage - // Note: return false is ignore unless it is the parent element - return false; - } - - function transform() { - let translateX = movingPos.value.x + oldTranslate.value.x; - let translateY = movingPos.value.y + oldTranslate.value.y; - - if (lockAxis.value === 'x') { - translateX = origPos.value?.x || 0; - movingPos.value.x = 0; - } else if (lockAxis.value === 'y') { - translateY = origPos.value?.y || 0; - movingPos.value.y = 0; - } - - const value = `translate3d(${Math.round(translateX)}px, ${Math.round(translateY)}px, 0px)`; - if (dragTarget.value) { - dragTarget.value.style.transform = value; - } - - // save current position - currentPos.value.x = translateX; - currentPos.value.y = translateY; - } - - function checkBounds(){ - if(!boundingElement.value || !dragTarget.value){ return null; } - const boundary = boundingElement.value.getBoundingClientRect(); - const targetRect = dragTarget.value.getBoundingClientRect(); - const result = { - 'top': boundary.top < targetRect.top, - 'right': boundary.right > targetRect.right, - 'bottom': boundary.bottom > targetRect.bottom, - 'left': boundary.left < targetRect.left - }; - - if (!result.top) { - movingPos.value.y -= targetRect.top - boundary.top; - } - - if (!result.bottom) { - movingPos.value.y -= targetRect.bottom - boundary.bottom; - } - - if (!result.right) { - movingPos.value.x -= targetRect.right - boundary.right; - } - - if (!result.left) { - movingPos.value.x -= targetRect.left - boundary.left; - } - - transform(); - return result; - } - - function moveTo(p?: Position) { - if (p) { - if (origPos.value) { - p.subtract(origPos.value); - } - - movingPos.value.set(p); - transform(); - checkBounds(); - } - } - - function onMouseMove(event: MouseEvent) { - if (moving.value && allowDrag.value) { - event.stopPropagation(); - event.preventDefault(); - - // Add a transparent helper div: - // helperBlock.add(); - moveTo(Position.fromEvent(event, dragHandle.value)); - } - } - - function stopMove() { - if (moving.value) { - - moving.value = false; - - oldTranslate.value.add(movingPos.value); - movingPos.value.reset(); - - dragTarget.value?.classList.remove('ng-dragging'); - - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', stopMove); - } - } - - function startMove() { - if (!moving.value && dragHandle.value) { - moving.value = true; - dragHandle.value.classList.add('ng-dragging'); - - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', stopMove); - } - } - - function resetTranslate() { - if (dragTarget.value) { - const pos = Position.getTransformInfo(dragTarget.value); - oldTranslate.value.set(pos); - return; - } - - oldTranslate.value.reset(); - } - - function onMouseDown(event: MouseEvent) { - if (!canMove.value) { - return; - } - // 1. skip right click; - if (event instanceof MouseEvent && event.button === 2) { - return; - } - // 2. if handle is set, the element can only be moved by handle - const target = event.target || event.srcElement; - if (dragHandle.value !== undefined && target && !checkHandleTarget(target, dragHandle.value)) { - return; - } - - // 3. if allow drag is set to false, ignore the mousedown - if (allowDrag.value === false) { - return; - } - - // 隐藏其他浮动层 - document.body.click(); - - event.stopPropagation(); - event.preventDefault(); - - origPos.value = Position.fromEvent(event, dragTarget.value); - resetTranslate(); - startMove(); - } - - function registerDraggle(handle: HTMLElement, hostElement: HTMLElement, boundingHost: HTMLElement | null) { - if (allowDrag.value && hostElement) { - if (handle) { - dragHandle.value = handle; - } else if (props.dragHandle) { - if (props.dragHandle instanceof HTMLElement) { - dragHandle.value = props.dragHandle; - } else if (typeof props.dragHandle === 'string') { - const element = hostElement.querySelector(props.dragHandle); - if(element) { - dragHandle.value = element as HTMLElement; - } - } - } - - dragTarget.value = hostElement; - boundingElement.value = boundingHost; - if (dragHandle.value) { - dragHandle.value.classList.add('ng-draggable'); - dragHandle.value.addEventListener('mousedown', onMouseDown); - } else { - allowDrag.value = false; - } - } - } - - return { - registerDraggle, resetTranslate - }; -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/use-resizeable.tsx b/packages/mobile-ui-vue/components/modal/src/composition/use-resizeable.tsx deleted file mode 100644 index e23782f59266e655aa21db2e46ffb8e28938173c..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/use-resizeable.tsx +++ /dev/null @@ -1,390 +0,0 @@ -import { ref } from "vue"; -import { Position } from "./resizeable/position"; -import { Size } from "./resizeable/size"; -import { IResizeEvent } from "./resizeable/resize-event"; - -export function useResizeable(props: any, context: any) { - - const resizedTarget = ref(); - const boundingElement = ref(); - - const origMousePos = ref(); - const origSize = ref(); - const origPos = ref(); - const currSize = ref(); - const currPos = ref(); - const direction = ref<{ 'n': boolean; 's': boolean; 'w': boolean; 'e': boolean } | null>(); - const resizeHandlerElement = ref(); - const modalBounding = ref(); - const resizedEventParam = ref(); - - const lastSize = ref(); - - const allowDrag = ref(props.draggable); - - const isMaximized = ref(false); - - function initBounding() { - const el = boundingElement.value || document.body; - const computed = window.getComputedStyle(el); - if(!computed){ - return; - } - - if (!resizedTarget.value) { - return; - } - - const transforms = Position.getTransformInfo(resizedTarget.value); - - - const bounding: any = {}; - - if (currPos.value) { - bounding.deltaL = resizedTarget.value.offsetLeft - currPos.value.x; - bounding.deltaT = resizedTarget.value.offsetTop - currPos.value.y; - } - - const p = computed.getPropertyValue('position'); - bounding.width = el.clientWidth; - bounding.height = el.clientHeight; - bounding.pr = parseInt(computed.getPropertyValue('padding-right'), 10); - bounding.pb = parseInt(computed.getPropertyValue('padding-bottom'), 10); - bounding.position = computed.getPropertyValue('position'); - - if (p === 'static') { - el.style.position = 'relative'; - } - - bounding.translateX = transforms.x; - bounding.translateY = transforms.y; - - modalBounding.value = bounding; - } - - function startResize(event: MouseEvent) { - - if (resizedTarget.value) { - origSize.value = Size.getCurrent(resizedTarget.value); - origPos.value = Position.getCurrent(resizedTarget.value); - currSize.value = origSize.value ? Size.copy(origSize.value) : null; - currPos.value = origPos.value ? Position.copy(origPos.value) : null; - - initBounding(); - - const directionType = (event.target as HTMLElement).getAttribute('type') || ''; - direction.value = { - n: !!directionType.match(/n/), - s: !!directionType.match(/s/), - w: !!directionType.match(/w/), - e: !!directionType.match(/e/) - }; - - } - } - - function doResize() { - if (resizedTarget.value) { - const container = resizedTarget.value as HTMLElement; - if (direction.value) { - if ((direction.value.n || direction.value.s) && currSize.value?.height) { - container.style.height = currSize.value.height + 'px'; - } - if ((direction.value.w || direction.value.e) && currSize.value?.width) { - container.style.width = currSize.value.width + 'px'; - } - - if (currPos.value) { - if (currPos.value?.x) { - container.style.left = currPos.value.x + 'px'; - } - if (currPos.value?.y) { - container.style.top = currPos.value.y + 'px'; - } - } - } - } - } - - function checkSize() { - - const minHeight = !props.minHeight ? 1 : props.minHeight; - const minWidth = !props.minWidth ? 1 : props.minWidth; - - if (currSize.value && currPos.value && direction.value && origSize.value) { - if (currSize.value.height < minHeight) { - currSize.value.height = minHeight; - - if (direction.value.n && origPos.value) { - currPos.value.y = origPos.value.y + (origSize.value.height - minHeight); - } - } - - if (currSize.value.width < minWidth) { - currSize.value.width = minWidth; - - if (direction.value.w && origPos.value) { - currPos.value.x = origPos.value.x + (origSize.value.width - minWidth); - } - } - - if (props.maxHeight && currSize.value.height > props.maxHeight) { - currSize.value.height = props.maxHeight; - - if (origPos.value && direction.value.n) { - currPos.value.y = origPos.value.y + (origSize.value.height - props.maxHeight); - } - } - - if (props.maxWidth && currSize.value.width > props.maxWidth) { - currSize.value.width = props.maxWidth; - - if (direction.value.w && origPos.value) { - currPos.value.x = origPos.value.x + (origSize.value.width - props.maxWidth); - } - } - } - - } - - function checkBounds(){ - if (boundingElement.value) { - const bounding = modalBounding.value; - - if (currPos.value && currSize.value && direction.value && origSize.value) { - const maxWidth = bounding.width - bounding.pr - bounding.deltaL - bounding.translateX - currPos.value.x; - const maxHeight = bounding.height - bounding.pb - bounding.deltaT - bounding.translateY - currPos.value.y; - - if (direction.value.n && (currPos.value.y + bounding.translateY < 0) && origPos.value) { - currPos.value.y = -bounding.translateY; - currSize.value.height = origSize.value.height + origPos.value.y + bounding.translateY; - } - - if (direction.value.w && (currPos.value.x + bounding.translateX) < 0 && origPos.value) { - currPos.value.x = -bounding.translateX; - currSize.value.width = origSize.value.width + origPos.value.x + bounding.translateX; - } - - if (currSize.value.width > maxWidth) { - currSize.value.width = maxWidth; - } - - if (currSize.value.height > maxHeight) { - currSize.value.height = maxHeight; - } - } - } - } - - function resizeTo(p: Position) { - - if (!origMousePos.value || !origSize.value || !origPos.value || !direction.value) { - return; - } - - p.subtract(origMousePos.value); - - const tmpX = p.x; - const tmpY = p.y; - - if (direction.value.n) { - // n, ne, nw - currPos.value!.y = origPos.value.y + tmpY; - currSize.value!.height = origSize.value.height - tmpY; - } else if (direction.value.s) { - // s, se, sw - currSize.value!.height = origSize.value.height + tmpY; - } - - if (direction.value.e) { - // e, ne, se - currSize.value!.width = origSize.value.width + tmpX; - } else if (direction.value.w) { - // w, nw, sw - currSize.value!.width = origSize.value.width - tmpX; - currPos.value!.x = origPos.value.x + tmpX; - } - - checkBounds(); - checkSize(); - doResize(); - } - - function onMouseMove(event: MouseEvent) { - if (!resizeHandlerElement.value) { - return; - } - - const pos = Position.fromEvent(event); - if (pos) { - resizeTo(pos); - } - } - - function getResizedEventParam(): IResizeEvent | null { - if (resizedTarget.value) { - const { width, height, x, y } = resizedTarget.value.getBoundingClientRect(); - const transforms = Position.getTransformInfo(resizedTarget.value); - - return { - size: { width, height }, - position: {x: x - transforms.x, y: y - transforms.y } - }; - } - return null; - } - - function onMouseLeave(event: MouseEvent) { - if (resizedTarget.value) { - const resizedParam = getResizedEventParam(); - resizedEventParam.value = resizedParam; - } - - origMousePos.value = undefined; - origSize.value = null; - origPos.value = null; - currSize.value = null; - currPos.value = null; - direction.value = null; - resizeHandlerElement.value = null; - - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', onMouseLeave); - } - - function registerMouseEvent() { - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', onMouseLeave); - } - - function onMouseDown(event: MouseEvent) { - // skip right click; - if (event instanceof MouseEvent && event.button === 2) { - return; - } - - if (!allowDrag.value) { - return; - } - // 隐藏其他浮动层 - document.body.click(); - // prevent default events - event.stopPropagation(); - event.preventDefault(); - - origMousePos.value = Position.fromEvent(event); - resizeHandlerElement.value = event.target; - startResize(event); - registerMouseEvent(); - } - - function renderResizeBar(hostElement: any) { - resizedTarget.value = hostElement; - return <> -
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
-
onMouseDown(e)}>
- ; - } - - function maximize(updateLastSize = true) { - // 隐藏其他浮动层 - document.body.click(); - - const container = boundingElement.value || document.body; - const maxSize = Size.getCurrent(container); - const target = resizedTarget.value as HTMLElement; - - if (updateLastSize && target) { - lastSize.value = getResizedEventParam(); - lastSize.value!.transform = target.style.transform; - } - - if (maxSize && target) { - currSize.value = maxSize; - - target.style.height = (currSize.value.height - 14) + 'px'; - target.style.width = (currSize.value.width - 14) + 'px'; - target.style.left = '7px'; - target.style.top = '7px'; - target.style.transform = ''; - - resizedEventParam.value = { - size: currSize.value, - position: {x: 0, y: 0} - }; - - allowDrag.value = false; - isMaximized.value = true; - } - } - - function restore() { - // 隐藏其他浮动层 - document.body.click(); - - if (lastSize.value) { - const size = { width: lastSize.value.size.width || 0, height: lastSize.value.size.height || 0 }; - const position = { x: (window.innerWidth - size.width) / 2, y: (window.innerHeight - size.height) / 2}; - - currSize.value?.set(size); - currPos.value?.set(position); - - const target = resizedTarget.value as HTMLElement; - target.style.height = size.height + 'px'; - target.style.width = size.width + 'px'; - target.style.left = `${position.x}px`; - target.style.top = `${position.y}px`; - target.style.transform = ''; - resizedEventParam.value = { - size, - position - }; - - allowDrag.value = props.draggable; - - isMaximized.value = false; - } - } - - function moveToCenter() { - if (resizedTarget.value) { - const modalSize = Size.getCurrent(resizedTarget.value); - if (modalSize) { - const { width, height } = modalSize; - resizedTarget.value.style.left = `${(window.innerWidth - width) / 2}px`; - resizedTarget.value.style.top = `${(window.innerHeight - height) / 2}px`; - resizedTarget.value.style.transform = ''; - - } - } - } - - function onWindowResize() { - const windowResizeHandle = () => { - if (isMaximized.value) { - maximize(false); - } else { - moveToCenter(); - } - // 隐藏其他浮动层 - document.body.click(); - }; - - window.addEventListener('resize', windowResizeHandle); - return () => { - window.removeEventListener('resize', windowResizeHandle); - }; - } - - const unWindowResizeHandle = onWindowResize(); - - return { - renderResizeBar, boundingElement, resizedEventParam, maximize, restore, allowDrag, isMaximized, unWindowResizeHandle - }; -} diff --git a/packages/mobile-ui-vue/components/modal/src/composition/use-shortcut.ts b/packages/mobile-ui-vue/components/modal/src/composition/use-shortcut.ts deleted file mode 100644 index 52e510aec03aad23d435c7ffad16c9fe82f99608..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/composition/use-shortcut.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { ref } from "vue"; - - -function registrationShortcutKeyEvent(keyCode: string, callBack: (...args) => void) { - if (keyCode) { - const registerKeyDown =(event: KeyboardEvent) =>{ - if (event.key.toLowerCase() === keyCode.toLowerCase()) { - callBack({ event, key: keyCode }); - } - }; - - document.addEventListener('keydown', registerKeyDown); - - return () => { - document.removeEventListener('keydown', registerKeyDown); - }; - } - -} - -export function useEsc(props: any, context: any) { - const enableEsc = ref(props.enableEsc); - - let removeEventListener: any = null; - - if (enableEsc.value) { - removeEventListener = registrationShortcutKeyEvent('Escape', ($event: any) => { - context.emit('esc', { event: $event.event, type: 'esc' }); - }); - - return { - remove: removeEventListener - }; - } - - return null; -} - -export function useEnter(props: any, context: any) { - const enableEnter = ref(props.enableEnter); - - let removeEventListener: any = null; - - if (enableEnter.value) { - removeEventListener = registrationShortcutKeyEvent('Enter', ($event: any) => { - context.emit('enter', { event: $event.event, type: 'enter' }); - }); - - return { - remove: removeEventListener - }; - } - - return null; - -} diff --git a/packages/mobile-ui-vue/components/modal/src/modal.component.tsx b/packages/mobile-ui-vue/components/modal/src/modal.component.tsx deleted file mode 100644 index 31b1e0a72ae5afd0fcc6ed7d8ff1fe69e6150996..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/modal.component.tsx +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { computed, defineComponent, ref, SetupContext, Teleport, watch, Transition, onMounted, onUnmounted, provide, nextTick } from 'vue'; -import { ModalButton, ModalOptions } from './composition/type'; -import { ModalProps, modalProps } from './modal.props'; -import { useResizeable } from './composition/use-resizeable'; -import { useDraggable } from './composition/use-draggable'; -import './modal.css'; -import { useEnter, useEsc } from './composition/use-shortcut'; - -export default defineComponent({ - name: 'FModal', - props: modalProps, - emits: ['update:modelValue', 'accept', 'cancel', 'closed', 'resize', 'esc', 'enter'] as (string[] & ThisType) | undefined, - setup(props: ModalProps, context: SetupContext) { - const width = ref(props.width || 300); - const height = ref(props.height || 200); - const modelValue = ref(props.modelValue); - const modalId = ref(''); - const customClass = ref(props.class); - const fitContent = ref(props.fitContent); - const showHeader = ref(props.showHeader); - const headerIconClass = ref(''); - const enableClose = ref(props.showCloseButton); - const enableMaximize = ref(props.showMaxButton); - const enableMinimize = ref(false); - const dialogType = ref(''); - const iframeSrc = ref(''); - const buttonAlignment = ref(''); - const showButtons = ref(props.showButtons); - const title = ref(props.title); - const resizeable = ref(props.reiszeable); - const containment = ref(props.containment || null); - const modalContainerRef = ref(); - - - function close($event: MouseEvent, accept?: boolean) { - modelValue.value = false; - context.emit('update:modelValue', false); - if (accept != null) { - context.emit(accept ? 'accept' : 'cancel'); - } - - context.emit('closed', $event); - } - const defaultButtons: ModalButton[] = [ - { - name: 'cancel', - text: '取消', - class: 'btn btn-secondary', - handle: ($event: MouseEvent) => { - close($event, false); - } - }, - { - name: 'accept', - text: '确定', - class: 'btn btn-primary', - handle: ($event: MouseEvent) => { - close($event, true); - } - } - ]; - const buttons = ref(props.buttons && props.buttons.length ? props.buttons : defaultButtons); - - const showHeaderIcon = computed(() => !!headerIconClass.value); - const showFooter = computed(() => !!showButtons.value && !!buttons.value); - - const modalHeaderRef = ref(); - const modalElementRef = ref(); - const maximized = ref(false); - - const { renderResizeBar, maximize, restore, boundingElement, - resizedEventParam, allowDrag, unWindowResizeHandle } = useResizeable(props, context); - const { registerDraggle } = useDraggable(props, context, allowDrag); - - // 监听modal 标题变化 - watch(() => props.title, (newValue, oldValue) => { - if (newValue !== oldValue) { - title.value = newValue; - } - }); - - // 监听打开关闭状态变化 - watch(() => props.modelValue, (newValue, oldValue) => { - if (newValue !== oldValue) { - modelValue.value = newValue; - } - }); - // 监听是否展示标题变化 - watch(() => props.showHeader, (newValue, oldValue) => { - if (newValue !== oldValue) { - showHeader.value = newValue; - } - }); - // 监听是否展示按钮变化 - // todo: 可以抽出公共方法 - watch(() => props.showButtons, (newValue, oldValue) => { - if (newValue !== oldValue) { - showButtons.value = newValue; - } - }); - - watch(() => resizedEventParam.value, (newSize, oldSize) => { - const newSizeValue = newSize || {}; - const oldSizeValue = oldSize || {}; - - if (JSON.stringify(newSizeValue) !== JSON.stringify(oldSizeValue)) { - context.emit('resize', { newSize, oldSize }); - } - }); - - function removeModalOpenStyle() { - const modalTotal = document.querySelectorAll('.farris-modal').length; - if (!modalTotal || modalTotal - 1 <= 0) { - document.body.classList.remove('modal-open'); - } - - if (modalContainerRef.value) { - modalContainerRef.value.classList.remove('show'); - } - } - - const showModal = computed(() => { - if (modelValue.value) { - document.body.classList.add('modal-open'); - } else { - removeModalOpenStyle(); - } - - return modelValue.value; - }); - - const modalContainerClass = computed(() => { - const classObject = { - modal: true, - 'farris-modal': true, - 'fade': true, - } as Record; - classObject['f-modal-fitContent'] = !!fitContent.value; - classObject.show = !!showModal.value; - return classObject; - }); - - const modalDialogClass = computed(() => { - const classObject = { 'modal-dialog': true }; - const customClassArray = customClass.value?.split(' '); - customClassArray?.reduce((target: any, className: string) => { - target[className] = true; - return target; - }, classObject); - return classObject; - }); - - const modalDialogStyle = computed(() => { - const styleObject = { - position: 'absolute', - top: `${(window.innerHeight - height.value) / 2}px`, - left: `${(window.innerWidth - width.value) / 2}px`, - width: `${width.value}px`, - height: fitContent.value ? 'auto' : `${height.value}px` - }; - return styleObject; - }); - - const modalContentClass = computed(() => { - const classObject = { - 'modal-content': true, - 'modal-content-has-header': showHeader.value - }; - return classObject; - }); - - const modalHeaderStyle = computed(() => { - const styleObject = { display: showHeader.value ? '' : 'none' }; - styleObject['pointer-events'] = allowDrag.value ? 'auto': 'none'; - return styleObject; - }); - - const headerMaxButtonClass = computed(() => { - const classObject = { 'f-icon': true, modal_maximize: true, modalrevert: maximized.value }; - return classObject; - }); - - const modalBodyClass = computed(() => { - const classObject = { 'modal-body': true, 'f-utils-flex-column': dialogType.value === 'iframe' }; - return classObject; - }); - - function buildFooterStyles(): Record { - return {}; - } - - const modalFooterStyle = computed(() => { - const styleObject = { textAlgin: buttonAlignment.value }; - const footerSytles = buildFooterStyles(); - return Object.assign(styleObject, footerSytles); - }); - - function maxDialog($event: MouseEvent) { - $event.stopPropagation(); - if (maximized.value) { - maximized.value = false; - restore(); - return; - } - maximize(); - maximized.value = true; - } - - async function customButtonClick(button: ModalButton, $event: MouseEvent) { - if (button.handle) { - const result = await button.handle($event, button); - if (result) { - context.emit('closed', $event); - } - } - } - - function updateModalOptions(options: ModalOptions) { - if (options.width) { - width.value = options.width; - } - if (options.height) { - height.value = options.height; - } - if (options.buttons) { - buttons.value = options.buttons; - } - if (options.title) { - title.value = options.title; - } - } - - let escEventHandler: any = null; - let enterEventHandler: any = null; - - onMounted(() => { - if (modalElementRef.value && !containment.value) { - containment.value = (modalElementRef.value as HTMLElement).parentElement; - boundingElement.value = containment.value; - registerDraggle(modalHeaderRef.value, modalElementRef.value, boundingElement.value); - } - if (showModal.value) { - document.body.classList.add('modal-open'); - } - - escEventHandler = useEsc(props, context); - enterEventHandler = useEnter(props, context); - - }); - - onUnmounted(() => { - removeModalOpenStyle(); - if (unWindowResizeHandle) { - unWindowResizeHandle(); - } - - if (escEventHandler) { - escEventHandler.remove(); - } - - if (enterEventHandler) { - enterEventHandler.remove(); - } - }); - - context.expose({ - modalElementRef, - updateModalOptions, - close, - maxDialog - }); - - function renderFloatingCloseButton() { - return
    - {enableMinimize.value && ( -
  • - -
  • - )} - {enableMaximize.value && ( -
  • - -
  • - )} - {enableClose.value && ( -
  • close(payload, false)} style="pointer-events: auto;"> - -
  • - )} -
; - } - - function renderFooterButtons() { - return ; - } - - function renderModalHeader() { - return ; - } - - function onClickModalBackdrop($event) { - $event.stopPropagation(); - } - - return () => { - return ( - - {showModal.value && - -
-
-
- { showHeader.value && renderModalHeader() } - -
- {context.slots.default?.()} - {dialogType.value === 'iframe' && ( - - )} -
- {showFooter.value && renderFooterButtons()} -
- {!fitContent.value && resizeable.value && modalElementRef.value && !maximized.value && renderResizeBar(modalElementRef.value)} -
-
-
} -
- ); - }; - } -}); diff --git a/packages/mobile-ui-vue/components/modal/src/modal.css b/packages/mobile-ui-vue/components/modal/src/modal.css deleted file mode 100644 index 080d52aa71e8e0b9e1fe7b77fdd02b361982cdf3..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/modal.css +++ /dev/null @@ -1,84 +0,0 @@ -.fade-enter-active, -.fade-leave-active { - transition: opacity 0.5s ease; -} - -.fade-enter-from, -.fade-leave-to { - opacity: 0; -} - -.fv-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; - touch-action: none; - - &:hover { - background: rgba(42, 135, 255, .07); - } - - &.fv-resizable-n { - cursor: n-resize; - height: 0.4375rem; - width: 100%; - top: -0.3125rem; - left: 0; - } - - &.fv-resizable-e { - cursor: e-resize; - width: 0.4375rem; - right: -0.3125rem; - height: 100%; - top: 0; - } - - &.fv-resizable-s { - cursor: s-resize; - height: 0.4375rem; - width: 100%; - bottom: -0.3125rem; - left: 0; - } - - &.fv-resizable-w { - cursor: w-resize; - height: 100%; - width: 0.4375rem; - left: -0.3125rem; - top: 0; - } - - &.fv-resizable-ne { - cursor: ne-resize; - width: .75rem; - height: .75rem; - right: 1px; - top: 1px; - } - - &.fv-resizable-se { - cursor: se-resize; - width: .75rem; - height: .75rem; - right: 1px; - bottom: 1px; - } - - &.fv-resizable-nw { - cursor: nw-resize; - width: .75rem; - height: .75rem; - left: 1px; - top: 1px; - } - - &.fv-resizable-sw { - cursor: sw-resize; - width: .75rem; - height: .75rem; - left: 1px; - bottom: 1px; - } -} diff --git a/packages/mobile-ui-vue/components/modal/src/modal.props.ts b/packages/mobile-ui-vue/components/modal/src/modal.props.ts deleted file mode 100644 index 19fa251526cbd84092470e1af2353ab39b979e8e..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/src/modal.props.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ExtractPropTypes, PropType } from 'vue'; -import { ModalButton } from './composition/type'; - -export type DragHandleType = HTMLElement | string; - -export const modalProps = { - /** - * 自定义类 - */ - class: { type: String, default: '' }, - /** - * 模态框标题 - */ - title: { type: String, default: '' }, - /** - * 模态框宽度 - */ - width: { type: Number, default: 500 }, - /** - * 模态框高度 - */ - height: { type: Number, default: 320 }, - /** - * 自定义按钮列表 - */ - buttons: { - type: Array, - default: [] - }, - /** - * 是否展示模态框 - */ - modelValue: { type: Boolean, default: false }, - /** - * 是否展示头部 - */ - showHeader: { type: Boolean, default: true }, - /** - * 是否展示默认按钮 - */ - showButtons: { type: Boolean, default: true }, - /** - * 是否启用自适应样式 - */ - fitContent: { type: Boolean, default: true }, - /** - * 是否展示右上角按钮 - */ - showCloseButton: { type: Boolean, default: true }, - showMaxButton: { type: Boolean, default: false }, - minHeight: {type: Number}, - maxHeight: {type: Number}, - minWidth: {type: Number}, - maxWidth: {type: Number}, - containment: {type: Object as PropType, default: null}, - reiszeable: { type: Boolean, default: false }, - draggable: { type: Boolean, default: false}, - dragHandle: { type: Object as PropType, default: null}, - closedCallback: { type: Function, default: null}, - resizeHandle: { type: Function, default: null}, - render: { type: Function, default: null}, - acceptCallback: { type: Function, default: null}, - rejectCallback: { type: Function, default: null}, - enableEsc: { type: Boolean, default: true }, - enableEnter: { type: Boolean, default: false } -}; - -export type ModalProps = Partial>; diff --git a/packages/mobile-ui-vue/components/modal/style.ts b/packages/mobile-ui-vue/components/modal/style.ts deleted file mode 100644 index ecfe335ae4db557fee79e2f97be11180f1c84dc4..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/modal/style.ts +++ /dev/null @@ -1,3 +0,0 @@ -import "@/components/dependent-base/style"; -import "@components/button/style"; -import "@theme-default/components/modal.css"; diff --git a/packages/mobile-ui-vue/components/navbar/index.ts b/packages/mobile-ui-vue/components/navbar/index.ts index 8249324fa854da373398acdb600cc4c4e5ec193e..b4fef1e79fb6e5abe7aefe93c2897824854ddefe 100644 --- a/packages/mobile-ui-vue/components/navbar/index.ts +++ b/packages/mobile-ui-vue/components/navbar/index.ts @@ -1,5 +1,5 @@ -import { withInstall } from '@components/common'; -import { propsResolver } from './src/navbar.props'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; +import { propsResolverGenerator } from './src/navbar.props'; import NavbarInstallless from './src/navbar.component'; import NavbarDesign from './src/designer/nav.design.component'; @@ -7,14 +7,16 @@ const NAVBAR_REGISTERED_NAME = 'navbar'; const Navbar = withInstall(NavbarInstallless); -Navbar.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { +Navbar.register = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext) => { componentMap[NAVBAR_REGISTERED_NAME] = Navbar; - propsResolverMap[NAVBAR_REGISTERED_NAME] = propsResolver; + propsResolverMap[NAVBAR_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; -Navbar.registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { +Navbar.registerDesigner = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record, registerContext: RegisterContext) => { componentMap[NAVBAR_REGISTERED_NAME] = NavbarDesign; - propsResolverMap[NAVBAR_REGISTERED_NAME] = propsResolver; + propsResolverMap[NAVBAR_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; export { Navbar }; export default Navbar; diff --git a/packages/mobile-ui-vue/components/navbar/src/designer/nav.design.component.tsx b/packages/mobile-ui-vue/components/navbar/src/designer/nav.design.component.tsx index e2a066b8b42c842fbe77b8021eaf1574e7945b8e..359bf636be9eda617501ccd6fb754bd3f3d39404 100644 --- a/packages/mobile-ui-vue/components/navbar/src/designer/nav.design.component.tsx +++ b/packages/mobile-ui-vue/components/navbar/src/designer/nav.design.component.tsx @@ -19,7 +19,7 @@ import { computed, defineComponent, inject, onMounted, ref, SetupContext } from import Navbar from '../..'; import { navbarProps, NavbarProps } from '../navbar.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: 'FNavDesign', diff --git a/packages/mobile-ui-vue/components/navbar/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/navbar/src/designer/use-designer-rules.ts index 00566e382cc5582906676db94e046b186d445e18..2c0f77c92728dee5a853300b12db1888bda9ca1b 100644 --- a/packages/mobile-ui-vue/components/navbar/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/navbar/src/designer/use-designer-rules.ts @@ -1,5 +1,4 @@ -import { DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { DesignerItemContext, UseDesignerRules, DraggingResolveContext } from "@farris/mobile-ui-vue/common"; import { nextTick, ref } from "vue"; import { NavBarProperty } from "../property-config/navbar.property-config"; diff --git a/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts b/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts index bd3add9711b0763ab3cb367fccde8f2f799c0315..33e9db98dfc2497ccb94150c1c3d68d99624daea 100644 --- a/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts +++ b/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import navbarSchema from './schema/navbar.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -45,7 +45,7 @@ export const navbarProps = { } }; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( navbarProps, navbarSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/navbar/src/property-config/navbar.property-config.ts b/packages/mobile-ui-vue/components/navbar/src/property-config/navbar.property-config.ts index e6a0c287c425c47b71cd83a70da622bae53c1000..dc9f20316204aaa4c643ebc4b42431f5efc4626b 100644 --- a/packages/mobile-ui-vue/components/navbar/src/property-config/navbar.property-config.ts +++ b/packages/mobile-ui-vue/components/navbar/src/property-config/navbar.property-config.ts @@ -1,8 +1,12 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty, ToolbarItemProperty } from "@farris/mobile-ui-vue/common"; +import ToolbarConverter from "@farris/mobile-ui-vue/dynamic-resolver/src/converter/right-toolbar.converter"; export class NavBarProperty extends BaseControlProperty { + private toolbarItemProperty: ToolbarItemProperty; constructor(componentId: string, designerHostService: any) { super(componentId, designerHostService); + this.toolbarItemProperty = new ToolbarItemProperty(componentId, designerHostService) + } public getPropertyConfig(propertyData: any) { // 基本信息 @@ -10,12 +14,35 @@ export class NavBarProperty extends BaseControlProperty { // 外观 this.propertyConfig.categories['appearance'] = this.getAppearanceConfig(propertyData); // 行为 - this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData); + this.propertyConfig.categories['behavior'] = this.getNavBarBehaviorConfig(propertyData); + this.propertyConfig.categories['rightToolbar'] = { + title: '工具栏', + $converter: ToolbarConverter, + properties: { + items: { + title: '右侧工具栏', + editor: { + type: "collection-property-editor", + textField: 'text', + modalTitle: '右侧工具栏编辑器', + onSelectionChange: ({ selectedData, propertyConfig }) => { + propertyConfig.value = this.toolbarItemProperty.getPropertyConfig(selectedData.value); + }, + defaultComponentSchema: { + id: 'button', + text: '按钮', + visible: true, + disabled: false + } + } + } + } + } return this.propertyConfig; } - private getBehaviorConfig(propertyData) { + private getNavBarBehaviorConfig(propertyData) { return { description: "基本信息", title: "行为", diff --git a/packages/mobile-ui-vue/components/navbar/src/schema/navbar.schema.json b/packages/mobile-ui-vue/components/navbar/src/schema/navbar.schema.json index 662ddd609020838bda3b4127bef6977f021623a6..d933a63793971fa17e46b7a18238878c9c1926fd 100644 --- a/packages/mobile-ui-vue/components/navbar/src/schema/navbar.schema.json +++ b/packages/mobile-ui-vue/components/navbar/src/schema/navbar.schema.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://farris-design.gitee.io/navbar.schema.json", "title": "navbar", - "description": "导航栏", + "description": "页面导航组件", "type": "object", "properties": { "id": { @@ -44,6 +44,9 @@ }, "onClickLeft": { "type": "string" + }, + "rightToolbar": { + "type": "object" } }, "events": [ @@ -54,8 +57,6 @@ "type" ], "ignore": [ - "id", - "type", "appearance" ] } \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/notify/src/index.tsx b/packages/mobile-ui-vue/components/notify/src/index.tsx index 85795cf297a56cb713c0ad57e262fc499e492bf2..26c7dcd03f9751a397f99afabcb1efeccfefea37 100644 --- a/packages/mobile-ui-vue/components/notify/src/index.tsx +++ b/packages/mobile-ui-vue/components/notify/src/index.tsx @@ -1,6 +1,6 @@ import FMNotify from './notify.component'; -import { isObject, inBrowser } from '@components/common'; -import { mountComponent, usePopupState } from '@components/common'; +import { isObject, inBrowser } from '@farris/mobile-ui-vue/common'; +import { mountComponent, usePopupState } from '@farris/mobile-ui-vue/common'; import { App } from 'vue'; let instance; let timer; diff --git a/packages/mobile-ui-vue/components/notify/src/notify.component.tsx b/packages/mobile-ui-vue/components/notify/src/notify.component.tsx index 7bec51d352ea14f945274303f679473ba2061146..3be1b9f363472e7ca062f4934f0296409680b90c 100644 --- a/packages/mobile-ui-vue/components/notify/src/notify.component.tsx +++ b/packages/mobile-ui-vue/components/notify/src/notify.component.tsx @@ -15,7 +15,7 @@ */ import { SetupContext, computed, defineComponent } from 'vue'; import { NotifyProps, notifyProps } from './notify.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; const name = 'fm-notify'; diff --git a/packages/mobile-ui-vue/components/number-input/index.ts b/packages/mobile-ui-vue/components/number-input/index.ts index 7b914dfea58da51850600d2d4f165f5a8e1a1283..3f43cf190a446bf5a2d9fcc5076f9fdc965339b2 100644 --- a/packages/mobile-ui-vue/components/number-input/index.ts +++ b/packages/mobile-ui-vue/components/number-input/index.ts @@ -1,6 +1,7 @@ -import { withInstall } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import NumberInputInstallless from './src/number-input.component'; -import { propsResolver } from './src/number-input.props'; +import { propsResolverGenerator } from './src/number-input.props'; +import NumberInputDesign from './src/designer/number-input.design.component'; export * from './src/number-input.props'; @@ -8,10 +9,8 @@ const NUMBER_INPUT_REGISTERED_NAME = 'number-input'; const NumberInput = withInstall(NumberInputInstallless); -NumberInput.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { - componentMap[NUMBER_INPUT_REGISTERED_NAME] = NumberInput; - propsResolverMap[NUMBER_INPUT_REGISTERED_NAME] = propsResolver; -}; +withRegister(NumberInput, { name: NUMBER_INPUT_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(NumberInput, { name: NUMBER_INPUT_REGISTERED_NAME, propsResolverGenerator, designerComponent: NumberInputDesign }); export { NumberInput }; export default NumberInput; diff --git a/packages/mobile-ui-vue/components/number-input/src/designer/number-input.design.component.tsx b/packages/mobile-ui-vue/components/number-input/src/designer/number-input.design.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d3d3f51dbbe142318da7b5777553eee702b623a9 --- /dev/null +++ b/packages/mobile-ui-vue/components/number-input/src/designer/number-input.design.component.tsx @@ -0,0 +1,30 @@ +import { defineComponent, inject, onMounted, ref, SetupContext } from 'vue'; + +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; +import { useDesignerRules } from './use-designer-rules'; +import { numberInputProps } from '../number-input.props'; +import InputGroup from '../..'; + +export default defineComponent({ + name: 'FmNunberInputDesign', + props: numberInputProps, + emits: [], + setup(props, context: SetupContext) { + const elementRef = ref(); + const designItemContext = inject('design-item-context') as DesignerItemContext; + const designerHostService = inject('designer-host-service'); + const designerRulesComposition = useDesignerRules(designItemContext, designerHostService); + const componentInstance = useDesignerComponent(elementRef, designItemContext, designerRulesComposition); + + onMounted(() => { + elementRef.value.componentInstance = componentInstance; + }); + + context.expose(componentInstance.value); + + + return () => ( + + ); + } +}); diff --git a/packages/mobile-ui-vue/components/number-input/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/number-input/src/designer/use-designer-rules.ts new file mode 100644 index 0000000000000000000000000000000000000000..4e6377b410c9572c22d3fde92c966e67701d2cf9 --- /dev/null +++ b/packages/mobile-ui-vue/components/number-input/src/designer/use-designer-rules.ts @@ -0,0 +1,15 @@ +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { NumberInputProperty } from "../property-config/number-input.property-config"; +export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { + + const schema = designItemContext.schema as ComponentSchema; + + // 构造属性配置方法 + function getPropsConfig(componentId: string, componentInstance: DesignerComponentInstance) { + const numberInputProps = new NumberInputProperty(componentId, designerHostService); + return numberInputProps.getPropertyConfig(schema, componentInstance); + } + + return { getPropsConfig } as UseDesignerRules; + +} diff --git a/packages/mobile-ui-vue/components/number-input/src/number-input.component.tsx b/packages/mobile-ui-vue/components/number-input/src/number-input.component.tsx index 5b1f2b1b7860c0f840475568f6bc28069ca5dfde..c17b190c06e536e4b8109eed3d452f3f45e4e4e0 100644 --- a/packages/mobile-ui-vue/components/number-input/src/number-input.component.tsx +++ b/packages/mobile-ui-vue/components/number-input/src/number-input.component.tsx @@ -15,8 +15,8 @@ */ import { defineComponent, SetupContext } from 'vue'; -import { useBem } from '@/components/common'; -import InputGroup from "@/components/input-group"; +import { useBem } from '@farris/mobile-ui-vue/common'; +import InputGroup from "@farris/mobile-ui-vue/input-group"; import { NUMBER_INPUT_NAME, numberInputProps, NumberInputProps } from './number-input.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/number-input/src/number-input.props.ts b/packages/mobile-ui-vue/components/number-input/src/number-input.props.ts index 836ba36b0af8cc5c307f6a260ccdeac978528593..fb1e2812957c89b687d23f527d03946465e89d54 100644 --- a/packages/mobile-ui-vue/components/number-input/src/number-input.props.ts +++ b/packages/mobile-ui-vue/components/number-input/src/number-input.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes } from 'vue'; -import { inputCommonProps } from '@/components/input-group'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import { inputCommonProps } from '@farris/mobile-ui-vue/input-group'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import numberInputSchema from './schema/number-input.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -15,4 +15,4 @@ export const numberInputProps = { export type NumberInputProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(numberInputProps, numberInputSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(numberInputProps, numberInputSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/number-input/src/property-config/number-input.property-config.ts b/packages/mobile-ui-vue/components/number-input/src/property-config/number-input.property-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..45e3182b0f97e8f0d93157e25e1a870337dc9519 --- /dev/null +++ b/packages/mobile-ui-vue/components/number-input/src/property-config/number-input.property-config.ts @@ -0,0 +1,30 @@ +import { InputBaseProperty } from "@farris/mobile-ui-vue/common"; + +export class NumberInputProperty extends InputBaseProperty { + + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } + + + getEditorProperties(propertyData: any) { + return this.getComponentConfig(propertyData, {}, { + precision: { + description: "", + title: "精度", + type: "number" + }, + max: { + description: "", + title: "最大值", + type: "number" + }, + min: { + description: "", + title: "最小值", + type: "number" + }, + }); + } + +} diff --git a/packages/mobile-ui-vue/components/number-input/src/schema/number-input.schema.json b/packages/mobile-ui-vue/components/number-input/src/schema/number-input.schema.json index 5efd6ace2fea342015860a35dfdbba641ae5895f..77d8162dab941d6ad8a96bcbf8e5aad19a9defe3 100644 --- a/packages/mobile-ui-vue/components/number-input/src/schema/number-input.schema.json +++ b/packages/mobile-ui-vue/components/number-input/src/schema/number-input.schema.json @@ -10,9 +10,9 @@ "type": "string" }, "type": { - "description": "类型", + "description": "控件类型", "type": "string", - "default": "textarea" + "default": "number-input" }, "appearance": { "description": "外观", diff --git a/packages/mobile-ui-vue/components/number-input/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/number-input/src/schema/schema-mapper.ts index d1c21abde8bc365f647bada2718e821e5008a2b0..42b3a02141cbb40a799489f47e0c50df2a3e29f9 100644 --- a/packages/mobile-ui-vue/components/number-input/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/number-input/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/number-input/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/number-input/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/number-input/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/number-input/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/overlay/index.ts b/packages/mobile-ui-vue/components/overlay/index.ts index 766c50712f793888645c17f0aab415818c7fae92..1216d00a00ea632818515dd3b8565364833548c0 100644 --- a/packages/mobile-ui-vue/components/overlay/index.ts +++ b/packages/mobile-ui-vue/components/overlay/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import OverlayInstallless from './src/overlay.component'; const Overlay = withInstall(OverlayInstallless); diff --git a/packages/mobile-ui-vue/components/overlay/src/overlay.component.tsx b/packages/mobile-ui-vue/components/overlay/src/overlay.component.tsx index d5a2ebe26c310f250826f9b8e034b4e6180ed8cc..da3eeecaeb11577f21e4c19aa8b865a69add7b98 100644 --- a/packages/mobile-ui-vue/components/overlay/src/overlay.component.tsx +++ b/packages/mobile-ui-vue/components/overlay/src/overlay.component.tsx @@ -15,7 +15,7 @@ */ import { computed, CSSProperties, defineComponent, SetupContext, Transition } from 'vue'; -import { preventDefault, noop, useBem, useLazyRender } from '@components/common'; +import { preventDefault, noop, useBem, useLazyRender } from '@farris/mobile-ui-vue/common'; import { OVERLAY_NAME, OverlayProps, overlayProps } from './overlay.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/page-body-container/index.ts b/packages/mobile-ui-vue/components/page-body-container/index.ts index 7d141367928f7dd9be645428318e1ec20ac536f4..40d7e8e998acbd35c5eb1202a4075321c13100a6 100644 --- a/packages/mobile-ui-vue/components/page-body-container/index.ts +++ b/packages/mobile-ui-vue/components/page-body-container/index.ts @@ -14,22 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import PageBodyContainerInstallless from './src/page-body-container.component'; import PageBodyContainerDesign from './src/designer/page-body-container.design.component'; -import { propsResolver } from './src/page-body-container.props'; +import { propsResolverGenerator } from './src/page-body-container.props'; const PAGE_BODY_CONTAINER_REGISTER_NAME = 'page-body-container'; const PageBodyContainer = withInstall(PageBodyContainerInstallless); -PageBodyContainer.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record): void => { +PageBodyContainer.register = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext): void => { componentMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = PageBodyContainer; - propsResolverMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = propsResolver; + propsResolverMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = propsResolverGenerator(registerContext); }; -PageBodyContainer.registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record): void => { +PageBodyContainer.registerDesigner = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record,registerContext: RegisterContext): void => { componentMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = PageBodyContainerDesign; - propsResolverMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = propsResolver; + propsResolverMap[PAGE_BODY_CONTAINER_REGISTER_NAME] = propsResolverGenerator(registerContext); }; export * from './src/page-body-container.props'; diff --git a/packages/mobile-ui-vue/components/page-body-container/src/designer/page-body-container.design.component.tsx b/packages/mobile-ui-vue/components/page-body-container/src/designer/page-body-container.design.component.tsx index 8662cedfd43d3cc5621e5e9c568b0cff86a81b47..6a35ae959782306737902bf343caa37898f39846 100644 --- a/packages/mobile-ui-vue/components/page-body-container/src/designer/page-body-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/page-body-container/src/designer/page-body-container.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, onMounted, ref } from 'vue'; import { PageBodyContainerProps, pageBodyContainerProps } from '../page-body-container.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FmPageBodyContainerDesign', diff --git a/packages/mobile-ui-vue/components/page-body-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/page-body-container/src/designer/use-designer-rules.ts index f5fd184a2498b8e148e167fb74f8bb4c459eb941..509cfa3d619f9e406e546efc709945e91bb6e393 100644 --- a/packages/mobile-ui-vue/components/page-body-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/page-body-container/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { nextTick, ref } from "vue"; import { PAGE_BODY_CONTAINER_NAME } from '../page-body-container.props'; -import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "@/components/designer-canvas/src/composition/types"; -import { DesignerItemContext } from "@/components/designer-canvas"; +import { DesignerHostService, DraggingResolveContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DesignerItemContext } from "@farris/mobile-ui-vue/common"; import { PageBodyContainerProperty } from "../property-config/page-body-container.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.component.tsx b/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.component.tsx index b1f6a581a473e4e3d57aa73fc1e37d770fe81c00..f62aaaee016c980a0b78087f8f2e913ef1086287 100644 --- a/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.component.tsx +++ b/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.component.tsx @@ -1,6 +1,6 @@ import { SetupContext, defineComponent, computed } from 'vue'; import { PAGE_BODY_CONTAINER_NAME, PageBodyContainerProps, pageBodyContainerProps } from './page-body-container.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: PAGE_BODY_CONTAINER_NAME, diff --git a/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.props.ts b/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.props.ts index 4a4089bf75c9670616f7c447666b0f14751b8095..6c98c831eb5a517edbeba635dfc2d59bbb9c8fd0 100644 --- a/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.props.ts +++ b/packages/mobile-ui-vue/components/page-body-container/src/page-body-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import pageBodyContainerSchema from './schema/page-body-container.schema.json'; import { schemaResolver } from './schema/schema-resolver'; @@ -12,7 +12,7 @@ export const pageBodyContainerProps = { export type PageBodyContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( pageBodyContainerProps, pageBodyContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/page-body-container/src/property-config/page-body-container.property-config.ts b/packages/mobile-ui-vue/components/page-body-container/src/property-config/page-body-container.property-config.ts index 077bd5883ae86e04dbd548eb065661d440485675..3ffa3e43166ea42f20aa7384de312a8c98e4d069 100644 --- a/packages/mobile-ui-vue/components/page-body-container/src/property-config/page-body-container.property-config.ts +++ b/packages/mobile-ui-vue/components/page-body-container/src/property-config/page-body-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class PageBodyContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/page-container/index.ts b/packages/mobile-ui-vue/components/page-container/index.ts index 4438af465e26fbc511fc2416655c2d2079cfc3e3..0737451b819d8807afc0b86abdc2e558329e982c 100644 --- a/packages/mobile-ui-vue/components/page-container/index.ts +++ b/packages/mobile-ui-vue/components/page-container/index.ts @@ -14,26 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import PageContainerInstallless from './src/page-container.component'; import PageContainerDesign from './src/designer/page-container.design.component'; -import { propsResolver } from './src/page-container.props'; +import { propsResolverGenerator } from './src/page-container.props'; const PAGE_CONTAINER_REGISTERED_NAME = 'page-container'; const PageContainer = withInstall(PageContainerInstallless); PageContainer.register = ( - componentMap: Record, propsResolverMap: Record, configResolverMap: Record + componentMap: Record, propsResolverMap: Record, + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext ): void => { componentMap[PAGE_CONTAINER_REGISTERED_NAME] = PageContainer; - propsResolverMap[PAGE_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[PAGE_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; PageContainer.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, configResolverMap: Record + componentMap: Record, propsResolverMap: Record, + configresolverMap: Record,registerContext: RegisterContext ): void => { componentMap[PAGE_CONTAINER_REGISTERED_NAME] = PageContainerDesign; - propsResolverMap[PAGE_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[PAGE_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; export * from './src/page-container.props'; diff --git a/packages/mobile-ui-vue/components/page-container/src/designer/page-container.design.component.tsx b/packages/mobile-ui-vue/components/page-container/src/designer/page-container.design.component.tsx index f265911ef324b16b98bb6166fda208a354dfb087..c3114429478b7e420040c1ba5b1a42d8bb465534 100644 --- a/packages/mobile-ui-vue/components/page-container/src/designer/page-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/page-container/src/designer/page-container.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, onMounted, ref } from 'vue'; import { PageContainerProps, pageContainerProps } from '../page-container.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FmPageContainerDesign', diff --git a/packages/mobile-ui-vue/components/page-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/page-container/src/designer/use-designer-rules.ts index dd317403bccd6f652be2665de7bc03c40596862b..a7220a9cb34b3e9e7228cb44ff8a482d407422ca 100644 --- a/packages/mobile-ui-vue/components/page-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/page-container/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { ref } from "vue"; import { PAGE_CONTAINER_NAME } from '../page-container.props'; -import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; import { PageContainerProperty } from "../property-config/page-container.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/page-container/src/page-container.component.tsx b/packages/mobile-ui-vue/components/page-container/src/page-container.component.tsx index 0e6e53e2d44b533e657d76bf781f3be932ccf52e..fd265a053984d6c7b12ddccd674cf714772464e9 100644 --- a/packages/mobile-ui-vue/components/page-container/src/page-container.component.tsx +++ b/packages/mobile-ui-vue/components/page-container/src/page-container.component.tsx @@ -1,6 +1,6 @@ import { SetupContext, defineComponent, computed } from 'vue'; import { PAGE_CONTAINER_NAME, PageContainerProps, pageContainerProps } from './page-container.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: PAGE_CONTAINER_NAME, diff --git a/packages/mobile-ui-vue/components/page-container/src/page-container.props.ts b/packages/mobile-ui-vue/components/page-container/src/page-container.props.ts index c7a084830ebdf8aac2c7e74799796862e25720ea..fb3003a9af19f9472ac246a3d5ce832ae44f334e 100644 --- a/packages/mobile-ui-vue/components/page-container/src/page-container.props.ts +++ b/packages/mobile-ui-vue/components/page-container/src/page-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import pageContainerSchema from './schema/page-container.schema.json'; import { schemaResolver } from './schema/schema-resolver'; @@ -12,7 +12,7 @@ export const pageContainerProps = { export type PageContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( pageContainerProps, pageContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/page-container/src/page-container.scss b/packages/mobile-ui-vue/components/page-container/src/page-container.scss index cfc7bc5443e35882b5ba7ee58cee70c2ee8f4ac4..36231eade9aae0319f7f0319b7fc72695e0d57d4 100644 --- a/packages/mobile-ui-vue/components/page-container/src/page-container.scss +++ b/packages/mobile-ui-vue/components/page-container/src/page-container.scss @@ -10,4 +10,17 @@ right: 0; bottom: 0; left: 0; +} + +.fm-page-container .drag-container { + display: inherit; + flex-direction: inherit; + flex-shrink: 1; + flex-grow: 1; + flex-basis: 0%; + flex-wrap: inherit; + justify-content: inherit; + align-items: inherit; + width: 100%; + overflow: inherit } \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/page-container/src/property-config/page-container.property-config.ts b/packages/mobile-ui-vue/components/page-container/src/property-config/page-container.property-config.ts index 9771ba1d932902554231b53f84448b05e84f9579..d36a043afa00929822464ef7d45fd535744d42ea 100644 --- a/packages/mobile-ui-vue/components/page-container/src/property-config/page-container.property-config.ts +++ b/packages/mobile-ui-vue/components/page-container/src/property-config/page-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class PageContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/page-footer-container/index.ts b/packages/mobile-ui-vue/components/page-footer-container/index.ts index e8cec7710aed0fbbf32342638ae21eb8a8d8dc72..2ad2032a67341c2053e4573b709d93255aa13ea0 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/index.ts +++ b/packages/mobile-ui-vue/components/page-footer-container/index.ts @@ -14,28 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import PageFooterContainerInstallless from './src/page-footer-container.component'; import PageFooterContainerDesign from './src/designer/page-footer-container.design.component'; -import { propsResolver } from './src/page-footer-container.props'; +import { propsResolverGenerator } from './src/page-footer-container.props'; const COMPONENT_TYPE = 'page-footer-container'; const PageFooterContainer = withInstall(PageFooterContainerInstallless); PageFooterContainer.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext ): void => { componentMap[COMPONENT_TYPE] = PageFooterContainer; - propsResolverMap[COMPONENT_TYPE] = propsResolver; + propsResolverMap[COMPONENT_TYPE] = propsResolverGenerator(registerContext); }; PageFooterContainer.registerDesigner = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record + configresolverMap: Record,registerContext: RegisterContext ): void => { componentMap[COMPONENT_TYPE] = PageFooterContainerDesign; - propsResolverMap[COMPONENT_TYPE] = propsResolver; + propsResolverMap[COMPONENT_TYPE] = propsResolverGenerator(registerContext); }; export * from './src/page-footer-container.props'; diff --git a/packages/mobile-ui-vue/components/page-footer-container/src/designer/page-footer-container.design.component.tsx b/packages/mobile-ui-vue/components/page-footer-container/src/designer/page-footer-container.design.component.tsx index 8a2a197866585921e45999924c0bcb8bac67f7ac..22c581508dc7b5239827e274180caa3c596cf360 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/src/designer/page-footer-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/page-footer-container/src/designer/page-footer-container.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, onMounted, ref } from 'vue'; import { PageFooterContainerProps, pageFooterContainerProps } from '../page-footer-container.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FmPageFooterContainerDesign', diff --git a/packages/mobile-ui-vue/components/page-footer-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/page-footer-container/src/designer/use-designer-rules.ts index d3d813ebed1d0b7679db289542a63ad0794d80e8..00e12a993f22f36bc38113d40812c283c7d94bf9 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/page-footer-container/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { ref } from "vue"; import { PAGE_FOOTER_CONTAINER_NAME } from '../page-footer-container.props'; -import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { DesignerHostService, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; import { PageFooterContainerProperty } from "../property-config/page-footer-container.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService?: DesignerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.component.tsx b/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.component.tsx index 49b858e2b322494e495a9970802b1521a8904588..4afbccd3ca58348c7530416e1d0e519775fdc53b 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.component.tsx +++ b/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.component.tsx @@ -1,6 +1,6 @@ import { SetupContext, defineComponent, computed } from 'vue'; import { PAGE_FOOTER_CONTAINER_NAME, PageFooterContainerProps, pageFooterContainerProps } from './page-footer-container.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: PAGE_FOOTER_CONTAINER_NAME, diff --git a/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.props.ts b/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.props.ts index 79bc601420aaddff5d640050bc5f5d5e9e38e0be..4b16652f2d6068fab32e1f0a75e214e42fb45794 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.props.ts +++ b/packages/mobile-ui-vue/components/page-footer-container/src/page-footer-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import pageFooterContainerSchema from './schema/page-footer-container.schema.json'; import { schemaResolver } from './schema/schema-resolver'; @@ -12,7 +12,7 @@ export const pageFooterContainerProps = { export type PageFooterContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( pageFooterContainerProps, pageFooterContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/page-footer-container/src/property-config/page-footer-container.property-config.ts b/packages/mobile-ui-vue/components/page-footer-container/src/property-config/page-footer-container.property-config.ts index 066b9d66ca2472299e8a838d51892ec6685f7e76..47fe8ee5999109109724912e08eecb3165ce5386 100644 --- a/packages/mobile-ui-vue/components/page-footer-container/src/property-config/page-footer-container.property-config.ts +++ b/packages/mobile-ui-vue/components/page-footer-container/src/property-config/page-footer-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class PageFooterContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/page-header-container/index.ts b/packages/mobile-ui-vue/components/page-header-container/index.ts index 1a36319a7ec2e3110d255cb92a5f9ec6977215f4..37dd643a72632cb022ad25bd25692be3ab645c5e 100644 --- a/packages/mobile-ui-vue/components/page-header-container/index.ts +++ b/packages/mobile-ui-vue/components/page-header-container/index.ts @@ -14,27 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import PageHeaderContainerInstallless from './src/page-header-container.component'; import PageHeaderContainerDesign from './src/designer/page-header-container.design.component'; -import { propsResolver } from './src/page-header-container.props'; +import { propsResolverGenerator } from './src/page-header-container.props'; const PAGE_HEADER_CONTAINER_REGISTERED_NAME = 'page-header-container'; const PageHeaderContainer = withInstall(PageHeaderContainerInstallless); PageHeaderContainer.register = ( componentMap: Record, propsResolverMap: Record, - configResolverMap: Record + configresolverMap: Record, resolverMap: Record, registerContext: RegisterContext ): void => { componentMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = PageHeaderContainer; - propsResolverMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; PageHeaderContainer.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, configResolverMap: Record + componentMap: Record, propsResolverMap: Record, + configresolverMap: Record,registerContext: RegisterContext ): void => { componentMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = PageHeaderContainerDesign; - propsResolverMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = propsResolver; + propsResolverMap[PAGE_HEADER_CONTAINER_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; export * from './src/page-header-container.props'; diff --git a/packages/mobile-ui-vue/components/page-header-container/src/designer/page-header-container.design.component.tsx b/packages/mobile-ui-vue/components/page-header-container/src/designer/page-header-container.design.component.tsx index b43faef2fb8f4dbfbaa89a1a2d296edfdf04b3f3..0f354e8dd11850bf48437b2db722ebaf12ef295e 100644 --- a/packages/mobile-ui-vue/components/page-header-container/src/designer/page-header-container.design.component.tsx +++ b/packages/mobile-ui-vue/components/page-header-container/src/designer/page-header-container.design.component.tsx @@ -1,7 +1,7 @@ import { SetupContext, defineComponent, inject, onMounted, ref } from 'vue'; import { PageHeaderContainerProps, pageHeaderContainerProps } from '../page-header-container.props'; import { useDesignerRules } from './use-designer-rules'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; export default defineComponent({ name: 'FmPageHeaderContainerDesign', diff --git a/packages/mobile-ui-vue/components/page-header-container/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/page-header-container/src/designer/use-designer-rules.ts index 9833f1936a97dcc6a8f82ab914f72311600699f4..a2279ec5615bf3c3208279f031da893fe54490fe 100644 --- a/packages/mobile-ui-vue/components/page-header-container/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/page-header-container/src/designer/use-designer-rules.ts @@ -1,7 +1,7 @@ import { ref } from "vue"; import { PAGE_HEADER_CONTAINER_NAME } from '../page-header-container.props'; -import { ComponentSchema, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; -import { DraggingResolveContext } from "@/components/designer-canvas/src/composition/types"; +import { ComponentSchema, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; +import { DraggingResolveContext } from "@farris/mobile-ui-vue/common"; import { PageHeaderContainerProperty } from "../property-config/page-header-container.property-config"; export function useDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.component.tsx b/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.component.tsx index ee9eebed78b8daa1588b405bec56185f414f65be..e9d513db678837235faf8d34b259740638662c3d 100644 --- a/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.component.tsx +++ b/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.component.tsx @@ -1,6 +1,6 @@ import { SetupContext, defineComponent, computed } from 'vue'; import { PAGE_HEADER_CONTAINER_NAME, PageHeaderContainerProps, pageHeaderContainerProps } from './page-header-container.props'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: PAGE_HEADER_CONTAINER_NAME, diff --git a/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.props.ts b/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.props.ts index 15901f23a8d81d15cb9711aa7fc7d72a76febbe5..8b7ab403b1d9e0cf9fc26ddc15bed6d43c3afe06 100644 --- a/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.props.ts +++ b/packages/mobile-ui-vue/components/page-header-container/src/page-header-container.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; +import { getPropsResolverGenerator } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import pageHeaderContainerSchema from './schema/page-header-container.schema.json'; import { schemaResolver } from './schema/schema-resolver'; @@ -12,7 +12,7 @@ export const pageHeaderContainerProps = { export type PageHeaderContainerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( pageHeaderContainerProps, pageHeaderContainerSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/page-header-container/src/property-config/page-header-container.property-config.ts b/packages/mobile-ui-vue/components/page-header-container/src/property-config/page-header-container.property-config.ts index 9100e1f3740825514773ede9f50bc06c07f026c2..a292e7834f42044bc6e875bd23c7d8aae7d8740f 100644 --- a/packages/mobile-ui-vue/components/page-header-container/src/property-config/page-header-container.property-config.ts +++ b/packages/mobile-ui-vue/components/page-header-container/src/property-config/page-header-container.property-config.ts @@ -1,4 +1,4 @@ -import { BaseControlProperty } from "@/components/property-panel"; +import { BaseControlProperty } from "@farris/mobile-ui-vue/common"; export class PageHeaderContainerProperty extends BaseControlProperty { constructor(componentId: string, designerHostService: any) { diff --git a/packages/mobile-ui-vue/components/picker-group/index.ts b/packages/mobile-ui-vue/components/picker-group/index.ts index 81940c1b01254769baa920ccfa40fccb2e4a43b6..67216c938ae5014d65c5846f96fbf2dcfb1d698e 100644 --- a/packages/mobile-ui-vue/components/picker-group/index.ts +++ b/packages/mobile-ui-vue/components/picker-group/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import PickerGroupInstallless from "./src/picker-group.component"; const PickerGroup = withInstall(PickerGroupInstallless); diff --git a/packages/mobile-ui-vue/components/picker-group/src/composition/use-picker-group-context.ts b/packages/mobile-ui-vue/components/picker-group/src/composition/use-picker-group-context.ts index eb00f48bc6ea6006697935396656407eec2808ce..ab37f419c70579c8a36151fcd036e23780b054b6 100644 --- a/packages/mobile-ui-vue/components/picker-group/src/composition/use-picker-group-context.ts +++ b/packages/mobile-ui-vue/components/picker-group/src/composition/use-picker-group-context.ts @@ -1,6 +1,6 @@ import { onMounted, reactive, ref, watch } from 'vue'; -import { useChildrenContexts } from '@components/common'; -import { GroupContext, GroupItem, PickerContext, PickerGroupKey } from '@/components/picker'; +import { useChildrenContexts } from '@farris/mobile-ui-vue/common'; +import { GroupContext, GroupItem, PickerContext, PickerGroupKey } from '@farris/mobile-ui-vue/picker'; export const usePickerGroupContext = () => { const innerValue = ref(); diff --git a/packages/mobile-ui-vue/components/picker-group/src/picker-group.component.tsx b/packages/mobile-ui-vue/components/picker-group/src/picker-group.component.tsx index db507927ccff46ca61fdd532b1d1e2a2127185c9..b85ad1b4e23eb549b5913b57bec62e8a4e2c76e0 100644 --- a/packages/mobile-ui-vue/components/picker-group/src/picker-group.component.tsx +++ b/packages/mobile-ui-vue/components/picker-group/src/picker-group.component.tsx @@ -1,6 +1,6 @@ import { defineComponent } from 'vue'; -import { useBem } from '@components/common'; -import { TabBar } from '@components/tab-bar'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { TabBar } from '@farris/mobile-ui-vue/tab-bar'; import { pickerGroupProps, PickerGroupProps, PICKER_GROUP_NAME } from './picker-group.props'; import { usePickerGroupContext } from './composition/use-picker-group-context'; diff --git a/packages/mobile-ui-vue/components/picker/index.ts b/packages/mobile-ui-vue/components/picker/index.ts index 1683a20794b467ccc67f4a2c6c446c7ea34242c0..ee28dbf6b83d6da87d20474a248be6a58798c9d0 100644 --- a/packages/mobile-ui-vue/components/picker/index.ts +++ b/packages/mobile-ui-vue/components/picker/index.ts @@ -1,7 +1,7 @@ -import { withInstall, withRegister, withRegisterDesigner } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import PickerPanelInstallless from "./src/picker-panel.component"; import PickerInstallless from "./src/picker.component"; -import { propsResolver } from './src/picker.props'; +import { propsResolverGenerator } from './src/picker.props'; import EnumFieldInputDesign from './src/designer/enum-field-input.design.component'; export * from './src/picker-panel.props'; @@ -19,8 +19,8 @@ const PICKER_REGISTERED_NAME = 'picker'; const Picker = withInstall(PickerInstallless); // 注册运行时及设计时 -withRegister(Picker, { name: PICKER_REGISTERED_NAME, propsResolver }); -withRegisterDesigner(Picker, { name: PICKER_REGISTERED_NAME, propsResolver, designerComponent: EnumFieldInputDesign }); +withRegister(Picker, { name: PICKER_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(Picker, { name: PICKER_REGISTERED_NAME, propsResolverGenerator, designerComponent: EnumFieldInputDesign }); export { Picker, PickerPanel }; export default Picker; diff --git a/packages/mobile-ui-vue/components/picker/src/components/column.component.tsx b/packages/mobile-ui-vue/components/picker/src/components/column.component.tsx index 47495b4e140c03364aeeeb93fb2e644813dc9555..28af569c71e849d38349c2dad4386971a30f3f38 100644 --- a/packages/mobile-ui-vue/components/picker/src/components/column.component.tsx +++ b/packages/mobile-ui-vue/components/picker/src/components/column.component.tsx @@ -1,5 +1,5 @@ import { CSSProperties, SetupContext, computed, defineComponent } from 'vue'; -import { addUnit, useBem } from '@components/common'; +import { addUnit, useBem } from '@farris/mobile-ui-vue/common'; import { PICKER_PANEL_NAME } from '../picker-panel.props'; import { useColumnTouch } from '../composition'; import { ColumnProps, columnProps } from './column.props'; diff --git a/packages/mobile-ui-vue/components/picker/src/composition/use-column-touch.ts b/packages/mobile-ui-vue/components/picker/src/composition/use-column-touch.ts index a7787aa9cf9618b9ae385755c95f92a0ce365c82..52182b433e7002c641826acb006288943a2acf04 100644 --- a/packages/mobile-ui-vue/components/picker/src/composition/use-column-touch.ts +++ b/packages/mobile-ui-vue/components/picker/src/composition/use-column-touch.ts @@ -1,5 +1,5 @@ import { SetupContext, reactive, watch } from 'vue'; -import { getValue, preventDefault, useTouch, useMonmentum } from '@components/common'; +import { getValue, preventDefault, useTouch, useMonmentum } from '@farris/mobile-ui-vue/common'; import { ColumnProps } from '../components/column.props'; import { ColumnTransition, ColumnTranslate, UseColumnTouch, ValueType } from '../types'; diff --git a/packages/mobile-ui-vue/components/picker/src/composition/use-columns.ts b/packages/mobile-ui-vue/components/picker/src/composition/use-columns.ts index 1e8dde4361738a4ac785ed241aed5ea81de2f3d7..688bdbdbfb019cb8d750bf99ae693e86afaf0a75 100644 --- a/packages/mobile-ui-vue/components/picker/src/composition/use-columns.ts +++ b/packages/mobile-ui-vue/components/picker/src/composition/use-columns.ts @@ -1,5 +1,5 @@ import { computed, } from 'vue'; -import { isArray, isFunction, isObject } from '@components/common'; +import { isArray, isFunction, isObject } from '@farris/mobile-ui-vue/common'; import { PickerPanelProps } from '../picker-panel.props'; import { Column, ColumnItem, Columns, UseColumns, UsePickerState, ValueType } from '../types'; diff --git a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-context.ts b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-context.ts index 6af411f4e0de29fd71aa7c6bd315413a3c6fdc08..455c2ec4581240869bed1869668bbef4acb67ad6 100644 --- a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-context.ts +++ b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-context.ts @@ -1,5 +1,5 @@ import { getCurrentInstance, watch } from 'vue'; -import { random, useParentContext } from '@components/common'; +import { random, useParentContext } from '@farris/mobile-ui-vue/common'; import { PickerPanelProps } from '../picker-panel.props'; import { GroupContext, PickerContext } from '../types'; diff --git a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-state.ts b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-state.ts index 8625d6eb6e142136bc96cdb2b6dddef387e20892..b03418301904dfb7d59a3205116c4d3127c48c62 100644 --- a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-state.ts +++ b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-panel-state.ts @@ -1,5 +1,5 @@ import { ref, watch } from 'vue'; -import { isArray, isDef, isString } from '@components/common'; +import { isArray, isDef, isString } from '@farris/mobile-ui-vue/common'; import { PickerPanelProps } from '../picker-panel.props'; import { UsePickerState, ValueType } from '../types'; diff --git a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-state.ts b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-state.ts index 380f3235416c61203e481aacd518875c012cda64..8cc2f6b2cc9b40cd5420392c4c3890706a77cc0f 100644 --- a/packages/mobile-ui-vue/components/picker/src/composition/use-picker-state.ts +++ b/packages/mobile-ui-vue/components/picker/src/composition/use-picker-state.ts @@ -1,6 +1,6 @@ import { SetupContext, onMounted, shallowRef } from 'vue'; -import { ButtonEditProps, useButtonEditProps } from '@/components/button-edit'; -import { ColumnItem } from '@/components/picker-panel'; +import { ButtonEditProps, useButtonEditProps } from '@farris/mobile-ui-vue/button-edit'; +import { ColumnItem } from '@farris/mobile-ui-vue/picker'; export const usePickerInputState = ( props: Omit, @@ -17,7 +17,9 @@ export const usePickerInputState = ( }; onMounted(() => { - updateInputValue(); + if((props as any).modelValue) { + updateInputValue(); + } }); const handleConfirm = (value: any[]) => { diff --git a/packages/mobile-ui-vue/components/picker/src/designer/enum-field-input.design.component.tsx b/packages/mobile-ui-vue/components/picker/src/designer/enum-field-input.design.component.tsx index 3f8befcd97a2175cd8e99ded4091b430fb7184e4..407757aae8c84c7a38d1f3cee448478202a39218 100644 --- a/packages/mobile-ui-vue/components/picker/src/designer/enum-field-input.design.component.tsx +++ b/packages/mobile-ui-vue/components/picker/src/designer/enum-field-input.design.component.tsx @@ -15,7 +15,7 @@ * limitations under the License. */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; import { pickerProps } from '../picker.props'; import Picker from '../picker.component'; import { useEnumFieldDesignerRules } from './use-designer-rules';; diff --git a/packages/mobile-ui-vue/components/picker/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/picker/src/designer/use-designer-rules.ts index a687e9a9afaea331c07a9c3b6d59dbe9c8d257fe..039b784430ea755459eff9a2a7f74b8b1d0307b1 100644 --- a/packages/mobile-ui-vue/components/picker/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/picker/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { EnumFieldInputProperty } from "../property-config/enum-field-input.property-config"; export function useEnumFieldDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/picker/src/picker-panel.component.tsx b/packages/mobile-ui-vue/components/picker/src/picker-panel.component.tsx index ee373d5939489df210286fa3013d99fe3bdd6f0a..0b4c1d6dd4ee0bd6072938e1f1670a2f39d34879 100644 --- a/packages/mobile-ui-vue/components/picker/src/picker-panel.component.tsx +++ b/packages/mobile-ui-vue/components/picker/src/picker-panel.component.tsx @@ -1,5 +1,5 @@ import { CSSProperties, computed, defineComponent } from 'vue'; -import { useBem, addUnit } from '@components/common'; +import { useBem, addUnit } from '@farris/mobile-ui-vue/common'; import { pickerPanelProps, PICKER_PANEL_NAME } from './picker-panel.props'; import { useColumns, usePickerState, usePickerContext } from './composition'; import ColumnComponent from './components/column.component'; diff --git a/packages/mobile-ui-vue/components/picker/src/picker.component.tsx b/packages/mobile-ui-vue/components/picker/src/picker.component.tsx index f5f5a52680c6c6277793ec64b2a04772ee621f3e..4fecad1e55cca6186f49d9c59ee69199ef7b6e48 100644 --- a/packages/mobile-ui-vue/components/picker/src/picker.component.tsx +++ b/packages/mobile-ui-vue/components/picker/src/picker.component.tsx @@ -1,6 +1,6 @@ import { computed, defineComponent} from 'vue'; -import { ButtonEdit } from '@/components/button-edit'; -import { useBem } from '@components/common'; +import { ButtonEdit } from '@farris/mobile-ui-vue/button-edit'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { pickerProps, PICKER_NAME } from './picker.props'; import { usePickerInputState } from './composition/use-picker-state'; import PickerPanel from './picker-panel.component'; diff --git a/packages/mobile-ui-vue/components/picker/src/picker.props.ts b/packages/mobile-ui-vue/components/picker/src/picker.props.ts index b9597c25cfbc3c020eaed82d41e060f5b54fdd30..69dcab00d4752fd010e3ea4d52e347e8d8cc6b73 100644 --- a/packages/mobile-ui-vue/components/picker/src/picker.props.ts +++ b/packages/mobile-ui-vue/components/picker/src/picker.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes } from 'vue'; -import { buttonEditProps } from '@/components/button-edit'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import { buttonEditProps } from '@farris/mobile-ui-vue/button-edit'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import pickerSchema from './schema/picker.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -10,9 +10,10 @@ export const PICKER_NAME = 'FmPicker'; export const pickerProps = { ...buttonEditProps, - ...pickerPanelProps + ...pickerPanelProps, + placeholder: { type: String, default: '请选择' }, }; export type PickerProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(pickerProps, pickerSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(pickerProps, pickerSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/picker/src/property-config/enum-field-input.property-config.ts b/packages/mobile-ui-vue/components/picker/src/property-config/enum-field-input.property-config.ts index 4c76243470705fefbe1b047b812a2ab1f8a13c9d..3e7ddf5ebf373febbb0c81c76a57787703ccec60 100644 --- a/packages/mobile-ui-vue/components/picker/src/property-config/enum-field-input.property-config.ts +++ b/packages/mobile-ui-vue/components/picker/src/property-config/enum-field-input.property-config.ts @@ -1,4 +1,4 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { InputBaseProperty } from "@farris/mobile-ui-vue/common"; export class EnumFieldInputProperty extends InputBaseProperty { diff --git a/packages/mobile-ui-vue/components/picker/src/schema/picker.schema.json b/packages/mobile-ui-vue/components/picker/src/schema/picker.schema.json index 697dadb0045e5c7e8610477722c0b296db305218..19a83d6350b111846061733e7c5984442b7755bb 100644 --- a/packages/mobile-ui-vue/components/picker/src/schema/picker.schema.json +++ b/packages/mobile-ui-vue/components/picker/src/schema/picker.schema.json @@ -12,7 +12,7 @@ "type": { "description": "控件类型", "type": "string", - "default": "enum-field" + "default": "picker" }, "appearance": { "description": "外观", diff --git a/packages/mobile-ui-vue/components/picker/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/picker/src/schema/schema-mapper.ts index 5eaaae80f943d7d2e6b8cec1c35de3afafa8dc49..502f2d482d48f682ef804f43ecba5027cc4ae8bb 100644 --- a/packages/mobile-ui-vue/components/picker/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/picker/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance, resolveDataPicker } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance, resolveDataPicker } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/picker/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/picker/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/picker/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/picker/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/picker/src/types/index.ts b/packages/mobile-ui-vue/components/picker/src/types/index.ts index b42d6b7d2008a54a59244148dd3e9d59906af817..a786d0d5bc82b1690680fb00129c7db37dffde30 100644 --- a/packages/mobile-ui-vue/components/picker/src/types/index.ts +++ b/packages/mobile-ui-vue/components/picker/src/types/index.ts @@ -22,7 +22,7 @@ export interface UsePickerState { export interface UseColumns { columns: ComputedRef; - getPickeds: () => ColumnItem[]; + getPickeds: () => (ValueType | ColumnItem)[]; getValue: () => ValueType[]; getTextValue: () => string; setDefaultValue: () => void; diff --git a/packages/mobile-ui-vue/components/popover/index.ts b/packages/mobile-ui-vue/components/popover/index.ts index 3c73728b5cc01bee62b14bfbef4b5ef068169d3b..1856b5e15c5010b1b00d6bb17e8017c6bdc01d0f 100644 --- a/packages/mobile-ui-vue/components/popover/index.ts +++ b/packages/mobile-ui-vue/components/popover/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import PopoverInstallless from './src/popover.component'; const Popover = withInstall(PopoverInstallless); diff --git a/packages/mobile-ui-vue/components/popover/src/composition/use-position.ts b/packages/mobile-ui-vue/components/popover/src/composition/use-position.ts index 9f771e2845abef25d3f775dbd4da0be68469d32c..71379b3fd0aef1d308db15210a1602d2bfccaf50 100644 --- a/packages/mobile-ui-vue/components/popover/src/composition/use-position.ts +++ b/packages/mobile-ui-vue/components/popover/src/composition/use-position.ts @@ -1,6 +1,6 @@ import { Ref, SetupContext, ref, watch, computed, CSSProperties } from 'vue'; import { computePosition, Placement, offset, flip, shift, size, arrow, autoPlacement, autoUpdate } from '@floating-ui/dom'; -import { isNumber } from '@/components/common'; +import { isNumber } from '@farris/mobile-ui-vue/common'; import { PopoverProps } from '../popover.props'; import { PopoverPlacement, EffectiveSide } from './types'; diff --git a/packages/mobile-ui-vue/components/popover/src/popover.component.tsx b/packages/mobile-ui-vue/components/popover/src/popover.component.tsx index 69beca5949d53079c853718e02260f325059ab62..f37eb4f8a4da324907c49b43263ecfd7094c302a 100644 --- a/packages/mobile-ui-vue/components/popover/src/popover.component.tsx +++ b/packages/mobile-ui-vue/components/popover/src/popover.component.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import { computed, defineComponent, ref, SetupContext } from 'vue'; -import { useBem } from '@components/common'; -import Popup from '@components/popup'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import Popup from '@farris/mobile-ui-vue/popup'; import { PopoverProps, popoverProps, POPOVER_NAME } from './popover.props'; import { usePosition } from './composition/use-position'; diff --git a/packages/mobile-ui-vue/components/popup/index.ts b/packages/mobile-ui-vue/components/popup/index.ts index 026d398aeea22caf4bceaa288e1592222526e1b8..87dd51cf9970796a1ec0b4f9892db44247a7a551 100644 --- a/packages/mobile-ui-vue/components/popup/index.ts +++ b/packages/mobile-ui-vue/components/popup/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import PopupInstallless from './src/popup.component'; import { PopupPosition } from './src/popup.props'; diff --git a/packages/mobile-ui-vue/components/popup/src/popup.component.tsx b/packages/mobile-ui-vue/components/popup/src/popup.component.tsx index 6490e2648b63361d209d66f88361ba356a18452d..3b68dd50bccdda34e195e03a17c15bc860bd767b 100644 --- a/packages/mobile-ui-vue/components/popup/src/popup.component.tsx +++ b/packages/mobile-ui-vue/components/popup/src/popup.component.tsx @@ -8,8 +8,8 @@ import { computed, SetupContext } from 'vue'; -import { getSlideTransitionName, useBem, useClickAway, useLockScroll } from '@components/common'; -import Overlay from '@components/overlay'; +import { getSlideTransitionName, useBem, useClickAway, useLockScroll } from '@farris/mobile-ui-vue/common'; +import Overlay from '@farris/mobile-ui-vue/overlay'; import { PopupProps, popupProps, POPUP_NAME } from './popup.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/property-panel/index.ts b/packages/mobile-ui-vue/components/property-panel/index.ts deleted file mode 100644 index 7963be09873589e9a106f4da19789b3c3683afe5..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { BaseControlProperty } from './src/composition/entity/base-property'; -import { SchemaDOMMapping } from './src/composition/entity/schema-dom-mapping'; - -export * from './src/composition/props/property-panel-item.props'; -export * from './src/composition/props/property-panel.props'; - -export * from './src/composition/type'; - -export { BaseControlProperty, SchemaDOMMapping }; diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item-list.css b/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item-list.css deleted file mode 100644 index 1df3d4efa1d8893c31e9f33890874b4a6359e920..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item-list.css +++ /dev/null @@ -1,80 +0,0 @@ -.propertyCascadeItem { - background-color: transparent !important; - border: none !important; -} - -.propertyCascadeItem .card-header { - background-color: transparent !important; - padding: 4px 0px !important; - color: inherit !important; -} - -.propertyCascadeItem .card-header .panel-item-title { - width: 100%; - position: relative; - font-size: inherit !important; -} - -.propertyCascadeItem .card-header .panel-item-title .farris-input-wrap { - margin-left: -5px; - margin-right: -5px; -} - -.propertyCascadeItem .form-group .col-form-label .f-icon { - color: #a3a3a3 !important; -} - -.propertyCascadeItem .f-accordion-collapse, -.propertyCascadeItem .f-accordion-expand { - right: 0; - left: auto !important; - top: 6px; - color: #6b94ec !important; - position: absolute; -} - -.propertyCascadeItem .card-body { - padding: 3px 12px !important; - background: rgba(255, 255, 255, 0.8); - border-radius: 8px; - margin: 4px 0px; -} - -.propertyCascadeItem .card-body.hidden { - display: none; -} - -.landscape { - display: none; - flex-shrink: 0; - align-items: center; - justify-content: flex-end; -} - -.wide-panel .vertical { - display: none; -} - -.wide-panel .landscape { - display: block; - padding: 0px; - overflow: hidden; -} - -.wide-panel .line-item { - display: flex; -} - -.wide-panel .line-item .f-header { - margin-bottom: 0; -} - -.wide-panel .line-item .f-section-formgroup-legend { - width: 89px; - text-align: right; - padding-right: 13px; -} - -.wide-panel .line-item .farris-input-wrap { - flex: 1 1 0; -} diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item.css b/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item.css deleted file mode 100644 index 50a976a6eab7e26aba701fc87e331785298ebf0b..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel-item.css +++ /dev/null @@ -1,30 +0,0 @@ -.property-item .form-group { - margin-bottom: 2px; -} - -.property-item .col-form-label { - line-height: 26px; -} - -.property-item .row-item { - align-items: center; -} - -.wide-panel .row-item { - display: flex; -} - -.wide-panel .row-item .component { - flex: 1 1 0; -} - -.wide-panel .row-item label { - width: 89px; - text-align: right; - padding-right: 10px; -} - -.wrap { - overflow: hidden; - text-overflow: ellipsis; -} \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel.css b/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel.css deleted file mode 100644 index a83de6b5095d92267e8de909e48e6206f00fcb83..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/class/property-panel.css +++ /dev/null @@ -1,222 +0,0 @@ -:host { - width: inherit; - height: inherit; -} - -.property-panel { - position: relative; -} - -.property-panel .switcher { - position: absolute; - top: 9px; - right: 0; - width: 40px; - text-align: center; -} - - -.property-panel .switcher i { - color: #4190FF; - font-size: 12px; - cursor: pointer; -} - -.property-panel .side-panel { - width: 41px; - background-color: #fff; - padding-top: 45px; - text-align: center; -} - -.property-panel .side-panel .icon { - display: block; - text-align: center; - color: #4190FF; - margin-bottom: 10px; -} - -.property-panel .side-panel span { - writing-mode: vertical-rl; - font-size: 14px; -} - -.propertyPanel { - width: 300px; - height: 100%; - color: rgba(0, 0, 0, 0.75); - background: #f3f8ff !important; - border-color: #d8dbe2 !important; - display: flex; -} - -.propertyPanel .title { - position: relative; - background: #d0d8e9 !important; - - flex-wrap: wrap; - border: 0; -} - -.propertyPanel .title.p-right { - padding-right: 40px; -} - -.propertyPanel .title>.title-label { - line-height: 34px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding-left: 12px; - padding-right: 12px; - color: #333333; - font-size: 13px; - font-weight: 600; - cursor: pointer; -} - -.propertyPanel .title>.title-label.active { - background: #8fb1df !important -} - -.propertyPanel .title .title-actions { - position: absolute; - right: 10px; - top: 0px; - padding-left: 35px; - height: 35px; - -ms-flex: 1; - flex: 1; - box-sizing: border-box; -} - -.propertyPanel .title .title-actions { - position: absolute; - right: 10px; - top: 0px; -} - -.propertyPanel .property-grid .group-label { - line-height: 30px; - display: block; - padding-left: 13px; - cursor: pointer; - background: rgb(226, 233, 246) !important; - ; - color: #435069 !important; - font-weight: 600 !important; - border-radius: 6px; -} - -.propertyPanel .search .textbox { - padding-left: 10px; -} - -.propertyPanel .search .input-group { - border-radius: 0; -} - -.propertyPanel .panel-body { - overflow: auto; - height: 100%; -} - -.propertyPanel .property-grid { - list-style: none; - margin: 0 10px; - padding: 0; -} - -.propertyPanel .property-grid li { - padding: 2px 0; -} - -.propertyPanel .panel-body .property-grid .group-label+div { - padding-bottom: 14px !important; - padding-top: .25rem !important; -} - -.propertyPanel .action-item { - cursor: pointer; - display: inline-block; - transition: transform 50ms ease; - position: relative; - padding: 0px; -} - -.propertyPanel .action-item>.f-icon { - color: rgba(66, 66, 66, .75); - line-height: 35px; - font-weight: 600; -} - -.propertyPanel .search .input-group-clear { - border-radius: 0 !important; -} - -/***************************白色主题******************************/ - -.white-theme .propertyPanel { - background: #fff !important; - border: 1px solid #D8DCE6 !important; -} - -.white-theme .propertyPanel .title { - overflow: visible; - background: #fff !important; - justify-content: space-around; -} - -.white-theme .propertyPanel { - background: #fff !important; -} - -.white-theme .propertyPanel .title { - overflow: visible; - background: #fff !important; - flex-wrap: wrap; - text-align: center; -} - -.white-theme .propertyPanel .title>.title-label { - border-bottom: 0; - font-weight: 400 !important; - /* margin-left: 20px; - margin-right: 20px; */ - border-bottom: 0; - background: #fff !important; - flex: 1; - color: #83849B; -} - -.white-theme .propertyPanel .title>.title-label>span { - padding: 0 14px 7px 14px; -} - -.white-theme .propertyPanel .title>.title-label.active>span { - border-bottom: 2px solid #5b89fe; - color: #5B89FE; - border-radius: 1.5px; -} - -.white-theme .propertyPanel .title.only { - text-align: left; -} - -.white-theme .propertyPanel .property-grid .group-label { - background: #fff !important; - line-height: 30px; - font-weight: 400 !important; - font-size: 13px; - color: #3F4764 !important; - border-radius: 6px; - background: #EEF4FF !important; - color: #435069 !important; -} - -.white-theme .propertyPanel .property-grid .group-label .f-icon { - color: #5D89FE; - font-size: 13px; -} - -/***************************白色主题 end ******************************/ \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/base-property.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/entity/base-property.ts deleted file mode 100644 index c07677ccf589651885ed807c4d912360bf0cb73f..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/base-property.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { DesignerComponentInstance } from "@/components/designer-canvas"; -import { DgControl } from "../../../../designer-canvas/src/composition/dg-control"; -import { cloneDeep } from "lodash-es"; - -/** - * 控件属性基类 - */ -export class BaseControlProperty { - public componentId: string; - - public viewModelId: string; - - public eventsEditorUtils: any; - - public formSchemaUtils: any; - public formMetadataConverter: any; - public designViewModelUtils: any; - public designViewModelField: any; - public controlCreatorUtils: any; - public designerHostService: any; - - schemaService: any = null; - - metadataService: any = null; - - protected propertyConfig = { - type: 'object', - categories: {} - }; - - constructor(componentId: string, designerHostService: any) { - this.componentId = componentId; - this.designerHostService = designerHostService; - this.eventsEditorUtils = designerHostService['eventsEditorUtils']; - this.formSchemaUtils = designerHostService['formSchemaUtils']; - this.formMetadataConverter = designerHostService['formMetadataConverter']; - this.viewModelId = this.formSchemaUtils?.getViewModelIdByComponentId(componentId) || ''; - this.designViewModelUtils = designerHostService['designViewModelUtils']; - this.controlCreatorUtils = designerHostService['controlCreatorUtils']; - this.metadataService = designerHostService['metadataService']; - this.schemaService = designerHostService['schemaService']; - } - - getTableInfo() { - return this.schemaService?.getTableInfoByViewModelId(this.viewModelId); - } - - setDesignViewModelField(propertyData: any) { - const bindingFieldId = propertyData.binding && propertyData.binding.type === 'Form' && propertyData.binding.field; - // 视图模型中[字段更新时机]属性现在要在控件上维护,所以在控件上复制一份属性值 - if (bindingFieldId) { - if (!this.designViewModelField) { - const dgViewModel = this.designViewModelUtils.getDgViewModel(this.viewModelId); - this.designViewModelField = dgViewModel.fields.find(f => f.id === bindingFieldId); - } - propertyData.updateOn = this.designViewModelField?.updateOn; - } - } - - getBasicPropConfig(propertyData: any): any { - return { - description: 'Basic Information', - title: '基本信息', - properties: { - id: { - description: '组件标识', - title: '标识', - type: 'string', - readonly: true - }, - type: { - description: '组件类型', - title: '控件类型', - type: 'select', - editor: { - type: 'combo-list', - textField: 'name', - valueField: 'value', - editable: false, - data: [{ value: propertyData.type, name: DgControl[propertyData.type] && DgControl[propertyData.type].name }] - } - } - } - }; - - } - - - protected getAppearanceConfig(propertyData = null): any { - return { - title: "外观", - description: "Appearance", - properties: { - class: { - title: "class样式", - type: "string", - description: "组件的CSS样式", - $converter: "/converter/appearance.converter" - }, - style: { - title: "style样式", - type: "string", - description: "组件的样式", - $converter: "/converter/appearance.converter" - } - } - }; - } - - /** - * - * @param propertyId - * @param componentInstance - * @returns - */ - public updateElementByParentContainer(propertyId:string, componentInstance: DesignerComponentInstance){ - // 1、定位控件父容器 - const parentContainer = componentInstance && componentInstance.parent && componentInstance.parent['schema']; - if (!parentContainer) { - return; - } - const index = parentContainer.contents.findIndex(c => c.id === propertyId); - // 通过cloneDeep方式的触发更新 - const controlSchema = cloneDeep(parentContainer.contents[index]); - // 5、替换控件 - parentContainer.contents.splice(index, 1); - parentContainer.contents.splice(index, 0, controlSchema); - } - -} diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/use-input-rules.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/entity/use-input-rules.ts deleted file mode 100644 index 111c3ced7a7e770a317d30f0464c3e377a481e40..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/entity/use-input-rules.ts +++ /dev/null @@ -1,62 +0,0 @@ - -import { ref } from "vue"; -import { DesignerHTMLElement, DraggingResolveContext, UseDesignerRules } from '../../../../designer-canvas/src/composition/types'; -import { ComponentSchema, DesignerItemContext } from "@/components/designer-canvas"; - -export function useInputDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { - const schema = designItemContext.schema as ComponentSchema; - /** 组件在拖拽时需要将所属的Component一起拖拽 */ - const triggerBelongedComponentToMoveWhenMoved = ref(true); - /** 组件在删除时需要将所属的Component一起拖拽 */ - const triggerBelongedComponentToDeleteWhenDeleted = ref(true); - /** data-grid所属的上级组件控制规则 */ - /** - * 判断是否可以接收拖拽新增的子级控件 - */ - function canAccepts(draggingContext: DraggingResolveContext): boolean { - return false; - } - - /** - * data-grid是否支持删除,取决于所属组件是否支持删除 - */ - function checkCanDeleteComponent() { - return false; - } - /** - * data-grid是否支持移动,取决于所属组件是否支持移动 - */ - function checkCanMoveComponent() { - return false; - } - - function hideNestedPaddingInDesginerView() { - return true; - } - - function onAcceptMovedChildElement(sourceElement: DesignerHTMLElement) { - } - /** - * 判断data-grid上下文 - */ - function resolveComponentContext() { - - } - // 构造属性配置方法 - function getPropsConfig(componentId: string) { - return null; - } - - return { - canAccepts, - checkCanDeleteComponent, - checkCanMoveComponent, - hideNestedPaddingInDesginerView, - onAcceptMovedChildElement, - resolveComponentContext, - triggerBelongedComponentToMoveWhenMoved, - triggerBelongedComponentToDeleteWhenDeleted, - getPropsConfig - } as UseDesignerRules; - -} diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item-list.props.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item-list.props.ts deleted file mode 100644 index 40bf0ca77a9f7902125345aec1afa7d3ff8f3cb1..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item-list.props.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ExtractPropTypes, PropType } from 'vue'; -import { ElementPropertyConfig } from '../entity/property-entity'; - -export const propertyPanelItemListProps = { - /** 某一分类下的属性配置 */ - // as PropType - category: { type: Object, default: {} }, - - categoryKey: { type: String }, - /** 属性值 */ - propertyData: { type: Object, default: {} }, - - valueChanged: { type: Function }, - - triggerRefreshPanel: { type: Function } -}; -export type PropertyPanelItemListProps = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item.props.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item.props.ts deleted file mode 100644 index c87c39e87b06433bd66629f11c7d54e665f93ee6..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel-item.props.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ExtractPropTypes, PropType } from 'vue'; - -export const propertyPanelItemProps = { - elementConfig: { type: Object, default: {} }, - category: { type: Object, default: {} } -}; -export type PropertyPanelItemProps = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel.props.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel.props.ts deleted file mode 100644 index 456a906bfad82d94fe2dd3451190addcb9a578d3..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/props/property-panel.props.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ExtractPropTypes, PropType } from 'vue'; - -type ShowMode = 'panel' | 'sidebar'; - -export const propertyPanelProps = { - - width: { type: String, default: '300px' }, - - height: { type: Number, default: 10 }, - - isWidePanel: { type: Boolean, default: false }, - - /** 是否启用搜索 */ - enableSearch: { type: Boolean, default: true }, - - /** 使用模式 */ - mode: { type: String as PropType, default: 'panel' }, - - /** 是否持有面板的隐藏显示状态 */ - isPersitOpenState: { type: Boolean, default: false }, - - /** isPersitOpenState=true时,控制面板是否隐藏显示 */ - isShowPanel: { type: Boolean, default: false }, - - /** 属性名 */ - propertyName: { type: String, default: '' }, - - /** 属性类型 */ - propertyConfig: { type: Array }, - - /** 属性值 */ - propertyData: { type: Object, default: {} }, - - /** 是否展示关闭按钮 */ - showCloseBtn: { type: Boolean, default: false }, - - /** 当前选中的标签页id */ - selectedTabId: { type: String, default: '' }, - - /** 是否是白色主题 */ - isWhiteTheme: { type: Boolean, default: true }, - - /** dom结构 */ - schema: { type: Object, default: {} }, - - /** 属性变更后事件 */ - propertyChanged: { type: Function } -}; -export type PropertyPanelProps = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/property-panel/src/composition/type.ts b/packages/mobile-ui-vue/components/property-panel/src/composition/type.ts deleted file mode 100644 index f6727192b3f282af52eb8b82f4e307908a33fa7f..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/composition/type.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * 属性类型 - */ -export enum PropertyType { - /** 字符串 */ - string = 'string', - - /** 布尔,下拉选择 */ - boolean = 'boolean', - - /** 数字 */ - number = 'number', - - /** 下拉选择:单选 */ - select = 'select', - - /** 已废弃,请使用editableSelect */ - boolOrExp = 'boolOrExp', - - /** 可编辑的下拉选择:单选,并且可编辑 */ - editableSelect = 'editableSelect', - - /** 下拉多选 */ - multiSelect = 'multiSelect', - - /** 日期 */ - date = 'date', - - /** 日期时间 */ - datetime = 'datetime', - - /** 模态窗,自定义组件 */ - modal = 'modal', - - /** 级联 */ - cascade = 'cascade', - - /** 自定义组件 */ - custom = 'custom', - - /** 多功能属性编辑器,支持常量、变量、自定义、表达式等场景 */ - unity = 'unity', - - /** 事件编辑器集成,支持导入命令、参数编辑等场景 */ - events = 'events', - - /** 开关类编辑器,适用于布尔值属性 */ - switch = 'switch', - - /** 多语言输入框 */ - multiLanguage = 'multiLanguage' -} - -/** 属性值转换器,返回模态框类属性文本框内的显示内容 */ -export interface TypeConverter { - // 由模态框转为属性框中展示的值 - convertTo(data: any, params?: any): string; -} - -export interface KeyMap { - key: any; - value: any; -} - -/** - * binding 类型 - */ -export enum FormBindingType { - Form = "Form", - Variable = "Variable" -} - -export interface FormUnifiedColumnLayout { - uniqueColClassInSM: number; - uniqueColClassInMD: number; - uniqueColClassInLG: number; - uniqueColClassInEL: number; -} - -export interface IPropertyConfig { - getPropertyConfig(propertyData: any, eventsEditorUtils: any); -} - -export * from './entity/property-entity'; diff --git a/packages/mobile-ui-vue/components/property-panel/src/mock.ts b/packages/mobile-ui-vue/components/property-panel/src/mock.ts deleted file mode 100644 index 8266d0cfe1d4cdc4bc725cc7fb687e28393b7f6a..0000000000000000000000000000000000000000 --- a/packages/mobile-ui-vue/components/property-panel/src/mock.ts +++ /dev/null @@ -1,174 +0,0 @@ -export const propertyConfigTemp = [ - { - categoryId: 'basic', - categoryName: '基本信息', - properties: [ - { - propertyID: 'id', - propertyName: '标识', - propertyType: 'string', - description: '组件的id', - readonly: true - }, - { - propertyID: 'type', - propertyName: '控件类型', - propertyType: 'select', - description: '组件的类型', - } - ] - }, - { - categoryId: 'appearance', - categoryName: '样式', - properties: [ - { - propertyID: 'fill', - propertyName: '填充', - propertyType: 'datetime', - description: 'flex布局下,填充满剩余部分', - modelValue: '2023-4-9', - editor: { - id: 'd152e48d-13d1-4553-94fa-525fa67d4f2b', - type: 'date-picker', - require: false, - format: 'yyyy-MM-dd', - weekSelect: false, - startFieldCode: 'BillDate', - endFieldCode: 'BillDate' - }, - }, - { - propertyID: 'expanded', - propertyName: '展开', - propertyType: 'boolean', - description: '是否展开', - modelValue: 'false', - editor: { - type: 'combo-list', - require: false, - valueType: '1', - multiSelect: false, - data: [ - { - value: 'true', - name: 'true' - }, - { - value: 'false', - name: 'false' - } - ] - } - }, - { - propertyID: 'showHeader', - propertyName: '显示头部区域', - propertyType: 'boolean', - description: '是否显示头部区域', - modelValue: 'true', - editor: { - type: 'combo-list', - require: false, - valueType: '1', - multiSelect: false, - data: [ - { - value: 'true', - name: 'true' - }, - { - value: 'false', - name: 'false' - } - ] - } - }, - { - propertyID: 'mainTitle', - propertyName: '主标题', - propertyType: 'string', - description: '主标题名称', - group: 'header' - }, - { - propertyID: 'subTitle', - propertyName: '副标题', - propertyType: 'string', - description: '副标题名称', - group: 'header' - }, - { - propertyID: 'enableMaximize', - propertyName: '显示最大化', - propertyType: 'boolean', - description: '是否显示最大化', - group: 'header' - }, - { - propertyID: 'enableAccordion', - propertyName: '启用收折功能', - propertyType: 'boolean', - description: '是否启用收折功能', - group: 'header' - }, - { - propertyID: 'accordionMode', - propertyName: '收折模式', - propertyType: 'select', - description: '收折模式选择', - iterator: [{ key: 'default', value: '默认收折' }, { key: 'custom', value: '自定义收折' }], - group: 'header' - } - ] - }, - { - categoryId: 'toolbar', - categoryName: '工具栏', - properties: [ - { - propertyID: 'toolbarCls', - propertyName: '工具栏样式', - propertyType: 'string' - }, - { - propertyID: 'toolbarBtnSize', - propertyName: '按钮尺寸', - propertyType: 'select', - iterator: [ - { key: 'default', value: '标准' }, - { key: 'lg', value: '大号' } - ] - }, - { - propertyID: 'toolbarPopDirection', - propertyName: '弹出方向', - propertyType: 'select', - iterator: [ - { key: 'default', value: '自动' }, - { key: 'top', value: '向上' }, - { key: 'bottom', value: '向下' } - ] - } - ] - } -]; - -export const propertyDataTemp = { - id: 'dataGrid', - testCategoryCascade: { - showSize2: false - }, - language1: { - 'zh-CHS': 'check1', - 'en': 'hhhh' - }, - language2: { - 'en': 'hhhh2', - 'zh-CHS': 'check2', - }, - language3: { - 'en': 'hhhh3', - 'zh-CHS': 'check3', - } -}; diff --git a/packages/mobile-ui-vue/components/pull-refresh/index.ts b/packages/mobile-ui-vue/components/pull-refresh/index.ts index 799902746c7065a1746281c85cdca9be1a50a6d4..53d4d871ec1ab521eb098988bcbdcbf8f4e35324 100644 --- a/packages/mobile-ui-vue/components/pull-refresh/index.ts +++ b/packages/mobile-ui-vue/components/pull-refresh/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import PullRefreshInstallless from './src/pull-refresh.component'; export * from './src/pull-refresh.props'; diff --git a/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.component.tsx b/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.component.tsx index 72c1238265e500af7dc1f9abe4c0c70901d6d45e..be589115acb874a9eb2336f32d63a11de896809f 100644 --- a/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.component.tsx +++ b/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.component.tsx @@ -15,9 +15,9 @@ */ import { defineComponent, SetupContext, ref, computed, nextTick, watch, toRef } from 'vue'; import { PULL_REFRESH_NAME, pullRefreshProps, PullRefreshProps } from './pull-refresh.props'; -import { useBem, useScrollParent, useTouch, useEventListener } from '@components/common'; -import { preventDefault } from '@components/common'; -import Loading from '@components/loading'; +import { useBem, useScrollParent, useTouch, useEventListener } from '@farris/mobile-ui-vue/common'; +import { preventDefault } from '@farris/mobile-ui-vue/common'; +import Loading from '@farris/mobile-ui-vue/loading'; type PullRefreshStatus = 'initial' | 'pulling' | 'loosing' | 'loading' | 'complete'; diff --git a/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.props.ts b/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.props.ts index 3960e394175f08a11f7592bdeecbf146f07eb6e4..239e450095fd654976506f07e52f935710b9839d 100644 --- a/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.props.ts +++ b/packages/mobile-ui-vue/components/pull-refresh/src/pull-refresh.props.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { ExtractPropTypes, PropType } from 'vue'; -import { LoadingProps } from '@components/loading'; +import { LoadingProps } from '@farris/mobile-ui-vue/loading'; export const PULL_REFRESH_NAME = 'fm-pull-refresh'; diff --git a/packages/mobile-ui-vue/components/radio-group/index.ts b/packages/mobile-ui-vue/components/radio-group/index.ts index 4c196194195a36716fbcaa07eac604414aedcf17..d1257d820349d28d93abe39f93765d7d19d72f65 100644 --- a/packages/mobile-ui-vue/components/radio-group/index.ts +++ b/packages/mobile-ui-vue/components/radio-group/index.ts @@ -1,6 +1,6 @@ -import { withInstall } from '@components/common'; +import { withInstall, RegisterContext } from '@farris/mobile-ui-vue/common'; import RadioGroupInstallless from './src/radio-group.component'; -import { propsResolver } from './src/radio-group.props'; +import { propsResolverGenerator } from './src/radio-group.props'; import RadioGroupDesign from './src/designer/radio-group.design.component'; export * from './src/radio-group.props'; @@ -9,13 +9,15 @@ const RADIO_GROUP_REGISTERED_NAME = 'radio-group'; const RadioGroup = withInstall(RadioGroupInstallless); -RadioGroup.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { +RadioGroup.register = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record, resolverMap: Record,registerContext: RegisterContext) => { componentMap[RADIO_GROUP_REGISTERED_NAME] = RadioGroup; - propsResolverMap[RADIO_GROUP_REGISTERED_NAME] = propsResolver; + propsResolverMap[RADIO_GROUP_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; -RadioGroup.registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record) => { +RadioGroup.registerDesigner = (componentMap: Record, propsResolverMap: Record, + configresolverMap: Record,registerContext: RegisterContext) => { componentMap[RADIO_GROUP_REGISTERED_NAME] = RadioGroupDesign; - propsResolverMap[RADIO_GROUP_REGISTERED_NAME] = propsResolver; + propsResolverMap[RADIO_GROUP_REGISTERED_NAME] = propsResolverGenerator(registerContext); }; diff --git a/packages/mobile-ui-vue/components/radio-group/src/designer/radio-group.design.component.tsx b/packages/mobile-ui-vue/components/radio-group/src/designer/radio-group.design.component.tsx index bf464deb8aa8d16be358a23155447d0248521521..fd1e3df35f297f2abbf9454ee7b29bd7ddfd717e 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/designer/radio-group.design.component.tsx +++ b/packages/mobile-ui-vue/components/radio-group/src/designer/radio-group.design.component.tsx @@ -16,7 +16,7 @@ */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; import { RadioGroup, RadioGroupProps, radioGroupProps } from '../..'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; import { useRadioGroupDesignerRules } from './use-designer-rules'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/radio-group/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/radio-group/src/designer/use-designer-rules.ts index f7e63a69dba7a4b1717822aa4dfa3ec0bf1bed40..ec88e3ba081c49ccc5a63ffbed6cf645e3023eb2 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/radio-group/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { RadioGroupProperty } from "../property-config/radio-group.property-config"; export function useRadioGroupDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/radio-group/src/property-config/radio-group.property-config.ts b/packages/mobile-ui-vue/components/radio-group/src/property-config/radio-group.property-config.ts index 2af44da90f9698c1090e3149b417fc21bf6756ef..066c73425c901b6f573780a0336091c13435c836 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/property-config/radio-group.property-config.ts +++ b/packages/mobile-ui-vue/components/radio-group/src/property-config/radio-group.property-config.ts @@ -1,48 +1,59 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { InputBaseProperty } from '@farris/mobile-ui-vue/common'; export class RadioGroupProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } - - - getEditorProperties(propertyData: any) { - const self = this; - const editorProperties = self.getComponentConfig(propertyData, { type: "radio-group" }, { - direction: { - description: "", - title: "排列方向", - type: "enum", - editor: { - type: "combo-list", - textField: "value", - valueField: "key", - data: [{ "key": "horizontal", "value": "横向" }, { "key": "vertical", "value": "纵向" }] - } - }, - data: { - description: "", - title: "数据", - type: "array", - $converter: "/converter/enum-data.converter", - ...self.getItemCollectionEditor(propertyData, propertyData.editor.valueField, propertyData.editor.textField), - // 这个属性,标记当属性变更得时候触发重新更新属性 - refreshPanelAfterChanged: true, - } - }); - editorProperties['setPropertyRelates'] = function (changeObject) { - if (!changeObject) { - return; - } - switch (changeObject.propertyID) { - case 'data': { - - break; - } - } - }; - return editorProperties; - } - + getEditorProperties(propertyData: any) { + const self = this; + const editorProperties = self.getComponentConfig( + propertyData, + {}, + { + placeholder: { + visible: false + }, + disabled: { + visible: false + }, + data: { + description: '', + title: '数据', + type: 'array', + $converter: '/converter/enum-data.converter', + ...self.getItemCollectionEditor( + propertyData, + propertyData.editor.valueField, + propertyData.editor.textField + ), + // 这个属性,标记当属性变更得时候触发重新更新属性 + refreshPanelAfterChanged: true + }, + textField: { + description: '', + title: '文本字段', + type: 'string', + readonly: true + }, + valueField: { + description: '', + title: '值字段', + type: 'string', + readonly: true + } + } + ); + editorProperties['setPropertyRelates'] = function (changeObject) { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'data': { + break; + } + } + }; + return editorProperties; + } } diff --git a/packages/mobile-ui-vue/components/radio-group/src/radio-group.component.tsx b/packages/mobile-ui-vue/components/radio-group/src/radio-group.component.tsx index 42213a2fb8d4280f938eb4f7839193aba3c2e647..cd552d70c4fb5d61cb1ed4519839e1c9fe74942c 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/radio-group.component.tsx +++ b/packages/mobile-ui-vue/components/radio-group/src/radio-group.component.tsx @@ -15,9 +15,9 @@ */ import { SetupContext, computed, defineComponent, ref, watch } from 'vue'; -import { useBem, useLink } from '@components/common'; -import { useGroupItems } from '@components/checkbox-group'; -import Radio from '@components/radio'; +import { useBem, useLink } from '@farris/mobile-ui-vue/common'; +import { useGroupItems } from '@farris/mobile-ui-vue/checkbox-group'; +import Radio from '@farris/mobile-ui-vue/radio'; import { RADIO_GROUP_NAME, RadioGroupContext, diff --git a/packages/mobile-ui-vue/components/radio-group/src/radio-group.props.ts b/packages/mobile-ui-vue/components/radio-group/src/radio-group.props.ts index f246ce170f22f24a2a8d947a6702c7d9cba728f5..2148d888b1354c058b1fa1208e284d5151e5e077 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/radio-group.props.ts +++ b/packages/mobile-ui-vue/components/radio-group/src/radio-group.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType } from 'vue'; -import {CheckerShape, CheckerShapeMap } from '@components/checker'; -import { CheckboxGroupContext, checkboxGroupProps } from '@components/checkbox-group'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import {CheckerShape, CheckerShapeMap } from '@farris/mobile-ui-vue/checker'; +import { CheckboxGroupContext, checkboxGroupProps } from '@farris/mobile-ui-vue/checkbox-group'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import inputSchema from './schema/radio-group.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -24,4 +24,4 @@ type Merge = { export type RadioGroupContext = Merge void }>; -export const propsResolver = createPropsResolver(radioGroupProps, inputSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(radioGroupProps, inputSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/radio-group/src/schema/radio-group.schema.json b/packages/mobile-ui-vue/components/radio-group/src/schema/radio-group.schema.json index 316b66fc68f3b6be4ab26478c67cf03cffa8dde6..7fad6675bf4385ad99edf0f0c63a07ac83c3e1d5 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/schema/radio-group.schema.json +++ b/packages/mobile-ui-vue/components/radio-group/src/schema/radio-group.schema.json @@ -1,78 +1,81 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://farris-design.gitee.io/radio-group.schema.json", - "title": "radio-group", - "description": "A Farris Input Component", - "type": "object", - "properties": { - "id": { - "description": "The unique identifier for a Input Group", - "type": "string" - }, - "type": { - "description": "The type string of Input Group component", - "type": "string", - "default": "radio-group" - }, - "appearance": { - "description": "", - "type": "object", - "properties": { - "class": { - "type": "string" - }, - "style": { - "type": "string" - } - }, - "default": {} - }, - "binding": { - "description": "", - "type": "object", - "default": {} - }, - "readonly": { - "type": "string", - "default": false - }, - "title": { - "description": "", - "type": "string", - "default": "" - }, - "label": { - "description": "", - "type": "string", - "default": "" - }, - "lableWidth": { - "description": "", - "type": "number" - }, - "visible": { - "description": "", - "type": "boolean", - "default": true - }, - "data": { - "description": "", - "type": "array", - "default": [] + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://farris-design.gitee.io/radio-group.schema.json", + "title": "radio-group", + "description": "A Farris Input Component", + "type": "object", + "properties": { + "id": { + "description": "The unique identifier for a Input Group", + "type": "string" + }, + "type": { + "description": "The type string of Input Group component", + "type": "string", + "default": "radio-group" + }, + "appearance": { + "description": "", + "type": "object", + "properties": { + "class": { + "type": "string" }, - "direction": { - "description": "", - "type": "string", - "default": "horizontal" + "style": { + "type": "string" } + }, + "default": {} + }, + "binding": { + "description": "", + "type": "object", + "default": {} + }, + "readonly": { + "type": "string", + "default": false + }, + "title": { + "description": "", + "type": "string", + "default": "" + }, + "label": { + "description": "", + "type": "string", + "default": "" + }, + "lableWidth": { + "description": "", + "type": "number" + }, + "visible": { + "description": "", + "type": "boolean", + "default": true + }, + "data": { + "description": "", + "type": "array", + "default": [] + }, + "direction": { + "description": "", + "type": "string", + "default": "horizontal" + }, + "textField": { + "description": "", + "type": "string", + "default": "name" }, - "required": [ - "type" - ], - "ignore": [ - "id", - "appearance", - "binding", - "visible" - ] -} \ No newline at end of file + "valueField": { + "description": "", + "type": "string", + "default": "value" + } + }, + "required": ["type"], + "ignore": ["id", "appearance", "binding", "visible"] +} diff --git a/packages/mobile-ui-vue/components/radio-group/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/radio-group/src/schema/schema-mapper.ts index 84d9b46a457c4a3e19441fc70157412cc15c9841..bf5fa0c7c604d94ab7ec1f164e2600ff20912a90 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/radio-group/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance, resolveData } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance, resolveData } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/radio-group/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/radio-group/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/radio-group/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/radio-group/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/radio/index.ts b/packages/mobile-ui-vue/components/radio/index.ts index f6aee206094527e453d8eb7a964278a9970bd1f4..a9d5943a2bb12918fd65271065d2df4051206a9f 100644 --- a/packages/mobile-ui-vue/components/radio/index.ts +++ b/packages/mobile-ui-vue/components/radio/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import RadioInstallless from './src/radio.component'; export * from './src/radio.props'; diff --git a/packages/mobile-ui-vue/components/radio/src/radio.component.tsx b/packages/mobile-ui-vue/components/radio/src/radio.component.tsx index 0b653df25f3d9ca73e787c7acca5cc09d50c2f2e..fb7a6bf9ff8197f618396499f7aba94aa2264c6a 100644 --- a/packages/mobile-ui-vue/components/radio/src/radio.component.tsx +++ b/packages/mobile-ui-vue/components/radio/src/radio.component.tsx @@ -15,9 +15,9 @@ */ import { defineComponent } from 'vue'; -import { Checker, CheckerRoleMap, CheckerShapeMap } from '@components/checker'; -import { useBem, useLink } from '@components/common'; -import { RADIO_GROUP_NAME, RadioGroupContext } from '@components/radio-group'; +import { Checker, CheckerRoleMap, CheckerShapeMap } from '@farris/mobile-ui-vue/checker'; +import { useBem, useLink } from '@farris/mobile-ui-vue/common'; +import { RADIO_GROUP_NAME, RadioGroupContext } from '@farris/mobile-ui-vue/radio-group'; import { RADIO_NAME, RadioProps, radioProps } from './radio.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/radio/src/radio.props.ts b/packages/mobile-ui-vue/components/radio/src/radio.props.ts index 01002d195708639f7724c05e282600b659d0ee95..4f74e985f006549c3aadd29e2dac590d448a5a39 100644 --- a/packages/mobile-ui-vue/components/radio/src/radio.props.ts +++ b/packages/mobile-ui-vue/components/radio/src/radio.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes, PropType } from 'vue'; -import { CheckerRole, CheckerRoleMap } from '@components/checker'; -import { checkboxProps } from '@components/checkbox'; +import { CheckerRole, CheckerRoleMap } from '@farris/mobile-ui-vue/checker'; +import { checkboxProps } from '@farris/mobile-ui-vue/checkbox'; export const RADIO_NAME = 'fm-radio'; diff --git a/packages/mobile-ui-vue/components/rate/index.ts b/packages/mobile-ui-vue/components/rate/index.ts index 70568149519cb9bcf30b0fa28a99dcbf8662a170..ec1fe1721189d18e62484b5b153d2a0ddb0eaab9 100644 --- a/packages/mobile-ui-vue/components/rate/index.ts +++ b/packages/mobile-ui-vue/components/rate/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import RateInstallless from './src/rate.component'; export * from './src/rate.props'; diff --git a/packages/mobile-ui-vue/components/rate/src/rate.component.tsx b/packages/mobile-ui-vue/components/rate/src/rate.component.tsx index 304636c0ba1e3b9dfb9bb8870d66c60581ad6266..327522ae8427a4d4ff2fc1df71a343f796cfcaeb 100644 --- a/packages/mobile-ui-vue/components/rate/src/rate.component.tsx +++ b/packages/mobile-ui-vue/components/rate/src/rate.component.tsx @@ -16,10 +16,10 @@ /* eslint-disable no-use-before-define */ import { defineComponent, SetupContext, computed, ref } from "vue"; import { RATE_NAME, rateProps, RateProps } from "./rate.props"; -import { useTouch, useRefs, useRect, useEventListener, useBem } from "@components/common"; +import { useTouch, useRefs, useRect, useEventListener, useBem } from "@farris/mobile-ui-vue/common"; import { RateItem } from "./composition/types"; -import { addUnit, preventDefault } from "@components/common"; -import { Icon } from "@components/icon"; +import { addUnit, preventDefault } from "@farris/mobile-ui-vue/common"; +import { Icon } from "@farris/mobile-ui-vue/icon"; export default defineComponent({ name: RATE_NAME, diff --git a/packages/mobile-ui-vue/components/register-designer.ts b/packages/mobile-ui-vue/components/register-designer.ts new file mode 100644 index 0000000000000000000000000000000000000000..abf235bbdc6d044c84b9d43cb296de79850b7141 --- /dev/null +++ b/packages/mobile-ui-vue/components/register-designer.ts @@ -0,0 +1,31 @@ +import { RegisterContext } from "./common"; +import { propertyConfigSchemaMapForDesigner, schemaMapForDesigner, schemaResolverMapForDesigner } from "./dynamic-resolver"; +import { propertyEffectMapForDesigner } from "./dynamic-resolver/src/resolver/property-config/property-config-resolver-design"; + +const componentMapForDesigner: Record = {}; +const componentPropsConverterForDesigner: Record = {}; +const componentPropertyConfigConverterForDesigner: Record = {}; + +let componentsRegistered = false; +/** + * 加载设计时组件 + */ +function registerDesignerComponents(components: any[]) { + if (componentsRegistered) { + return; + } + + componentsRegistered = true; + const registerContext:RegisterContext = { + schemaMap: schemaMapForDesigner, + propertyConfigSchemaMap: propertyConfigSchemaMapForDesigner, + propertyEffectMap: propertyEffectMapForDesigner, + schemaResolverMap: schemaResolverMapForDesigner + }; + + components.forEach(component => { + component.registerDesigner && component.registerDesigner(componentMapForDesigner, componentPropsConverterForDesigner, componentPropertyConfigConverterForDesigner, registerContext); + }); +} + +export { registerDesignerComponents, componentMapForDesigner, componentPropsConverterForDesigner }; diff --git a/packages/mobile-ui-vue/components/search/index.ts b/packages/mobile-ui-vue/components/search/index.ts index 0dfb44567403601e243ede732acf44997ad583be..07fe5e72294d67f9987c7998331d2c5c68f9718a 100644 --- a/packages/mobile-ui-vue/components/search/index.ts +++ b/packages/mobile-ui-vue/components/search/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import searchInstallless from './src/search.component'; const Search = withInstall(searchInstallless); diff --git a/packages/mobile-ui-vue/components/search/src/search.component.tsx b/packages/mobile-ui-vue/components/search/src/search.component.tsx index 43784181ae5349b660740623035382ffb12b8895..fd1b8af4e334b3d11ec3025269fcf850826540a2 100644 --- a/packages/mobile-ui-vue/components/search/src/search.component.tsx +++ b/packages/mobile-ui-vue/components/search/src/search.component.tsx @@ -1,7 +1,7 @@ import { computed, CSSProperties, defineComponent, ref, watch } from "vue"; -import { useBem } from "@/components/common"; -import InputGroup from "@/components/input-group"; -import Icon from "@/components/icon"; +import { useBem } from "@farris/mobile-ui-vue/common"; +import InputGroup from "@farris/mobile-ui-vue/input-group"; +import Icon from "@farris/mobile-ui-vue/icon"; import { SEARCH_NAME, SearchProps, searchProps } from "./search.props"; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/swipe-cell/index.ts b/packages/mobile-ui-vue/components/swipe-cell/index.ts index bb4f05257b477b39f1fb29299c001629e369ceda..ae88a25d2d50a594add6605b50514a7d5ef947b6 100644 --- a/packages/mobile-ui-vue/components/swipe-cell/index.ts +++ b/packages/mobile-ui-vue/components/swipe-cell/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import SwipeCellInstallless from './src/swipe-cell.component'; export * from './src/swipe-cell.props'; diff --git a/packages/mobile-ui-vue/components/swipe-cell/src/swipe-cell.component.tsx b/packages/mobile-ui-vue/components/swipe-cell/src/swipe-cell.component.tsx index 146911c40b61437d67fb83b989ab9c7982d1719c..dc966947fb9b5295a0302520c19d398196a83a28 100644 --- a/packages/mobile-ui-vue/components/swipe-cell/src/swipe-cell.component.tsx +++ b/packages/mobile-ui-vue/components/swipe-cell/src/swipe-cell.component.tsx @@ -31,10 +31,10 @@ import { useRect, useEventListener, useClickAway, -} from '@components/common'; -import { preventDefault } from '@components/common'; +} from '@farris/mobile-ui-vue/common'; +import { preventDefault } from '@farris/mobile-ui-vue/common'; import { SwipeCellSide, SwipeCellClickPosition, SwipeCellButton } from './composition/type'; -import Icon from '@components/icon'; +import Icon from '@farris/mobile-ui-vue/icon'; export default defineComponent({ name: SWIPE_CELL_NAME, diff --git a/packages/mobile-ui-vue/components/switch/index.ts b/packages/mobile-ui-vue/components/switch/index.ts index bd7a3b611a29a0828011cb97a7bdcafeb8206d12..004a82cdfd683c40ba66df97f22ab518c2b71b7f 100644 --- a/packages/mobile-ui-vue/components/switch/index.ts +++ b/packages/mobile-ui-vue/components/switch/index.ts @@ -1,7 +1,7 @@ -import { withInstall } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import SwitchInstallless from "./src/switch.component"; import SwitchDesign from './src/designer/switch.design.component'; -import { propsResolver } from './src/switch.props'; +import { propsResolverGenerator } from './src/switch.props'; export * from './src/switch.props'; @@ -10,21 +10,8 @@ const SWITCH_REGISTERED_NAME = 'switch'; const Switch = withInstall(SwitchInstallless); -Switch.register = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[SWITCH_REGISTERED_NAME] = Switch; - propsResolverMap[SWITCH_REGISTERED_NAME] = propsResolver; -}; - -Switch.registerDesigner = ( - componentMap: Record, propsResolverMap: Record, - configResolverMap: Record, resolverMap: Record -) => { - componentMap[SWITCH_REGISTERED_NAME] = SwitchDesign; - propsResolverMap[SWITCH_REGISTERED_NAME] = propsResolver; -}; +withRegister(Switch, { name: SWITCH_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(Switch, { name: SWITCH_REGISTERED_NAME, propsResolverGenerator, designerComponent: SwitchDesign }); export { Switch }; export default Switch; diff --git a/packages/mobile-ui-vue/components/switch/src/designer/switch.design.component.tsx b/packages/mobile-ui-vue/components/switch/src/designer/switch.design.component.tsx index 08afa9356acc3876d0babd80199c78c03c865025..602ae671bfd1d04629a075461dc5159f7d9495f6 100644 --- a/packages/mobile-ui-vue/components/switch/src/designer/switch.design.component.tsx +++ b/packages/mobile-ui-vue/components/switch/src/designer/switch.design.component.tsx @@ -16,7 +16,7 @@ */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; import { Switch, SwitchProps, switchProps } from '../..'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common';; import { useInputGroupDesignerRules } from './use-designer-rules'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/switch/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/switch/src/designer/use-designer-rules.ts index 2dd61acf6d3d432d61458a52c44c734268fcd367..71636e20fa353b03fb9daec8a404631049985c53 100644 --- a/packages/mobile-ui-vue/components/switch/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/switch/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { SwitchProperty } from "../property-config/switch.property-config"; export function useInputGroupDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/switch/src/property-config/switch.property-config.ts b/packages/mobile-ui-vue/components/switch/src/property-config/switch.property-config.ts index 0aa4d0bd192aefd6e7e304f396814b7c247d34bf..8e3ee681a1d02ff4216c1920a8b31a18ec2082ed 100644 --- a/packages/mobile-ui-vue/components/switch/src/property-config/switch.property-config.ts +++ b/packages/mobile-ui-vue/components/switch/src/property-config/switch.property-config.ts @@ -1,55 +1,56 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { InputBaseProperty } from '@farris/mobile-ui-vue/common'; export class SwitchProperty extends InputBaseProperty { + constructor(componentId: string, designerHostService: any) { + super(componentId, designerHostService); + } - constructor(componentId: string, designerHostService: any) { - super(componentId, designerHostService); - } + getEditorProperties(propertyData: any) { + const self = this; + const editorProperties = self.getComponentConfig( + propertyData, + {}, + { + disabled: { + visible: false + }, + placeholder: { + visible: false + }, + // onColor: { + // description: '', + // title: '打开时背景色', + // type: 'string' + // }, + // offColor: { + // description: '', + // title: '关闭时背景色', + // type: 'string' + // }, + size: { + description: '', + title: '尺寸', + type: 'enum', + editor: { + data: [ + { + id: 'small', + name: '小号' + }, + { + id: 'medium', + name: '中号' + }, + { + id: 'large', + name: '大号' + } + ] + } + } + } + ); - - getEditorProperties(propertyData: any) { - const self = this; - const editorProperties = self.getComponentConfig(propertyData, { type: "switch" }, { - onBackground: { - description: "", - title: "打开时背景色", - type: "string" - }, - offBackground: { - description: "", - title: "关闭时背景色", - type: "string" - }, - size: { - description: "", - title: "尺寸", - type: "number" - }, - // size:{ - // description: "", - // title: "尺寸", - // type: "enum", - // editor:{ - // data: [ - // { - // id: "small", - // name: "小号" - // }, - // { - // id: "medium", - // name: "中号" - // }, - // { - // id: "large", - // name: "大号" - // } - // ] - // } - // } - }); - - return editorProperties; - } - - + return editorProperties; + } } diff --git a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx index cf2570614277b98a00fa676f513c5e1e5535e282..5035a7c20f67e9d9f11b61133c5fa955086a0ee1 100644 --- a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx +++ b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import { CSSProperties, SetupContext, computed, defineComponent } from 'vue'; -import { Loading } from '@components/loading'; -import { addUnit, useBem } from '@components/common'; +import { Loading } from '@farris/mobile-ui-vue/loading'; +import { addUnit, useBem } from '@farris/mobile-ui-vue/common'; import { SwitchProps, switchProps } from './switch.props'; const name = 'fm-switch'; @@ -32,6 +32,15 @@ export default defineComponent({ return props.modelValue === props.activeValue; }); + const sizeMap = { + small: 16, + medium: 22, + large: 28 + }; + const SwitchSize = computed(()=>{ + return sizeMap[props.size]; + }); + const onClick = (event: MouseEvent) => { emit('click', event); @@ -45,7 +54,7 @@ export default defineComponent({ }; const renderLoading = () => { - return ; + return ; }; const switchClass = computed(() => ({ @@ -57,7 +66,7 @@ export default defineComponent({ })); const switchSize = computed(() => { - const height = props.size + 2; + const height = SwitchSize.value + 2; const width = height * 1.66; return { height, @@ -79,8 +88,8 @@ export default defineComponent({ const { height, width } = switchSize.value; const translateX = checked.value ? width - height : 0; return { - width: addUnit(props.size), - height: addUnit(props.size), + width: addUnit(SwitchSize.value), + height: addUnit(SwitchSize.value), transform: `translateX(${addUnit(translateX)})` }; }); diff --git a/packages/mobile-ui-vue/components/switch/src/switch.props.ts b/packages/mobile-ui-vue/components/switch/src/switch.props.ts index d208781ec4516e8a0b050224692017bc1023c489..5bd636f72414fed541b31711af568c8614695490 100644 --- a/packages/mobile-ui-vue/components/switch/src/switch.props.ts +++ b/packages/mobile-ui-vue/components/switch/src/switch.props.ts @@ -13,12 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createPropsResolver } from '@/components/dynamic-resolver'; -import { ExtractPropTypes } from 'vue'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; +import { ExtractPropTypes, PropType } from 'vue'; import switchSchema from './schema/switch.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; +export enum SwitchSize { + small = 'small', + medium = 'medium', + large = 'large' +} + export const switchProps = { modelValue: { type: Boolean, default: false }, @@ -28,7 +34,7 @@ export const switchProps = { loading: { type: Boolean, default: false }, - size: { type: Number, default: 22 }, + size: { type: String as PropType, default: SwitchSize.medium }, activeColor: { type: String, default: '' }, @@ -41,7 +47,7 @@ export const switchProps = { export type SwitchProps = ExtractPropTypes; -export const propsResolver = createPropsResolver( +export const propsResolverGenerator = getPropsResolverGenerator( switchProps, switchSchema, schemaMapper, diff --git a/packages/mobile-ui-vue/components/tab-bar/index.ts b/packages/mobile-ui-vue/components/tab-bar/index.ts index c0fa53f304c81b3813ebdd23ffb7a6de51a16cf6..f95d837125513314d44f3adae836fd365c65e0bf 100644 --- a/packages/mobile-ui-vue/components/tab-bar/index.ts +++ b/packages/mobile-ui-vue/components/tab-bar/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import TabBarInstallless from './src/tab-bar.component'; export * from './src/tab-bar.props'; diff --git a/packages/mobile-ui-vue/components/tab-bar/src/components/tab-bar-item.component.tsx b/packages/mobile-ui-vue/components/tab-bar/src/components/tab-bar-item.component.tsx index 5f4b84063ff7d4816fd51aa98822fb76f3fd0d99..c57d108758077612dfe4828a5d3aca34443d0bc6 100644 --- a/packages/mobile-ui-vue/components/tab-bar/src/components/tab-bar-item.component.tsx +++ b/packages/mobile-ui-vue/components/tab-bar/src/components/tab-bar-item.component.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import { SetupContext, computed, defineComponent } from 'vue'; -import { preventDefault, useBem } from '@components/common'; -import FmIcon from '@components/icon'; +import { preventDefault, useBem } from '@farris/mobile-ui-vue/common'; +import FmIcon from '@farris/mobile-ui-vue/icon'; import { TAB_BAR_ITEM_NAME, TabBarItemProps, tabBarItemProps } from './tab-bar-item.props'; export default defineComponent({ diff --git a/packages/mobile-ui-vue/components/tab-bar/src/composition/use-tab-bar-touch.ts b/packages/mobile-ui-vue/components/tab-bar/src/composition/use-tab-bar-touch.ts index 720785397f84f47ce2cf9b1bd14341577857740b..fe4e8e326f1357e38182eba7418dede421b7e407 100644 --- a/packages/mobile-ui-vue/components/tab-bar/src/composition/use-tab-bar-touch.ts +++ b/packages/mobile-ui-vue/components/tab-bar/src/composition/use-tab-bar-touch.ts @@ -1,5 +1,5 @@ -import { useMonmentum, useTouch } from "@components/common"; -import { preventDefault } from "@components/common"; +import { useMonmentum, useTouch } from "@farris/mobile-ui-vue/common"; +import { preventDefault } from "@farris/mobile-ui-vue/common"; import { reactive } from "vue"; export const useTabBarTouch = () => { diff --git a/packages/mobile-ui-vue/components/tab-bar/src/tab-bar.component.tsx b/packages/mobile-ui-vue/components/tab-bar/src/tab-bar.component.tsx index 8b5487f81a36c56759f9d1f8953e451c6db4a6e9..93d68d47155d518e7e1741e689a6fa56b0dbee54 100644 --- a/packages/mobile-ui-vue/components/tab-bar/src/tab-bar.component.tsx +++ b/packages/mobile-ui-vue/components/tab-bar/src/tab-bar.component.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { SetupContext, computed, defineComponent, ref, onMounted, watch } from 'vue'; -import { addUnit, useBem } from '@components/common'; +import { addUnit, useBem } from '@farris/mobile-ui-vue/common'; import { TAB_BAR_NAME, TabBarItemProps, TabBarProps, tabBarProps } from './tab-bar.props'; import TabBarItem from './components/tab-bar-item.component'; import { useTabBarTouch } from './composition'; diff --git a/packages/mobile-ui-vue/components/tab/index.ts b/packages/mobile-ui-vue/components/tab/index.ts index 61872695b40c985450919ae03d511342b10c5791..66c8bd8c8255a4924aac3d63aef9319cd4eceed1 100644 --- a/packages/mobile-ui-vue/components/tab/index.ts +++ b/packages/mobile-ui-vue/components/tab/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import TabInstallless from '../tabs/src/components/tab.component'; export * from '../tabs/src/components/tab.props'; diff --git a/packages/mobile-ui-vue/components/tabs/index.ts b/packages/mobile-ui-vue/components/tabs/index.ts index 6ba70604adbe336802d78f447ff55aba86ae155b..3e8f6894fb11c0bd24ec32f7559b1ddb462832dc 100644 --- a/packages/mobile-ui-vue/components/tabs/index.ts +++ b/packages/mobile-ui-vue/components/tabs/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import TabsInstallless from './src/tabs.component'; export * from './src/tabs.props'; diff --git a/packages/mobile-ui-vue/components/tabs/src/components/tab.component.tsx b/packages/mobile-ui-vue/components/tabs/src/components/tab.component.tsx index 8c1c7c69179d461ce4893ef23ceda5bca4bafe4f..bfde60afce836af1155c779df41ee0622119f05c 100644 --- a/packages/mobile-ui-vue/components/tabs/src/components/tab.component.tsx +++ b/packages/mobile-ui-vue/components/tabs/src/components/tab.component.tsx @@ -24,7 +24,7 @@ import { } from 'vue'; import { TAB_NAME, tabProps, TabProps } from './tab.props'; import { TABS_CONTEXT_KEY } from '../composition/type'; -import { isDef, useBem } from '@components/common'; +import { isDef, useBem } from '@farris/mobile-ui-vue/common'; export default defineComponent({ name: TAB_NAME, diff --git a/packages/mobile-ui-vue/components/tabs/src/composition/use-swipe.tsx b/packages/mobile-ui-vue/components/tabs/src/composition/use-swipe.tsx index d76024d0e247df70f8238c69458b8416185c28e8..ada59a693f22f250789cd1f8a5fda522a83295a2 100644 --- a/packages/mobile-ui-vue/components/tabs/src/composition/use-swipe.tsx +++ b/packages/mobile-ui-vue/components/tabs/src/composition/use-swipe.tsx @@ -1,6 +1,6 @@ import { reactive, ref, Ref, computed } from 'vue'; -import { useTouch, useEventListener } from '@components/common'; -import { preventDefault } from '@components/common'; +import { useTouch, useEventListener } from '@farris/mobile-ui-vue/common'; +import { preventDefault } from '@farris/mobile-ui-vue/common'; import { TabsProps } from '../tabs.props'; import { UseSwipe, UseTabs } from './type'; diff --git a/packages/mobile-ui-vue/components/tabs/src/composition/use-tabs.ts b/packages/mobile-ui-vue/components/tabs/src/composition/use-tabs.ts index 9cb0aca88b01ad7d7b20bc3d4957c8e02b719628..90a9b73287d310dc333f09a5645a5a9113c426ee 100644 --- a/packages/mobile-ui-vue/components/tabs/src/composition/use-tabs.ts +++ b/packages/mobile-ui-vue/components/tabs/src/composition/use-tabs.ts @@ -2,7 +2,7 @@ import { SetupContext, computed, ref, watch, isVNode, VNode, Fragment } from 'vu import { TabsProps } from '../tabs.props'; import Tab from '../components/tab.component'; import { TabProps } from '../components/tab.props'; -import { isDef } from '@components/common'; +import { isDef } from '@farris/mobile-ui-vue/common'; import { UseTabs } from './type'; export function useTabs(props: TabsProps, context: SetupContext): UseTabs { diff --git a/packages/mobile-ui-vue/components/tabs/src/tabs.component.tsx b/packages/mobile-ui-vue/components/tabs/src/tabs.component.tsx index e2e5bf0cc43d980a803beef72ceb8bd29ad0cbfe..c1c9bf17b09cc6f7ad01735671b0ecaa6c3212e5 100644 --- a/packages/mobile-ui-vue/components/tabs/src/tabs.component.tsx +++ b/packages/mobile-ui-vue/components/tabs/src/tabs.component.tsx @@ -16,10 +16,10 @@ import { defineComponent, SetupContext, computed, ref, provide, readonly, CSSProperties } from 'vue'; import { TABS_NAME, tabsProps, TabsProps } from './tabs.props'; import { TabsContext, TABS_CONTEXT_KEY } from './composition/type'; -import { useBem } from '@components/common'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { useTabs } from './composition/use-tabs'; import { useSwipe } from './composition/use-swipe'; -import { TabBar, TabBarItemProps } from '@components/tab-bar'; +import { TabBar, TabBarItemProps } from '@farris/mobile-ui-vue/tab-bar'; export default defineComponent({ name: TABS_NAME, diff --git a/packages/mobile-ui-vue/components/tag/index.ts b/packages/mobile-ui-vue/components/tag/index.ts index fed37ee7c3f1e0ebf4c8b091027b9af9d8371b22..e497f0e8a4a36b7c1e3694ec1004b5869459b99f 100644 --- a/packages/mobile-ui-vue/components/tag/index.ts +++ b/packages/mobile-ui-vue/components/tag/index.ts @@ -1,4 +1,4 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import TagInstallless from './src/tag.component'; export * from './src/tag.props'; diff --git a/packages/mobile-ui-vue/components/tag/src/tag.component.tsx b/packages/mobile-ui-vue/components/tag/src/tag.component.tsx index 49350360b8aea983a3719f1e344cf6adf8e50807..93e68738b0fb1787f2bee491b8e1e967baceef3e 100644 --- a/packages/mobile-ui-vue/components/tag/src/tag.component.tsx +++ b/packages/mobile-ui-vue/components/tag/src/tag.component.tsx @@ -1,7 +1,7 @@ import { computed, CSSProperties, defineComponent, Transition } from 'vue'; import { TAG_NAME, TagProps, tagProps } from './tag.props'; -import { stopPropagation, useBem } from '@/components/common'; -import { Icon } from '@/components/icon'; +import { stopPropagation, useBem } from '@farris/mobile-ui-vue/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; export default defineComponent({ name: TAG_NAME, diff --git a/packages/mobile-ui-vue/components/textarea/index.ts b/packages/mobile-ui-vue/components/textarea/index.ts index b41ca39b337f65a5bb3ca781de054e03e14a6fcf..524590e7db14854f5d4a91ead7397ac0cdf8f77f 100644 --- a/packages/mobile-ui-vue/components/textarea/index.ts +++ b/packages/mobile-ui-vue/components/textarea/index.ts @@ -1,7 +1,7 @@ -import { withInstall } from '@components/common'; +import { withInstall, withRegister, withRegisterDesigner } from '@farris/mobile-ui-vue/common'; import TextareaInstallless from './src/textarea.component'; import TextareaDesign from './src/designer/textarea.design.component'; -import { propsResolver } from './src/textarea.props'; +import { propsResolverGenerator } from './src/textarea.props'; export * from './src/textarea.props'; @@ -9,15 +9,8 @@ const TEXTAREA_REGISTERED_NAME = 'textarea'; const Textarea = withInstall(TextareaInstallless); -Textarea.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { - componentMap[TEXTAREA_REGISTERED_NAME] = Textarea; - propsResolverMap[TEXTAREA_REGISTERED_NAME] = propsResolver; -}; -Textarea.registerDesigner = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record) => { - componentMap[TEXTAREA_REGISTERED_NAME] = TextareaDesign; - propsResolverMap[TEXTAREA_REGISTERED_NAME] = propsResolver; -}; - +withRegister(Textarea, { name: TEXTAREA_REGISTERED_NAME, propsResolverGenerator }); +withRegisterDesigner(Textarea, { name: TEXTAREA_REGISTERED_NAME, propsResolverGenerator, designerComponent: TextareaDesign }); export { Textarea }; export default Textarea; diff --git a/packages/mobile-ui-vue/components/textarea/src/designer/textarea.design.component.tsx b/packages/mobile-ui-vue/components/textarea/src/designer/textarea.design.component.tsx index 470bb1e1279491403ef6145d44170101e50a2acc..ebdd1187f9ee2327d23bb9770eadcb8015ec3dfd 100644 --- a/packages/mobile-ui-vue/components/textarea/src/designer/textarea.design.component.tsx +++ b/packages/mobile-ui-vue/components/textarea/src/designer/textarea.design.component.tsx @@ -15,7 +15,8 @@ * limitations under the License. */ import { computed, defineComponent, inject, onMounted, readonly, ref, SetupContext } from 'vue'; -import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@/components/designer-canvas';import { TEXTAREA_NAME, textareaProps, TextareaProps } from '../textarea.props'; +import { DesignerHostService, DesignerItemContext, useDesignerComponent } from '@farris/mobile-ui-vue/common'; +import { TEXTAREA_NAME, textareaProps, TextareaProps } from '../textarea.props'; import { useTextareaDesignerRules } from './use-designer-rules'; import Textarea from '../..'; @@ -37,6 +38,7 @@ export default defineComponent({ const inputGroupProps = computed(() => ({ ...props, + type:"textarea", editable: false, modelValue:null })); diff --git a/packages/mobile-ui-vue/components/textarea/src/designer/use-designer-rules.ts b/packages/mobile-ui-vue/components/textarea/src/designer/use-designer-rules.ts index 03c38f7cbd99efeaa3f9a010d3e023dfeb39154f..8359c1491343b5846f479d82d999da50655a8a06 100644 --- a/packages/mobile-ui-vue/components/textarea/src/designer/use-designer-rules.ts +++ b/packages/mobile-ui-vue/components/textarea/src/designer/use-designer-rules.ts @@ -1,4 +1,4 @@ -import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@/components/designer-canvas"; +import { ComponentSchema, DesignerComponentInstance, DesignerItemContext, UseDesignerRules } from "@farris/mobile-ui-vue/common"; import { TextareaProperty } from "../property-config/textarea.property-config"; export function useTextareaDesignerRules(designItemContext: DesignerItemContext, designerHostService): UseDesignerRules { diff --git a/packages/mobile-ui-vue/components/textarea/src/property-config/textarea.property-config.ts b/packages/mobile-ui-vue/components/textarea/src/property-config/textarea.property-config.ts index 3db2084f9a3a674c5d39edc763d039603a171faf..481dff85bdea41791a163d91b48162fac531a468 100644 --- a/packages/mobile-ui-vue/components/textarea/src/property-config/textarea.property-config.ts +++ b/packages/mobile-ui-vue/components/textarea/src/property-config/textarea.property-config.ts @@ -1,4 +1,4 @@ -import { InputBaseProperty } from "@/components/common/src/entity/input-base-property"; +import { InputBaseProperty } from "@farris/mobile-ui-vue/common"; export class TextareaProperty extends InputBaseProperty { @@ -8,11 +8,6 @@ export class TextareaProperty extends InputBaseProperty { getEditorProperties(propertyData: any) { return this.getComponentConfig(propertyData, { type: "textarea" }, { - placeholder: { - description: "空值时,输入控件内的占位文本", - title: "提示文本", - type: "string" - }, rows: { description: "", title: "文本区域可见的行数", @@ -28,10 +23,15 @@ export class TextareaProperty extends InputBaseProperty { type: "boolean" }, maxLength: { - description: "", - title: "文本最大长度", + description: "文本最大长度", + title: "最大长度", type: "number" - } + }, + autoHeight: { + description: "", + title: "自动高度", + type: "boolean" + }, }); } diff --git a/packages/mobile-ui-vue/components/textarea/src/schema/schema-mapper.ts b/packages/mobile-ui-vue/components/textarea/src/schema/schema-mapper.ts index d1c21abde8bc365f647bada2718e821e5008a2b0..42b3a02141cbb40a799489f47e0c50df2a3e29f9 100644 --- a/packages/mobile-ui-vue/components/textarea/src/schema/schema-mapper.ts +++ b/packages/mobile-ui-vue/components/textarea/src/schema/schema-mapper.ts @@ -1,4 +1,4 @@ -import { MapperFunction, resolveAppearance } from '@/components/dynamic-resolver'; +import { MapperFunction, resolveAppearance } from '@farris/mobile-ui-vue/dynamic-resolver'; export const schemaMapper = new Map([ ['appearance', resolveAppearance], diff --git a/packages/mobile-ui-vue/components/textarea/src/schema/schema-resolver.ts b/packages/mobile-ui-vue/components/textarea/src/schema/schema-resolver.ts index 660e1e609e11d876dc4227ce631026bfbee8312a..7c8af7fc63d68147438fc329e74ebce565df4ef7 100644 --- a/packages/mobile-ui-vue/components/textarea/src/schema/schema-resolver.ts +++ b/packages/mobile-ui-vue/components/textarea/src/schema/schema-resolver.ts @@ -1,4 +1,4 @@ -import { DynamicResolver } from "@/components/dynamic-resolver"; +import { DynamicResolver } from "@farris/mobile-ui-vue/dynamic-resolver"; export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { return schema; diff --git a/packages/mobile-ui-vue/components/textarea/src/textarea.component.tsx b/packages/mobile-ui-vue/components/textarea/src/textarea.component.tsx index 21b52cfe0a3abe8f6501a60d7167710fc42e7fc7..3c626226999b867c27f60a10a78c43dfc08bf8aa 100644 --- a/packages/mobile-ui-vue/components/textarea/src/textarea.component.tsx +++ b/packages/mobile-ui-vue/components/textarea/src/textarea.component.tsx @@ -14,16 +14,14 @@ * limitations under the License. */ -import { defineComponent, SetupContext } from 'vue'; -import { useBem } from '@/components/common'; -import InputGroup from "@/components/input-group"; +import { defineComponent } from 'vue'; +import InputGroup from "@farris/mobile-ui-vue/input-group"; import { TEXTAREA_NAME, textareaProps, TextareaProps } from './textarea.props'; export default defineComponent({ name: TEXTAREA_NAME, props: textareaProps, - setup(props: TextareaProps, context: SetupContext) { - const { bem } = useBem(TEXTAREA_NAME); + setup(props: TextareaProps, context) { const { emit } = context; const handleValueChange = (value: string | number) => { @@ -31,7 +29,7 @@ export default defineComponent({ }; return () => ( - + ); } }); diff --git a/packages/mobile-ui-vue/components/textarea/src/textarea.props.ts b/packages/mobile-ui-vue/components/textarea/src/textarea.props.ts index 48beaf60bcc7884720f4101b941e0a0dcf016ca7..4eb0aa16e86e908e071be975a8d1ac9e83c4ebe6 100644 --- a/packages/mobile-ui-vue/components/textarea/src/textarea.props.ts +++ b/packages/mobile-ui-vue/components/textarea/src/textarea.props.ts @@ -1,6 +1,6 @@ import { ExtractPropTypes } from 'vue'; -import { inputCommonProps } from '@/components/input-group'; -import { createPropsResolver } from '@/components/dynamic-resolver'; +import { inputCommonProps } from '@farris/mobile-ui-vue/input-group'; +import { getPropsResolverGenerator } from '@farris/mobile-ui-vue/dynamic-resolver'; import textareaSchema from './schema/textarea.schema.json'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; @@ -10,7 +10,7 @@ export const TEXTAREA_NAME = 'FmTextarea'; export const textareaProps = { ...inputCommonProps, - autoSize: { type: Boolean, default: undefined }, + autoHeight: { type: Boolean, default: undefined }, rows: { type: Number, default: undefined }, @@ -23,4 +23,4 @@ export const textareaProps = { export type TextareaProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(textareaProps, textareaSchema, schemaMapper, schemaResolver); +export const propsResolverGenerator = getPropsResolverGenerator(textareaProps, textareaSchema, schemaMapper, schemaResolver); diff --git a/packages/mobile-ui-vue/components/time-picker/index.ts b/packages/mobile-ui-vue/components/time-picker/index.ts index 04847b04b70b759a13e39c339c31b455406c8a1b..62ab9fe9bdab934a2e7da805fdc43236492c7c6c 100644 --- a/packages/mobile-ui-vue/components/time-picker/index.ts +++ b/packages/mobile-ui-vue/components/time-picker/index.ts @@ -1,8 +1,8 @@ -import { withInstall } from '@components/common'; +import { withInstall } from '@farris/mobile-ui-vue/common'; import TimePickerInstallless from './src/time-picker.component'; import TimePickerPanelInstallless from './src/time-picker-panel.component'; -export * from './src/time-picker-panel.props'; +export { TimePickerType } from './src/composition'; const TimePickerPanel = withInstall(TimePickerPanelInstallless); const TimePicker = withInstall(TimePickerInstallless); diff --git a/packages/mobile-ui-vue/components/time-picker/src/composition/index.ts b/packages/mobile-ui-vue/components/time-picker/src/composition/index.ts index 0e0b60b69b9b177c3e0e88843c21320bf6093ac2..247698b0dbe7306e92255cd272d6719641098e54 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/composition/index.ts +++ b/packages/mobile-ui-vue/components/time-picker/src/composition/index.ts @@ -1 +1,2 @@ +export * from './type'; export * from './use-time-columns'; diff --git a/packages/mobile-ui-vue/components/time-picker/src/composition/type.ts b/packages/mobile-ui-vue/components/time-picker/src/composition/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..9cd9a523dfc6e4dfc8ee30093b606d32c064d00d --- /dev/null +++ b/packages/mobile-ui-vue/components/time-picker/src/composition/type.ts @@ -0,0 +1,13 @@ + +export enum TimePickerType { + Hours = 'hours', + HoursMinutes = 'hours-minutes', + HoursMinutesSeconds = 'hours-minutes-seconds', + Time= 'time', +} + +export enum TimeColumn { + Hours = 'hours', + Minutes = 'minutes', + Seconds= 'seconds', +}; diff --git a/packages/mobile-ui-vue/components/time-picker/src/composition/use-time-columns.ts b/packages/mobile-ui-vue/components/time-picker/src/composition/use-time-columns.ts index 0451215d9e52baf35dbd02227efacae44d2c1ed1..088c793bc2fc394df20063d06ea0902426d19e00 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/composition/use-time-columns.ts +++ b/packages/mobile-ui-vue/components/time-picker/src/composition/use-time-columns.ts @@ -1,13 +1,9 @@ import { computed, watch, ref } from 'vue'; -import { Columns, Column, PickerChange } from '@components/picker'; -import { formatTime, getTimeRecord, } from "@components/common"; -import { TimePickerPanelProps, TimePickerPanelTypeMap } from "../time-picker-panel.props"; +import { Columns, Column, PickerChange } from '@farris/mobile-ui-vue/picker'; +import { formatTime, getTimeRecord, } from "@farris/mobile-ui-vue/common"; +import { TimePickerPanelProps } from "../time-picker-panel.props"; +import { TimeColumn, TimePickerType } from './type'; -enum TimeColumn { - Hours = 'hours', - Minutes = 'minutes', - Seconds= 'seconds', -} export const useTimeColumns = (props: TimePickerPanelProps) => { const textField = 'text'; @@ -104,7 +100,7 @@ export const useTimeColumns = (props: TimePickerPanelProps) => { }; const columnsMap = computed(() => { - const type = props.type === TimePickerPanelTypeMap.Time ? TimePickerPanelTypeMap.HoursMinutesSeconds : props.type; + const type = props.type === TimePickerType.Time ? TimePickerType.HoursMinutesSeconds : props.type; return type.split('-'); }); diff --git a/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.component.tsx b/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.component.tsx index 313e4eba65ea615a36f797423a1a4f0d14ac6a89..0c59b8cb959830fa208b4f502907772c10e9d269 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.component.tsx +++ b/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.component.tsx @@ -1,6 +1,6 @@ import { defineComponent } from 'vue'; -import { PickerPanel, PickerChange } from '@components/picker'; -import { useBem } from '@components/common'; +import { PickerPanel, PickerChange } from '@farris/mobile-ui-vue/picker'; +import { useBem } from '@farris/mobile-ui-vue/common'; import { useTimeColumns } from './composition'; import { timePickerPanelProps, TIME_PICKER_PANEL_NAME } from './time-picker-panel.props'; diff --git a/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.props.ts b/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.props.ts index 4789cb0b248207269eb2130c398dc5a27eceb39f..2759e6d31601e69ec85243a4f8ff828e3f5819ce 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.props.ts +++ b/packages/mobile-ui-vue/components/time-picker/src/time-picker-panel.props.ts @@ -1,20 +1,13 @@ import { ExtractPropTypes, PropType } from 'vue'; +import { TimePickerType } from './composition/type'; export const TIME_PICKER_PANEL_NAME = 'FmTimePickerPanel'; -export const enum TimePickerPanelTypeMap { - Hours = 'hours', - HoursMinutes = 'hours-minutes', - HoursMinutesSeconds = 'hours-minutes-seconds', - Time= 'time', -} - -export type TimePickerPanelType = `${TimePickerPanelTypeMap}`; export const timePickerPanelProps = { title: { type: String, default: '' }, - type: { type: String as PropType, default: TimePickerPanelTypeMap.Time }, + type: { type: String as PropType, default: TimePickerType.Time }, modelValue: { type: String, default: '' }, diff --git a/packages/mobile-ui-vue/components/time-picker/src/time-picker.component.tsx b/packages/mobile-ui-vue/components/time-picker/src/time-picker.component.tsx index 712e3934b93076a9f0f9bb3dbc9932638d6e3a85..2176ad3719ae8136a2e5259126d81c5614580131 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/time-picker.component.tsx +++ b/packages/mobile-ui-vue/components/time-picker/src/time-picker.component.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent } from 'vue'; -import { useBem } from '@components/common'; -import ButtonEdit from '@/components/button-edit'; -import { usePickerInputState } from '@/components/picker'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import ButtonEdit from '@farris/mobile-ui-vue/button-edit'; +import { usePickerInputState } from '@farris/mobile-ui-vue/picker'; import { timePickerProps, TIME_PICKER_NAME } from './time-picker.props'; import TimePickerPanel from './time-picker-panel.component'; diff --git a/packages/mobile-ui-vue/components/time-picker/src/time-picker.props.ts b/packages/mobile-ui-vue/components/time-picker/src/time-picker.props.ts index 3dd704548b29e00c90517ce10d751cd16d30c7b9..6fe0505ec0793698f8a5d44f2f4b54073d3e4701 100644 --- a/packages/mobile-ui-vue/components/time-picker/src/time-picker.props.ts +++ b/packages/mobile-ui-vue/components/time-picker/src/time-picker.props.ts @@ -1,5 +1,5 @@ import { ExtractPropTypes } from 'vue'; -import { buttonEditProps } from '@/components/button-edit'; +import { buttonEditProps } from '@farris/mobile-ui-vue/button-edit'; import { timePickerPanelProps } from './time-picker-panel.props'; export const TIME_PICKER_NAME = 'FmTimePicker'; @@ -7,6 +7,8 @@ export const TIME_PICKER_NAME = 'FmTimePicker'; export const timePickerProps = { ...buttonEditProps, ...timePickerPanelProps, + + placeholder: { type: String, default: '请选择时间' }, round: { type: Boolean, default: false } }; diff --git a/packages/mobile-ui-vue/components/toast/src/index.tsx b/packages/mobile-ui-vue/components/toast/src/index.tsx index 5e2d0ebed502de0fabafdb47def2c9a576351200..de4c6e1487e15dae993c34b14f4e81b6a48b9643 100644 --- a/packages/mobile-ui-vue/components/toast/src/index.tsx +++ b/packages/mobile-ui-vue/components/toast/src/index.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import FMToast from './toast.component'; -import { isObject, inBrowser } from '@components/common'; -import { mountComponent, usePopupState } from '@components/common'; +import { isObject, inBrowser } from '@farris/mobile-ui-vue/common'; +import { mountComponent, usePopupState } from '@farris/mobile-ui-vue/common'; import { App } from 'vue'; let instance; diff --git a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx index 3f129dc65e5ccedd4ffac074c8f074ebdabb9995..785b0a7ace05a9f852d8f2efb1be34b547e7a08e 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx +++ b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx @@ -15,9 +15,9 @@ */ import { SetupContext, computed, defineComponent } from 'vue'; import { ToastProps, toastProps } from './toast.props'; -import { useBem } from '@components/common'; -import { Icon } from '@components/icon'; -import { Overlay } from '@components/overlay'; +import { useBem } from '@farris/mobile-ui-vue/common'; +import { Icon } from '@farris/mobile-ui-vue/icon'; +import { Overlay } from '@farris/mobile-ui-vue/overlay'; const name = 'fm-toast'; diff --git a/packages/mobile-ui-vue/demos/date-picker/basic.vue b/packages/mobile-ui-vue/demos/date-picker/basic.vue index dc31ef18acad40e47bd275598ff70803daa6fc68..86f0e36bf23ab03e42f4d23ee10bbb4719871216 100644 --- a/packages/mobile-ui-vue/demos/date-picker/basic.vue +++ b/packages/mobile-ui-vue/demos/date-picker/basic.vue @@ -3,5 +3,5 @@ diff --git a/packages/mobile-ui-vue/demos/date-picker/formatter.vue b/packages/mobile-ui-vue/demos/date-picker/formatter.vue index 7d37a997b2a36a0673bdcdbabfb0c14e6993b6bc..3a5b6ab87630a9e7053aeb7cbd1a4a098b63224b 100644 --- a/packages/mobile-ui-vue/demos/date-picker/formatter.vue +++ b/packages/mobile-ui-vue/demos/date-picker/formatter.vue @@ -2,7 +2,7 @@ diff --git a/packages/mobile-ui-vue/demos/date-picker/min-max.vue b/packages/mobile-ui-vue/demos/date-picker/min-max.vue index bccee245541c683bf3ce5a63d13e2d58ba1446ba..1786b1943e8efbd57f8308b9cf371dc3041e8a7d 100644 --- a/packages/mobile-ui-vue/demos/date-picker/min-max.vue +++ b/packages/mobile-ui-vue/demos/date-picker/min-max.vue @@ -7,5 +7,5 @@ diff --git a/packages/mobile-ui-vue/demos/date-picker/type.vue b/packages/mobile-ui-vue/demos/date-picker/type.vue index 6a453c35487423e37906276a4ce983a52b007a1c..ea3bd2cf5a9018be325d5bbd08d9b25f4fa103bd 100644 --- a/packages/mobile-ui-vue/demos/date-picker/type.vue +++ b/packages/mobile-ui-vue/demos/date-picker/type.vue @@ -1,7 +1,7 @@ diff --git a/packages/mobile-ui-vue/demos/date-time-picker/basic.vue b/packages/mobile-ui-vue/demos/date-time-picker/basic.vue index 58ba9b637e76f83eedf076ed5f5b9aea4a84b6dc..915b2b0ebcbdad6ac96c161c5611eb806bdf7976 100644 --- a/packages/mobile-ui-vue/demos/date-time-picker/basic.vue +++ b/packages/mobile-ui-vue/demos/date-time-picker/basic.vue @@ -2,5 +2,5 @@ diff --git a/packages/mobile-ui-vue/demos/date-time-picker/formatter.vue b/packages/mobile-ui-vue/demos/date-time-picker/formatter.vue index f0fba9ab5b03909db30715fe43131a066c8c6346..d95f9652094cbcc3350a26bfc1edd370b7c2898d 100644 --- a/packages/mobile-ui-vue/demos/date-time-picker/formatter.vue +++ b/packages/mobile-ui-vue/demos/date-time-picker/formatter.vue @@ -2,7 +2,7 @@ diff --git a/packages/mobile-ui-vue/demos/date-time-picker/max&min.vue b/packages/mobile-ui-vue/demos/date-time-picker/max&min.vue index 9e55e861af69459398cc77b7ab2e7305e77a18ec..2ed704b7d12d47319cc729731f2e6eba475bf247 100644 --- a/packages/mobile-ui-vue/demos/date-time-picker/max&min.vue +++ b/packages/mobile-ui-vue/demos/date-time-picker/max&min.vue @@ -2,7 +2,7 @@ diff --git a/packages/mobile-ui-vue/demos/dialog/avatar.vue b/packages/mobile-ui-vue/demos/dialog/avatar.vue index f370355d8993dd740412698294f7e8377fe23923..85086ba515a70208efa924ca23a5e27455c4d388 100644 --- a/packages/mobile-ui-vue/demos/dialog/avatar.vue +++ b/packages/mobile-ui-vue/demos/dialog/avatar.vue @@ -15,7 +15,7 @@ diff --git a/packages/mobile-ui-vue/demos/form/control-type.vue b/packages/mobile-ui-vue/demos/form/control-type.vue index 35232bfbbfc6b5b9db203a240915d2425a7994be..04da0d31a512bb90f0f98851b0b6c6db678a49d1 100644 --- a/packages/mobile-ui-vue/demos/form/control-type.vue +++ b/packages/mobile-ui-vue/demos/form/control-type.vue @@ -10,14 +10,14 @@ - + > import { onMounted, ref } from 'vue'; -import { Notify } from '@components/notify'; +import { Notify } from '@farris/mobile-ui-vue/notify'; const fmIconDemoRef = ref(null); diff --git a/packages/mobile-ui-vue/demos/lookup/basic.vue b/packages/mobile-ui-vue/demos/lookup/basic.vue index ef8540ab37b470332dfd2efc0bf2320a98dd7001..94eed4f9e065ecb122f8c8065c99ad48418540c1 100644 --- a/packages/mobile-ui-vue/demos/lookup/basic.vue +++ b/packages/mobile-ui-vue/demos/lookup/basic.vue @@ -9,7 +9,7 @@ diff --git a/packages/mobile-ui-vue/demos/popup/position.vue b/packages/mobile-ui-vue/demos/popup/position.vue index 44966d393d2bdd667b957d4810056ffb51e8f115..850bbf2408ddea93adc801ec5d48793f6796e835 100644 --- a/packages/mobile-ui-vue/demos/popup/position.vue +++ b/packages/mobile-ui-vue/demos/popup/position.vue @@ -12,7 +12,7 @@