1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360 |
- <template>
- <div class="props">
- <t-tabs v-model="data.tab">
- <t-tab-panel :value="1" label="外观">
- <t-space direction="vertical" class="py-16 w-full">
- <div class="form-item px-12">
- <label style="width: 50px">ID</label>
- <t-input
- class="w-full"
- placeholder="ID"
- :value="data.pen.id"
- @change="changeID($event)"
- />
- </div>
- <div class="form-item px-12" style="margin-top: -12px">
- <label style="width: 50px">名称</label>
- <t-input
- class="w-full"
- placeholder="名称"
- v-model.number="data.pen.name"
- @change="changeValue('name')"
- />
- </div>
- <div class="form-item px-12" style="margin-top: -12px">
- <label style="width: 50px">分组</label>
- <t-select-input
- v-model:inputValue="data.inputTag"
- :value="data.pen.tags"
- v-model:popupVisible="data.tagPopupVisible"
- allow-input
- placeholder="请输入或选择分组"
- multiple
- @tag-change="onChangeInputTag"
- @focus="data.tagPopupVisible = true"
- @blur="data.tagPopupVisible = false"
- :tag-input-props="{ excessTagsDisplayType: 'scroll' }"
- >
- <template #panel>
- <ul style="padding: 8px 12px">
- <li
- v-for="item in data.groups"
- :key="item"
- @click="onSelectTag(item)"
- >
- {{ item }}
- </li>
- </ul>
- </template>
- </t-select-input>
- </div>
- <t-divider style="margin: -8px 0" />
- <div class="form-item" style="margin-top: -12px">
- <t-input
- class="ml-4"
- label="X"
- placeholder="X"
- v-model.number="data.rect.x"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeRectValue('x')"
- />
- <t-icon name="link" class="hidden ml-4" />
- <t-input
- class="ml-4"
- label="Y"
- placeholder="Y"
- v-model.number="data.rect.y"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeRectValue('y')"
- />
- <t-input
- class="ml-16"
- v-model.number="data.pen.rotate"
- placeholder="旋转"
- style="width: 80px"
- :format="decimalRound"
- @change="changeValue('rotate')"
- >
- <template #prefix-icon>
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-rotate"></use>
- </svg>
- </template>
- </t-input>
- </div>
- <div class="form-item hover-icons" style="margin-top: -12px">
- <t-input
- class="ml-4"
- label="W"
- v-model.number="data.rect.width"
- placeholder="宽"
- min="1"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeRectValue('width')"
- />
- <t-tooltip v-if="data.pen.ratio" content="固定比例" placement="top">
- <t-icon
- name="link"
- class="ml-4 hover"
- @click="data.pen.ratio = !data.pen.ratio"
- />
- </t-tooltip>
- <t-tooltip v-else content="不固定比例" placement="top">
- <t-icon
- name="link-unlink"
- class="ml-4 hover icon"
- @click="data.pen.ratio = !data.pen.ratio"
- />
- </t-tooltip>
- <t-input
- class="ml-4"
- label="H"
- placeholder="高"
- v-model.number="data.rect.height"
- min="1"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeRectValue('height')"
- />
- <t-input
- class="ml-16"
- v-model.number="data.pen.borderRadius"
- placeholder="圆角"
- style="width: 80px"
- @change="changeValue('borderRadius')"
- >
- <template #prefix-icon>
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-border-radius"></use>
- </svg>
- </template>
- </t-input>
- </div>
- <t-divider style="margin: -8px 0" />
- <div class="form-item px-16" style="margin-top: -12px">
- <label>不透明度</label>
- <t-slider
- v-model="data.pen.globalAlpha"
- :min="0"
- :max="1"
- :step="0.01"
- @change="changeValue('globalAlpha')"
- />
- <span class="ml-16" style="width: 50px; line-height: 30px">
- {{ data.pen.globalAlpha }}
- </span>
- </div>
- <t-collapse
- :defaultValue="['1', '2', '3', '4', '5']"
- expandIconPlacement="right"
- :borderless="true"
- >
- <t-collapse-panel
- v-if="data.pen.props.look !== false"
- value="1"
- header="外观"
- >
- <t-space direction="vertical" size="small" class="w-full">
- <div class="form-item">
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- :clearable="true"
- v-model="data.pen.color"
- @change="changeValue('color')"
- />
- <label style="width: 64px">前景颜色</label>
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.hoverColor"
- @change="changeValue('hoverColor')"
- />
- <label style="width: 64px">悬停颜色</label>
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.activeColor"
- @change="changeValue('activeColor')"
- />
- <label style="width: 64px">选中颜色</label>
- </div>
- <div class="form-item">
- <label style="width: 32px">线条 </label>
- <t-select
- v-model="data.pen.dash"
- placeholder="线条样式"
- @change="changeValue('dash')"
- style="width: 80px"
- >
- <template #valueDisplay="{ value }">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- style="width: 100%; height: 20px"
- >
- <g fill="none" stroke="var(--color)" stroke-width="1">
- <path v-if="value === 0" d="M0 9 l85 0" />
- <path
- v-else-if="value === 1"
- stroke-dasharray="5 5"
- d="M0 9 l85 0"
- />
- <path
- v-else-if="value === 2"
- stroke-dasharray="10 10"
- d="M0 9 l85 0"
- />
- <path
- v-else-if="value === 3"
- stroke-dasharray="10 10 2 10"
- d="M0 9 l85 0"
- />
- </g>
- </svg>
- </template>
- <t-option :key="0" :value="0">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- style="width: 80px; height: 14px"
- >
- <g fill="none" stroke="var(--color)" stroke-width="1">
- <path d="M0 9 l85 0" />
- </g>
- </svg>
- </t-option>
- <t-option :key="1" :value="1">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- style="width: 80px; height: 14px"
- >
- <g fill="none" stroke="var(--color)" stroke-width="1">
- <path stroke-dasharray="5 5" d="M0 9 l85 0" />
- </g>
- </svg>
- </t-option>
- <t-option :key="2" :value="2">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- style="width: 80px; height: 14px"
- >
- <g fill="none" stroke="var(--color)" stroke-width="1">
- <path stroke-dasharray="10 10" d="M0 9 l85 0" />
- </g>
- </svg>
- </t-option>
- <t-option :key="3" :value="3">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- style="width: 80px; height: 14px"
- >
- <g fill="none" stroke="var(--color)" stroke-width="1">
- <path stroke-dasharray="10 10 2 10" d="M0 9 l85 0" />
- </g>
- </svg>
- </t-option>
- </t-select>
- <t-input-number
- theme="normal"
- placeholder="线条宽度"
- v-model="data.pen.lineWidth"
- :min="0"
- :decimalPlaces="0"
- @change="changeValue('lineWidth')"
- class="ml-4"
- style="width: 40px"
- />
- <t-tooltip content="线条渐变" placement="top">
- <div class="flex middle ml-8">
- <t-checkbox
- v-model="data.pen.strokeType"
- @change="changeValue('strokeType')"
- style="width: 22px"
- />
- <t-color-picker
- v-if="data.pen.strokeType"
- class="simple mr-4"
- format="CSS"
- :color-modes="['linear-gradient']"
- :show-primary-color-preview="false"
- :clearable="true"
- :enableAlpha="true"
- v-model="data.pen.lineGradientColors"
- @change="changeValue('lineGradientColors')"
- placeholder="无"
- />
- </div>
- </t-tooltip>
- </div>
- <div class="flex" style="margin-left: 40px">
- <div class="flex column middle">
- <t-radio-group
- size="small"
- v-model="data.pen.lineCap"
- default-value="butt"
- @change="changeValue('lineCap')"
- >
- <t-radio-button value="butt">
- <t-tooltip content="默认" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-duandian1"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="round">
- <t-tooltip content="圆形" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-duandian2"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="square">
- <t-tooltip content="方形" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-duandian3"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- </t-radio-group>
- <div class="mt-4" style="font-size: 12px">末端样式</div>
- </div>
- <div class="flex column middle ml-16">
- <t-radio-group
- size="small"
- v-model="data.pen.lineJoin"
- default-value="miter"
- @change="changeValue('lineJoin')"
- >
- <t-radio-button value="miter">
- <t-tooltip content="默认" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-jiedian1"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="round">
- <t-tooltip content="圆形" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-jiedian2"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="bevel">
- <t-tooltip content="斜角" placement="top">
- <svg class="l-icon" aria-hidden="true">
- <use xlink:href="#l-jiedian3"></use>
- </svg>
- </t-tooltip>
- </t-radio-button>
- </t-radio-group>
- <div class="mt-4" style="font-size: 12px">连接样式</div>
- </div>
- </div>
- <div class="form-item">
- <label style="width: 32px">背景</label>
- <div class="ml-8">
- <t-radio-group
- size="small"
- v-model="data.pen.bkType"
- :default-value="0"
- @change="changeValue('bkType')"
- >
- <t-radio-button :value="0"> 纯色 </t-radio-button>
- <t-radio-button :value="1"> 线性渐变 </t-radio-button>
- <t-radio-button :value="2"> 径向渐变 </t-radio-button>
- </t-radio-group>
- <div v-if="data.pen.bkType === 0" class="mt-8 -ml-8">
- <t-color-picker
- class="w-full"
- format="CSS"
- :color-modes="['monochrome']"
- :enable-alpha="true"
- :show-primary-color-preview="false"
- enable-alpha
- v-model="data.pen.background"
- @change="changeValue('background')"
- />
- </div>
- <div
- v-else-if="data.pen.bkType === 1"
- class="mt-8 -ml-8"
- style="width: 200px"
- >
- <t-color-picker
- class="w-full"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['linear-gradient']"
- :show-primary-color-preview="false"
- v-model="data.pen.gradientColors"
- @change="changeValue('gradientColors')"
- />
- </div>
- <div
- v-else-if="data.pen.bkType === 2"
- class="mt-8 flex middle"
- >
- <t-color-picker
- class="simple"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['linear-gradient']"
- :show-primary-color-preview="false"
- v-model="data.pen.gradientColors"
- @change="changeValue('gradientColors')"
- />
- <t-input-number
- theme="column"
- placeholder="渐变半径"
- v-model="data.pen.gradientRadius"
- :min="0"
- :max="1"
- :step="0.1"
- @change="changeValue('gradientRadius')"
- class="ml-8"
- style="width: 100px"
- />
- </div>
- </div>
- </div>
- <div class="form-item">
- <label style="width: 32px">阴影 </label>
- <div class="flex middle ml-8">
- <t-checkbox
- v-model="data.pen.shadow"
- @change="changeValue('shadow')"
- style="width: 22px"
- />
- <t-color-picker
- v-if="data.pen.shadow"
- class="simple"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.shadowColor"
- @change="changeValue('shadowColor')"
- />
- </div>
- </div>
- <div class="form-item" v-if="data.pen.shadow">
- <label style="width: 28px"></label>
- <div class="flex" style="margin-top: -8px">
- <t-input
- class="ml-4"
- label="X"
- placeholder="0"
- v-model.number="data.pen.shadowOffsetX"
- style="width: 60px"
- @change="changeValue('shadowOffsetX')"
- title="X偏移"
- />
- <t-input
- class="ml-4"
- label="Y"
- placeholder="0"
- v-model.number="data.pen.shadowOffsetY"
- style="width: 60px"
- @change="changeValue('shadowOffsetY')"
- title="Y偏移"
- />
- <t-input
- class="ml-4"
- label="模糊"
- placeholder="0"
- v-model.number="data.pen.shadowBlur"
- style="width: 64px"
- @change="changeValue('shadowBlur')"
- title="模糊大小"
- />
- </div>
- </div>
- </t-space>
- </t-collapse-panel>
- <t-collapse-panel
- v-if="data.pen.props.text"
- value="2"
- header="文字"
- >
- <t-space direction="vertical" size="small" class="w-full">
- <div class="form-item">
- <div class="flex middle" style="margin-left: -10px">
- <t-select-input
- :value="data.pen.fontFamily"
- :popup-visible="data.fontFamilyPopupVisible"
- placeholder="字体名"
- allow-input
- style="width: 170px"
- @change="changeValue('fontFamily')"
- @enter="changeValue('fontFamily')"
- @blur="changeValue('fontFamily')"
- @popup-visible-change="onFontPopupVisible"
- :popup-props="{
- overlayInnerStyle: { width: 'auto' },
- }"
- >
- <template #panel>
- <ul style="padding: 12px">
- <li
- v-for="item in fonts"
- :key="item"
- @click="onFontFamily(item)"
- >
- {{ item }}
- </li>
- </ul>
- </template>
- <template #suffixIcon>
- <t-icon name="chevron-down" />
- </template>
- </t-select-input>
- <t-input
- class="ml-8"
- placeholder="字体大小"
- v-model.number="data.pen.fontSize"
- style="width: 80px"
- :format="decimalRound"
- @change="changeValue('fontSize')"
- />
- </div>
- </div>
- <div class="flex middle">
- <t-radio-group
- size="small"
- v-model="data.pen.textAlign"
- default-value="center"
- @change="changeValue('textAlign')"
- >
- <t-radio-button value="left">
- <t-tooltip content="居左" placement="top">
- <t-icon name="format-vertical-align-left" />
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="center">
- <t-tooltip content="居中" placement="top">
- <t-icon name="format-vertical-align-center" />
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="right">
- <t-tooltip content="居右" placement="top">
- <t-icon name="format-vertical-align-right" />
- </t-tooltip>
- </t-radio-button>
- </t-radio-group>
- <t-radio-group
- class="ml-8"
- size="small"
- v-model="data.pen.textBaseline"
- default-value="top"
- @change="changeValue('textBaseline')"
- >
- <t-radio-button value="top">
- <t-tooltip content="顶部对齐" placement="top">
- <t-icon name="format-horizontal-align-top" />
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="middle">
- <t-tooltip content="垂直居中" placement="middle">
- <t-icon name="format-horizontal-align-center" />
- </t-tooltip>
- </t-radio-button>
- <t-radio-button value="bottom">
- <t-tooltip content="底部对齐" placement="top">
- <t-icon name="format-horizontal-align-bottom" />
- </t-tooltip>
- </t-radio-button>
- </t-radio-group>
- <t-button
- :class="{ active: data.pen.fontWeight === 'bold' }"
- class="ml-8 icon"
- shape="rectangle"
- variant="text"
- @click="
- data.pen.fontWeight === 'bold'
- ? (data.pen.fontWeight = 'normal')
- : (data.pen.fontWeight = 'bold');
- changeValue('fontWeight');
- "
- >
- B
- </t-button>
- <t-button
- :class="{ active: data.pen.fontStyle === 'italic' }"
- class="ml-4 icon"
- shape="rectangle"
- variant="text"
- @click="
- data.pen.fontStyle === 'italic'
- ? (data.pen.fontStyle = 'normal')
- : (data.pen.fontStyle = 'italic');
- changeValue('fontStyle');
- "
- style="font-style: italic; font-family: serif"
- >I</t-button
- >
- </div>
- <div class="form-item">
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- :clearable="true"
- v-model="data.pen.textColor"
- @change="changeValue('textColor')"
- />
- <label style="width: 44px">前景</label>
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.textBackground"
- @change="changeValue('textBackground')"
- />
- <label style="width: 44px">背景</label>
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.hoverTextColor"
- @change="changeValue('hoverTextColor')"
- />
- <label style="width: 44px">悬停</label>
- <t-color-picker
- class="simple mt-8 mr-4"
- format="CSS"
- :enable-alpha="true"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen.activeTextColor"
- @change="changeValue('activeTextColor')"
- />
- <label style="width: 44px">选中</label>
- </div>
- <div class="form-item">
- <t-checkbox
- v-model="data.pen.whiteSpace"
- @change="changeValue('whiteSpace')"
- style="width: 64px"
- >
- 换行
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.ellipsis"
- @change="changeValue('ellipsis')"
- style="width: 68px"
- >
- 省略号
- </t-checkbox>
- <t-tooltip content="行高">
- <t-input
- placeholder="行高"
- v-model.number="data.pen.lineHeight"
- style="width: 40px"
- @change="changeValue('lineHeight')"
- />
- </t-tooltip>
- <t-tooltip content="显示时保留小数位数">
- <t-input
- class="ml-4"
- placeholder="小数"
- v-model.number="data.pen.keepDecimal"
- style="width: 60px"
- @change="changeValue('keepDecimal')"
- />
- </t-tooltip>
- </div>
- <div class="form-item" style="margin-top: -4px">
- <t-tooltip content="水平偏移">
- <t-input
- placeholder="X"
- v-model.number="data.pen.textLeft"
- style="width: 60px; margin-left: -8px"
- @change="changeValue('textLeft')"
- />
- </t-tooltip>
- <t-tooltip content="垂直偏移">
- <t-input
- class="ml-4"
- placeholder="Y"
- v-model.number="data.pen.textTop"
- style="width: 60px"
- @change="changeValue('textTop')"
- />
- </t-tooltip>
- <t-tooltip content="宽">
- <t-input
- class="ml-4"
- placeholder="宽"
- v-model.number="data.pen.textWidth"
- style="width: 60px"
- @change="changeValue('textWidth')"
- />
- </t-tooltip>
- <t-tooltip content="高">
- <t-input
- class="ml-4"
- placeholder="高"
- v-model.number="data.pen.textHeight"
- style="width: 60px"
- @change="changeValue('textHeight')"
- />
- </t-tooltip>
- </div>
- <div class="flex middle">
- <t-checkbox
- v-model="data.pen.disableInput"
- @change="changeValue('disableInput')"
- style="width: 64px"
- >
- 只读
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.hiddenText"
- @change="changeValue('hiddenText')"
- style="width: 90px"
- >
- 隐藏文字
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.textAutoAdjust"
- @change="changeValue('textAutoAdjust')"
- style="width: 90px"
- >
- 自动调整
- </t-checkbox>
- </div>
- </t-space>
- </t-collapse-panel>
- <t-collapse-panel
- v-if="data.pen.props.image"
- value="3"
- header="图片"
- >
- <t-space direction="vertical" size="small" class="w-full">
- <div>
- <t-upload
- ref="uploadRef"
- v-model="data.images"
- action="/api/image/upload"
- theme="image"
- accept="image/*"
- :headers="headers"
- :data="updataData"
- :before-upload="beforeUpload"
- draggable
- @success="fileSuccessed"
- @remove="fileRemoved"
- >
- <template #fileListDisplay>
- <div style="z-index: 20">
- <a class="mr-4" @click="upload"> 点击上传 </a>
- / 拖拽图片到此区域
- </div>
- </template>
- </t-upload>
- </div>
- <div class="form-item hover-icons" style="margin-left: -12px">
- <t-input
- class="ml-4"
- label="W"
- v-model.number="data.pen.iconWidth"
- placeholder="自适应"
- min="1"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeValue('iconWidth')"
- />
- <t-tooltip
- v-if="data.pen.imageRatio"
- content="固定比例"
- placement="top"
- >
- <t-icon
- name="link"
- class="ml-4 hover"
- @click="data.pen.imageRatio = !data.pen.imageRatio"
- />
- </t-tooltip>
- <t-tooltip v-else content="不固定比例" placement="top">
- <t-icon
- name="link-unlink"
- class="ml-4 hover icon"
- @click="data.pen.imageRatio = !data.pen.imageRatio"
- />
- </t-tooltip>
- <t-input
- class="ml-4"
- label="H"
- placeholder="自适应"
- v-model.number="data.pen.iconHeight"
- min="1"
- style="width: 80px"
- :format="decimalPlaces"
- @change="changeValue('iconHeight')"
- />
- <t-checkbox
- class="ml-8"
- v-model="data.pen.isBottom"
- @change="changeValue('isBottom')"
- >
- 置底
- </t-checkbox>
- </div>
- <div class="flex">
- <label style="width: 30px; color: var(--color)">Url:</label>
- {{ data.pen.image }}
- </div>
- </t-space>
- </t-collapse-panel>
- <t-collapse-panel
- v-if="data.pen.props.icon"
- value="4"
- header="图标"
- >
- <t-space direction="vertical" size="small" class="w-full">
- <div class="form-item">
- <label style="width: 32px">图标 </label>
- <i
- class="ml-8"
- :class="data.pen.iconFamily"
- style="line-height: 30px; height: 30px; color: var(--color)"
- >
- {{ data.pen.icon }}
- </i>
- <a class="ml-12 mt-4" @click="iconsDrawer.show = true">
- 选择
- </a>
- <t-drawer
- v-model:visible="iconsDrawer.show"
- header="选择图标"
- :footer="null"
- >
- <Iconfonts :urls="data.iconUrls" @change="onChangeIcon" />
- </t-drawer>
- </div>
- </t-space>
- </t-collapse-panel>
- <t-collapse-panel
- v-if="data.pen.props.custom"
- value="5"
- header="属性"
- >
- <t-space direction="vertical" size="small" class="w-full">
- <div v-for="item in data.pen.props.custom" class="form-item">
- <label>{{ item.label }}</label>
- <t-checkbox
- class="ml-8"
- v-if="item.type === 'bool'"
- v-model="data.pen[item.key]"
- @change="changeValue(item.key)"
- />
- <t-input-number
- class="w-full"
- v-else-if="item.type === 'number'"
- v-model.number="data.pen[item.key]"
- theme="column"
- :max="item.max"
- :min="item.min"
- @change="changeValue(item.key)"
- :placeholder="item.placeholder"
- />
- <t-color-picker
- class="w-full"
- v-else-if="item.type === 'color'"
- :enable-alpha="true"
- format="CSS"
- :color-modes="['monochrome']"
- :show-primary-color-preview="false"
- v-model="data.pen[item.key]"
- @change="changeValue(item.key)"
- :placeholder="item.placeholder"
- />
- <t-select
- class="w-full"
- v-else-if="item.type === 'select'"
- size="small"
- :options="item.options"
- v-model="data.pen[item.key]"
- @change="changeValue(item.key)"
- :placeholder="item.placeholder"
- />
- <t-button
- v-else-if="item.type === 'code'"
- shape="square"
- variant="outline"
- style="width: 24px"
- @click="showPropsEdit(item)"
- >
- <t-icon name="ellipsis" slot="icon"
- /></t-button>
- <t-input
- class="w-full"
- v-else
- v-model="data.pen[item.key]"
- @change="changeValue(item.key)"
- :placeholder="item.placeholder"
- />
- </div>
- </t-space>
- </t-collapse-panel>
- </t-collapse>
- <t-divider style="margin: -8px 0" />
- <div class="form-item px-16" style="margin-top: -12px">
- <t-checkbox
- v-model="data.pen.flipX"
- @change="changeValue('flipX')"
- style="width: 90px"
- >
- 水平翻转
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.flipY"
- @change="changeValue('flipY')"
- style="width: 90px"
- >
- 垂直翻转
- </t-checkbox>
- <label style="width: 50px">锚点半径</label>
- <input
- class="ml-4"
- v-model.number="data.pen.anchorRadius"
- style="width: 20px"
- @change="changeValue('anchorRadius')"
- placeholder="4"
- />
- </div>
- <t-divider style="margin: -8px 0" />
- <div class="form-item px-16" style="margin-top: -12px">
- <t-checkbox
- v-model="data.pen.disableRotate"
- @change="changeValue('disableRotate')"
- style="width: 90px"
- >
- 禁止旋转
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.disableSize"
- @change="changeValue('disableSize')"
- style="width: 90px"
- >
- 禁止缩放
- </t-checkbox>
- <t-checkbox
- v-model="data.pen.disableAnchor"
- @change="changeValue('disableAnchor')"
- style="width: 90px"
- >
- 禁用锚点
- </t-checkbox>
- </div>
- <t-divider style="margin: -8px 0" />
- <div class="form-item px-16" style="margin-top: -12px">
- <label style="width: 60px">鼠标提示</label>
- <t-button
- shape="square"
- variant="outline"
- style="width: 24px"
- @click="showTooltip"
- >
- <t-icon name="ellipsis" slot="icon"
- /></t-button>
- </div>
- <t-dialog
- v-if="tooltipDialog.show"
- :visible="true"
- header="鼠标提示"
- @confirm="onOkTooltip"
- @close="tooltipDialog.show = false"
- :width="700"
- >
- <t-radio-group v-model="tooltipDialog.type">
- <t-radio value="1">文字</t-radio>
- <t-radio value="2">函数</t-radio>
- </t-radio-group>
- <div class="py-8">
- <CodeEditor
- v-show="tooltipDialog.type == 1"
- v-model="tooltipDialog.title"
- style="height: 300px"
- />
- <div v-show="tooltipDialog.type == 2">
- <div>function tooltip(pen) {</div>
- <CodeEditor
- v-model="tooltipDialog.titleFnJs"
- class="mt-4"
- style="height: 248px"
- />
- <div class="mt-4">}</div>
- </div>
- </div>
- <div class="gray" style="font-size: 12px">支持Markdown格式</div>
- </t-dialog>
- <t-dialog
- v-if="propsDialog.show"
- :visible="true"
- :header="propsDialog.header"
- @confirm="onOkPropsEdit"
- @close="propsDialog.show = false"
- :width="700"
- >
- <div class="py-8">
- <CodeEditor
- :json="true"
- :language="'json'"
- v-model="propsDialog.value"
- style="height: 300px"
- />
- </div>
- <div class="gray" style="font-size: 12px">
- {{ propsDialog.placeholder }}
- </div>
- </t-dialog>
- <t-space />
- </t-space>
- </t-tab-panel>
- <t-tab-panel :value="2" label="动画">
- <PenAnimates :pen="data.pen" />
- </t-tab-panel>
- <t-tab-panel :value="3" label="数据">
- <PenDatas :pen="data.pen" />
- </t-tab-panel>
- <t-tab-panel :value="4" label="交互">
- <PenEvents :pen="data.pen" />
- </t-tab-panel>
- <t-tab-panel :value="5" label="结构">
- <ElementTree />
- </t-tab-panel>
- </t-tabs>
- </div>
- </template>
- <script lang="ts" setup>
- import { onBeforeMount, onUnmounted, reactive, ref, watch } from 'vue';
- import CodeEditor from './common/CodeEditor.vue';
- import Iconfonts from './common/Iconfonts.vue';
- import PenAnimates from './PenAnimates.vue';
- import PenDatas from './PenDatas.vue';
- import PenEvents from './PenEvents.vue';
- import ElementTree from './ElementTree.vue';
- import { getCookie } from '@/services/cookie';
- import { useSelection } from '@/services/selections';
- import { autoSave, fonts, inTreePanel } from '@/services/common';
- import { updatePen } from './pen';
- import { MessagePlugin } from 'tdesign-vue-next';
- import { useUser } from '@/services/user';
- const { user } = useUser();
- const headers = {
- Authorization: 'Bearer ' + (localStorage.token || getCookie('token') || ''),
- };
- const updataData = { directory: '/项目' };
- const uploadRef = ref();
- const data = reactive<any>({
- tab: 1,
- pen: {},
- rect: {},
- });
- const { selections } = useSelection();
- const tooltipDialog = reactive<any>({
- show: false,
- });
- const propsDialog = reactive<any>({
- show: false,
- });
- const iconsDrawer = reactive<any>({
- show: false,
- });
- onBeforeMount(() => {
- if (inTreePanel.value) {
- data.tab = 5;
- }
- const d = meta2d.store.data as any;
- if (!d.groups) {
- d.groups = [];
- }
- if (!d.iconUrls) {
- d.iconUrls = [];
- }
- data.iconUrls = d.iconUrls;
- data.groups = d.groups;
- initPenData();
- meta2d.on('translatePens', getRect);
- meta2d.on('resizePens', getRect);
- meta2d.on('rotatePens', getRect);
- });
- function initPenData() {
- data.pen = selections.pen;
- if (!data.pen.props) {
- data.pen.props = {};
- }
- if (!data.pen.globalAlpha) {
- data.pen.globalAlpha = 1;
- }
- if (!data.pen.dash) {
- data.pen.dash = 0;
- }
- if (!data.pen.props.text) {
- if (data.pen.text || data.pen.name === 'text') {
- data.pen.props.text = true;
- }
- }
- if (!data.pen.props.image) {
- if (data.pen.image) {
- data.pen.props.image = true;
- }
- }
- if (!data.pen.props.icon) {
- if (data.pen.icon) {
- data.pen.props.icon = true;
- }
- }
- if (data.pen.image) {
- data.images = [
- {
- url: data.pen.image,
- },
- ];
- }
- if (!data.pen.tags) {
- data.pen.tags = [];
- }
- if (data.pen.bkType == undefined) {
- data.pen.bkType = 0;
- }
- if (!data.pen.animations) {
- data.pen.animations = [];
- }
- data.pen.shadow = !!data.pen.shadowColor;
- getRect();
- }
- const watcher = watch(() => selections.pen.id, initPenData);
- const getRect = () => {
- data.rect = meta2d.getPenRect(data.pen);
- };
- const decimalPlaces = (val: number) => {
- if (!val) {
- return 0;
- }
- return Math.round(+val * 100) / 100;
- };
- const decimalRound = (val: number) => {
- return Math.round(+val || 0);
- };
- const changeValue = (prop: string) => {
- updatePen(data.pen, prop);
- };
- const changeID = (value: any) => {
- if (!value) {
- initPenData();
- MessagePlugin.error('id 不能为空');
- return;
- }
- const oldID: string = data.pen.id;
- try {
- meta2d.changePenId(oldID, value);
- initPenData();
- } catch (error) {
- console.warn(error.message);
- MessagePlugin.error('id 修改失败,请检查 id 是否重复');
- return;
- }
- };
- const changeRectValue = (prop: string) => {
- data.rect.id = data.pen.id;
- data.rect.ratio = data.pen.ratio;
- updatePen(data.rect, prop);
- };
- const onFontPopupVisible = (val: boolean) => {
- data.fontFamilyPopupVisible = val;
- };
- const onFontFamily = (fontFamily: string) => {
- data.pen.fontFamily = fontFamily;
- data.fontFamilyPopupVisible = false;
- changeValue('fontFamily');
- };
- const beforeUpload = (file: any) => {
- // if (file.size > 5 * 1024 * 1024) {
- // MessagePlugin.warning('上传的图片不能大于5M');
- // return false;
- // }
- if (!(user && user.id)) {
- MessagePlugin.warning('请先登录!');
- return false;
- }
- return true;
- };
- const fileSuccessed = async (content: any) => {
- // meta2d.store.patchFlagsBackground = true;
- // meta2d.setBackgroundImage(content.response.url);
- // meta2d.store.patchFlagsBackground = true;
- data.pen.image = content.response.url;
- updatePen(data.pen, 'image');
- meta2d.render();
- };
- const fileRemoved = () => {
- // meta2d.setBackgroundImage('');
- // meta2d.store.patchFlagsBackground = true;
- data.pen.image = '';
- updatePen(data.pen, 'image');
- meta2d.render();
- // data.background = [];
- };
- const upload = () => {
- uploadRef.value.triggerUpload();
- };
- const onSelectTag = (tag: string) => {
- data.tagPopupVisible = false;
- if (data.pen.tags.includes(tag)) {
- return;
- }
- data.pen.tags.push(tag);
- changeValue('tags');
- };
- const onChangeInputTag = (currentTags: any, context: any) => {
- const { trigger, index, item } = context;
- if (['tag-remove', 'backspace'].includes(trigger)) {
- data.pen.tags.splice(index, 1);
- }
- if (trigger === 'enter') {
- onSelectTag(item);
- const d = meta2d.store.data as any;
- if (!d.groups.includes(item)) {
- d.groups.push(item);
- data.groups = d.groups;
- }
- data.inputTag = '';
- }
- data.tagPopupVisible = false;
- };
- const showTooltip = () => {
- tooltipDialog.title = data.pen.title || '';
- tooltipDialog.titleFnJs =
- data.pen.titleFnJs || '// 例如:return `${pen.name}<br/>${pen.text}`;';
- tooltipDialog.type = data.pen.titleFnJs ? '2' : '1';
- tooltipDialog.show = true;
- };
- const onOkTooltip = () => {
- if (tooltipDialog.type === '1') {
- data.pen.title = tooltipDialog.title;
- data.pen.titleFnJs = '';
- } else {
- data.pen.title = '';
- data.pen.titleFnJs = tooltipDialog.titleFnJs;
- }
- tooltipDialog.show = false;
- };
- const showPropsEdit = (item: any) => {
- propsDialog.key = item.key;
- propsDialog.header = `${item.label}(${item.key})`;
- propsDialog.value = data.pen[item.key];
- propsDialog.placeholder = item.placeholder;
- propsDialog.show = true;
- };
- const onOkPropsEdit = () => {
- if (!propsDialog.value) {
- MessagePlugin.error('数据不满足json格式');
- return;
- }
- data.pen[propsDialog.key] = propsDialog.value;
- updatePen(data.pen, propsDialog.key);
- propsDialog.show = false;
- };
- const onChangeIcon = (params: any) => {
- Object.assign(data.pen, params);
- meta2d.setValue({
- id: data.pen.id,
- icon: params.icon,
- iconFamily: params.iconFamily,
- });
- autoSave(true);
- };
- onUnmounted(() => {
- watcher();
- meta2d.off('translatePens', getRect);
- meta2d.off('resizePens', getRect);
- meta2d.off('rotatePens', getRect);
- });
- </script>
- <style lang="postcss" scoped>
- .props {
- }
- </style>
|