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,AAEAAAALAIAAAwAwR1NVQiCLJXoAAAE4AAAAVE9TLzI2F0mSAAABjAAAAGBjbWFwWyufJAAABOAAAAvwZ2x5ZmYmnHoAABJMAACrzGhlYWQk/WunAAAA4AAAADZoaGVhCL4FHgAAALwAAAAkaG10ePZ1/44AAAHsAAAC9GxvY2G8ducyAAAQ0AAAAXxtYXhwAdgBLgAAARgAAAAgbmFtZRCjPLAAAL4YAAACZ3Bvc3SlGMLJAADAgAAACxoAAQAAA4D/gABcBOz/8//0BOwAAQAAAAAAAAAAAAAAAAAAAL0AAQAAAAEAAP3cUZJfDzz1AAsEAAAAAADgf5PPAAAAAOB/k8//8/9+BOwDjgAAAAgAAgAAAAAAAAABAAAAvQEiABEAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKADAAPgACREZMVAAObGF0bgAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAQEAwGQAAUAAAKJAswAAACPAokCzAAAAesAMgEIAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAwOAA5r8DgP+AAAAD3ACCAAAAAQAAAAAAAAAAAAAAAAACBAAAAAQAAAAEAAAABAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQA//8EAP//BAD//wQAAAAEAP//BAAAAAQAAAAEAP//BAD//wQA//8EAf//BAD//wQAAAAEAAAABAAAAAQA//8EAAAABAD//wQAAAAEAAAABAD/9wQAAAAEAP//BAAAAAQAAAAEAP//BAAAAAQA//8EAAAABAAAAAQAAAAEAP//BAD//wQAAAAEAAAABAD//wQA//8EAP/7BAD//QQA//8EAP//BAAAAAQAAAAEAP//BAAAAAQAAAAEBgAABAAAAAQGAAAEAAAABAD//wQAAAAEAP//BAD//wQA//8EAAAABAAAAAQAAAAEAP//BAAAAAQAAAAEAP//BAD//wQAAAAEIQAABAD/8wQAAAAEAAAABAD/9QQA//4EAAAABAAAAAQA//4EAAAABAD//wQAAAAEAAAABAD//wQAAAAEAAAABAD/9gQA//8EAAAABAAAAAQAAAAEAAAABAAAAAQuAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAE7AAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABOwAAAQA//8EAP//BAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQA//8EAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAP/+BAD//wQAAAAEAP//BAD//wQAAAAEAAAABAAAAAQGAAAEAP//BAD//wQA//8EAP//BAD//wQAAAAEAAAABAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQA//8EAP/9BAD//wQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQA//sEAAAAAAAABQAAAAMAAAAsAAAABAAAAwQAAQAAAAAB/gADAAEAAAAsAAMACgAAAwQABAHSAAAAEgAQAAMAAuAs5gnmMOY05jfmOuad5r///wAA4ADmCeYL5jLmNuY55lXmp///AAAAAAAAAAAAAAAAAAAAAAABABIAagBqALQAuAC6ALwBTAAAALwAuwC6ALkAuAC3ALYAtQC0ALMAsgCxALAArwCuAK0ArACrAKoAqQCoAKcApgClAKQAowCiAKEAoACfAJsAngCdAJwAmgCZAJgAlwCWAJUAlACTAJIAkQCQADMAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApAHYAdQB0AHMAKgArAHAAcQByAG8ALABlAGYAZwBoAGkAagBrAGwAbQBuAGMAZABiADQALQAuAC8AMAAxADIANQA6ADcAOAA9AF4AXwBgAGEANgA7ADwAOQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZACgAWgBbAFwAXQAaABsAGAAZAA4ADwAKAAsADAANAAkACAAQABEAEgATABQAFQAWABcABwAFAAYABAADAAIAAQCAAIEAggCDAIQAhQCGAIcAiACJAIoAiwCMAI0AjgCPAHcAeAB5AHoAewB8AH0AfgB/AAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAjsAAAAAAAAAL0AAOAAAADgAAAAALwAAOABAADgAQAAALsAAOACAADgAgAAALoAAOADAADgAwAAALkAAOAEAADgBAAAALgAAOAFAADgBQAAALcAAOAGAADgBgAAALYAAOAHAADgBwAAALUAAOAIAADgCAAAALQAAOAJAADgCQAAALMAAOAKAADgCgAAALIAAOALAADgCwAAALEAAOAMAADgDAAAALAAAOANAADgDQAAAK8AAOAOAADgDgAAAK4AAOAPAADgDwAAAK0AAOAQAADgEAAAAKwAAOARAADgEQAAAKsAAOASAADgEgAAAKoAAOATAADgEwAAAKkAAOAUAADgFAAAAKgAAOAVAADgFQAAAKcAAOAWAADgFgAAAKYAAOAXAADgFwAAAKUAAOAYAADgGAAAAKQAAOAZAADgGQAAAKMAAOAaAADgGgAAAKIAAOAbAADgGwAAAKEAAOAcAADgHAAAAKAAAOAdAADgHQAAAJ8AAOAeAADgHgAAAJsAAOAfAADgHwAAAJ4AAOAgAADgIAAAAJ0AAOAhAADgIQAAAJwAAOAiAADgIgAAAJoAAOAjAADgIwAAAJkAAOAkAADgJAAAAJgAAOAlAADgJQAAAJcAAOAmAADgJgAAAJYAAOAnAADgJwAAAJUAAOAoAADgKAAAAJQAAOApAADgKQAAAJMAAOAqAADgKgAAAJIAAOArAADgKwAAAJEAAOAsAADgLAAAAJAAAOYJAADmCQAAADMAAOYLAADmCwAAABwAAOYMAADmDAAAAB0AAOYNAADmDQAAAB4AAOYOAADmDgAAAB8AAOYPAADmDwAAACAAAOYQAADmEAAAACEAAOYRAADmEQAAACIAAOYSAADmEgAAACMAAOYTAADmEwAAACQAAOYUAADmFAAAACUAAOYVAADmFQAAACYAAOYWAADmFgAAACcAAOYXAADmFwAAACgAAOYYAADmGAAAACkAAOYZAADmGQAAAHYAAOYaAADmGgAAAHUAAOYbAADmGwAAAHQAAOYcAADmHAAAAHMAAOYdAADmHQAAACoAAOYeAADmHgAAACsAAOYfAADmHwAAAHAAAOYgAADmIAAAAHEAAOYhAADmIQAAAHIAAOYiAADmIgAAAG8AAOYjAADmIwAAACwAAOYkAADmJAAAAGUAAOYlAADmJQAAAGYAAOYmAADmJgAAAGcAAOYnAADmJwAAAGgAAOYoAADmKAAAAGkAAOYpAADmKQAAAGoAAOYqAADmKgAAAGsAAOYrAADmKwAAAGwAAOYsAADmLAAAAG0AAOYtAADmLQAAAG4AAOYuAADmLgAAAGMAAOYvAADmLwAAAGQAAOYwAADmMAAAAGIAAOYyAADmMgAAADQAAOYzAADmMwAAAC0AAOY0AADmNAAAAC4AAOY2AADmNgAAAC8AAOY3AADmNwAAADAAAOY5AADmOQAAADEAAOY6AADmOgAAADIAAOZVAADmVQAAADUAAOZWAADmVgAAADoAAOZXAADmVwAAADcAAOZYAADmWAAAADgAAOZZAADmWQAAAD0AAOZaAADmWgAAAF4AAOZbAADmWwAAAF8AAOZcAADmXAAAAGAAAOZdAADmXQAAAGEAAOZeAADmXgAAADYAAOZfAADmXwAAADsAAOZgAADmYAAAADwAAOZhAADmYQAAADkAAOZiAADmYgAAAD4AAOZjAADmYwAAAD8AAOZkAADmZAAAAEAAAOZlAADmZQAAAEEAAOZmAADmZgAAAEIAAOZnAADmZwAAAEMAAOZoAADmaAAAAEQAAOZpAADmaQAAAEUAAOZqAADmagAAAEYAAOZrAADmawAAAEcAAOZsAADmbAAAAEgAAOZtAADmbQAAAEkAAOZuAADmbgAAAEoAAOZvAADmbwAAAEsAAOZwAADmcAAAAEwAAOZxAADmcQAAAE0AAOZyAADmcgAAAE4AAOZzAADmcwAAAE8AAOZ0AADmdAAAAFAAAOZ1AADmdQAAAFEAAOZ2AADmdgAAAFIAAOZ3AADmdwAAAFMAAOZ4AADmeAAAAFQAAOZ5AADmeQAAAFUAAOZ6AADmegAAAFYAAOZ7AADmewAAAFcAAOZ8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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 (
-
- );
- }
-
- 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