PenProps.vue 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. <template>
  2. <div class="props">
  3. <t-tabs v-model="data.tab">
  4. <t-tab-panel :value="1" :label="$t('外观')">
  5. <t-space direction="vertical" class="py-16 w-full">
  6. <div class="form-item px-12">
  7. <label style="width: 50px">ID</label>
  8. <t-input
  9. class="w-full"
  10. placeholder="ID"
  11. :value="data.pen.id"
  12. @change="changeID($event)"
  13. />
  14. </div>
  15. <div class="form-item px-12" style="margin-top: -12px">
  16. <label style="width: 50px">{{$t('名称')}}</label>
  17. <!-- <t-input
  18. class="w-full"
  19. placeholder="名称"
  20. disabled
  21. v-model.number="data.pen.name"
  22. @change="changeValue('name')"
  23. /> -->
  24. <div style="padding-left: 8px; line-height: 30px">
  25. {{ data.pen.name }}
  26. </div>
  27. </div>
  28. <div class="form-item px-12" style="margin-top: -12px">
  29. <label style="width: 50px">{{$t('分组')}}</label>
  30. <t-select-input v-model:inputValue="data.inputTag" :value="data.pen.tags" allow-input multiple @tag-change="onChangeInputTag" @focus="data.tagPopupVisible = true" @blur="data.tagPopupVisible = false" :tag-input-props="{ excessTagsDisplayType: 'break-line' }" :placeholder="$t('请输入或选择分组')">
  31. <template #panel>
  32. <ul style="padding: 8px 12px">
  33. <li
  34. v-for="item in data.groups"
  35. :key="item"
  36. @click="onSelectTag(item)"
  37. >
  38. {{ item }}
  39. </li>
  40. </ul>
  41. </template>
  42. </t-select-input>
  43. </div>
  44. <div v-if="isDom" class="form-item px-12" style="margin-top: -12px">
  45. <label style="width: 50px">z-index</label>
  46. <t-input-number
  47. v-model="data.pen.zIndex"
  48. theme="column"
  49. :min="0"
  50. :placeholder="$t('默认5')"
  51. @change="changeValue('zIndex')"
  52. />
  53. </div>
  54. <div v-else class="form-item px-12" style="margin-top: -12px">
  55. <label style="width: 50px">{{$t('画布层')}}</label>
  56. <!-- <t-switch
  57. class="mt-8 ml-8"
  58. v-model="data.pen.template"
  59. size="small"
  60. @change="changeValue('template')"
  61. /> -->
  62. <t-select v-model="data.pen.canvasLayer" @change="changeValue('canvasLayer')">
  63. <t-option :key="4" :disabled="data.pen.name!=='image'" :value="4" :label="$t('上层图片层')"> {{$t('上层图片层')}} </t-option>
  64. <t-option :key="3" :value="3" :label="$t('主画布层')"> {{$t('主画布层')}} </t-option>
  65. <t-option :key="2" :disabled="data.pen.name!=='image'" :value="2" :label="$t('下层图片层')"> {{$t('下层图片层')}} </t-option>
  66. <t-option :key="1" :value="1" :label="$t('模板层')"> {{$t('模板层')}} </t-option>
  67. </t-select>
  68. </div>
  69. <t-divider style="margin: -8px 0"></t-divider>
  70. <div style="margin: 0 16px 16px 16px">
  71. <t-space direction="vertical" size="small" class="w-full">
  72. <div style="color: var(--color); margin-bottom: 2px">
  73. {{$t('大屏对齐')}}
  74. </div>
  75. <div class="icons">
  76. <t-tooltip
  77. v-for="item in aligns"
  78. :content="item.label"
  79. placement="top"
  80. >
  81. <svg
  82. class="l-icon btn"
  83. aria-hidden="true"
  84. @click="align(item.value)"
  85. >
  86. <use :xlink:href="item.icon"></use>
  87. </svg>
  88. </t-tooltip>
  89. </div>
  90. </t-space>
  91. </div>
  92. <t-divider style="margin: -8px 0" />
  93. <div class="form-item" style="margin-top: -12px">
  94. <t-input
  95. class="ml-4"
  96. label="X"
  97. placeholder="X"
  98. v-model.number="data.rect.x"
  99. style="width: 80px"
  100. :format="decimalPlaces"
  101. @change="changeRectValue('x')"
  102. />
  103. <link-icon class="hidden ml-4"/>
  104. <!-- <t-icon name="link" class="hidden ml-4" /> -->
  105. <t-input
  106. class="ml-4"
  107. label="Y"
  108. placeholder="Y"
  109. v-model.number="data.rect.y"
  110. style="width: 80px"
  111. :format="decimalPlaces"
  112. @change="changeRectValue('y')"
  113. />
  114. <t-input
  115. class="ml-16"
  116. v-model.number="data.pen.rotate"
  117. :placeholder="$t('旋转')"
  118. style="width: 80px"
  119. :format="decimalRound"
  120. @change="changeValue('rotate')"
  121. >
  122. <template #prefix-icon>
  123. <svg class="l-icon" aria-hidden="true">
  124. <use xlink:href="#l-rotate"></use>
  125. </svg>
  126. </template>
  127. </t-input>
  128. </div>
  129. <div class="form-item hover-icons" style="margin-top: -12px">
  130. <t-input class="ml-4" label="W" v-model.number="data.rect.width" min="1" style="width: 80px" :format="decimalPlaces" @change="changeRectValue('width')" :placeholder="$t('宽')"></t-input>
  131. <t-tooltip v-if="data.pen.ratio" placement="top" :content="$t('固定比例')">
  132. <link-icon class="ml-4 hover" @click="data.pen.ratio = !data.pen.ratio"></link-icon>
  133. <!-- <t-icon
  134. name="link"
  135. class="ml-4 hover"
  136. @click="data.pen.ratio = !data.pen.ratio"
  137. /> -->
  138. </t-tooltip>
  139. <t-tooltip v-else placement="top" :content="$t('不固定比例')">
  140. <link-unlink-icon class="ml-4 hover icon" @click="data.pen.ratio = !data.pen.ratio"></link-unlink-icon>
  141. <!-- <t-icon
  142. name="link-unlink"
  143. class="ml-4 hover icon"
  144. @click="data.pen.ratio = !data.pen.ratio"
  145. /> -->
  146. </t-tooltip>
  147. <t-input class="ml-4" label="H" v-model.number="data.rect.height" min="1" style="width: 80px" :format="decimalPlaces" @change="changeRectValue('height')" :placeholder="$t('高')"></t-input>
  148. <t-input class="ml-16" v-model.number="data.pen.borderRadius" style="width: 80px" @change="changeValue('borderRadius')" :placeholder="$t('圆角')">
  149. <template #prefix-icon>
  150. <svg class="l-icon" aria-hidden="true">
  151. <use xlink:href="#l-border-radius"></use>
  152. </svg>
  153. </template>
  154. </t-input>
  155. </div>
  156. <t-divider style="margin: -8px 0" />
  157. <div class="form-item px-16" style="margin-top: -12px">
  158. <label>{{$t('透明度')}}</label>
  159. <t-slider v-model="data.pen.globalAlpha" :min="0" :max="1" :step="0.01" @change="changeValue('globalAlpha')"></t-slider>
  160. <span class="ml-16" style="width: 50px; line-height: 30px">
  161. {{ data.pen.globalAlpha }}
  162. </span>
  163. </div>
  164. <template
  165. v-if="
  166. data.pen.name === 'combine' && data.pen.showChild !== undefined
  167. "
  168. >
  169. <t-divider style="margin: -8px 0" />
  170. <div>
  171. <div class="form-item px-16" style="margin-top: -12px">
  172. <label>{{$t('状态')}}</label>
  173. <t-select v-model="data.pen.showChild" @change="changeValue('showChild')" style="width: 150px" :placeholder="$t('状态')">
  174. <t-option v-for="(a, index) in data.pen.children" :key="index" :value="index">
  175. {{$t(' 状态')}}{{ index + 1 }}</t-option>
  176. </t-select>
  177. </div>
  178. <div v-if="data.childPen.image" class="px-16 py-8">
  179. <t-upload
  180. ref="childUploadRef"
  181. v-model="data.childImages"
  182. action="/api/image/upload"
  183. theme="image"
  184. accept="image/*"
  185. :headers="headers"
  186. :data="updataData"
  187. :before-upload="beforeUpload"
  188. draggable
  189. @success="fileChildSuccessed"
  190. >
  191. <template #fileListDisplay>
  192. <div style="z-index: 20">
  193. <a class="mr-4" @click="childUpload"> {{$t('点击上传')}} </a>
  194. / {{$t('拖拽图片到此区域')}}
  195. </div>
  196. </template>
  197. </t-upload>
  198. </div>
  199. <div v-if="data.childPen.image" class="form-item px-16">
  200. <label style="width: 30px; color: var(--color)">Url:</label>
  201. <t-input class="w-full" v-model.number="data.childPen.image" @change="changeChildValue('image')" :placeholder="$t('图片地址')"></t-input>
  202. </div>
  203. </div>
  204. </template>
  205. <t-collapse :defaultValue="['1', '2', '3', '4', '5']" expandIconPlacement="right" :borderless="true">
  206. <t-collapse-panel v-if="data.pen.props.custom" value="5" :header="$t('属性')">
  207. <Custom :pen="data.pen"></Custom>
  208. </t-collapse-panel>
  209. <t-collapse-panel v-if="data.pen.props.look !== false" value="1" :header="$t('外观')">
  210. <t-space direction="vertical" size="small" class="w-full">
  211. <div class="form-item">
  212. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" :clearable="true" v-model="data.pen.color" @change="changeValue('color')"></t-color-picker>
  213. <label style="width: 64px">{{$t('前景颜色')}}</label>
  214. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.hoverColor" @change="changeValue('hoverColor')"></t-color-picker>
  215. <label style="width: 64px">{{$t('悬停颜色')}}</label>
  216. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.activeColor" @change="changeValue('activeColor')"></t-color-picker>
  217. <label style="width: 64px">{{$t('选中颜色')}}</label>
  218. </div>
  219. <div class="form-item">
  220. <label style="width: 32px">{{$t('线条')}} </label>
  221. <t-select v-model="data.pen.dash" @change="changeValue('dash')" style="width: 80px" :placeholder="$t('线条样式')">
  222. <template #valueDisplay="{ value }">
  223. <div v-if="value === -1">{{$t( '无' )}}</div>
  224. <svg
  225. v-else
  226. xmlns="http://www.w3.org/2000/svg"
  227. version="1.1"
  228. style="width: 100%; height: 20px"
  229. >
  230. <g fill="none" stroke="var(--color)" stroke-width="1">
  231. <path v-if="value === 0" d="M0 9 l85 0" />
  232. <path
  233. v-else-if="value === 1"
  234. stroke-dasharray="5 5"
  235. d="M0 9 l85 0"
  236. />
  237. <path
  238. v-else-if="value === 2"
  239. stroke-dasharray="10 10"
  240. d="M0 9 l85 0"
  241. />
  242. <path
  243. v-else-if="value === 3"
  244. stroke-dasharray="10 10 2 10"
  245. d="M0 9 l85 0"
  246. />
  247. </g>
  248. </svg>
  249. </template>
  250. <t-option :key="-1" :value="-1">
  251. <div class="flex" style=" align-items:center;">
  252. <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
  253. <path d="M113.777778 0h796.444444a113.777778 113.777778 0 0 1 113.777778 113.777778v796.444444a113.777778 113.777778 0 0 1-113.777778 113.777778H113.777778a113.777778 113.777778 0 0 1-113.777778-113.777778V113.777778a113.777778 113.777778 0 0 1 113.777778-113.777778z m0 85.333333a28.444444 28.444444 0 0 0-28.444445 28.444445v796.444444a28.444444 28.444444 0 0 0 28.444445 28.444445h796.444444a28.444444 28.444444 0 0 0 28.444445-28.444445V113.777778a28.444444 28.444444 0 0 0-28.444445-28.444445H113.777778z" fill="#e3e8f4" p-id="37532"></path>
  254. <path d="M897.706667 75.662222L105.813333 894.748444a42.666667 42.666667 0 0 0 61.326223 59.278223l791.893333-819.143111a42.666667 42.666667 0 1 0-61.383111-59.335112z" fill="#ff4000" p-id="37533"></path>
  255. </svg>
  256. <p style="margin-left:8px;">{{$t('无')}}</p>
  257. </div>
  258. </t-option>
  259. <t-option :key="0" :value="0">
  260. <svg
  261. xmlns="http://www.w3.org/2000/svg"
  262. version="1.1"
  263. style="width: 80px; height: 14px"
  264. >
  265. <g fill="none" stroke="var(--color)" stroke-width="1">
  266. <path d="M0 9 l85 0" />
  267. </g>
  268. </svg>
  269. </t-option>
  270. <t-option :key="1" :value="1">
  271. <svg
  272. xmlns="http://www.w3.org/2000/svg"
  273. version="1.1"
  274. style="width: 80px; height: 14px"
  275. >
  276. <g fill="none" stroke="var(--color)" stroke-width="1">
  277. <path stroke-dasharray="5 5" d="M0 9 l85 0" />
  278. </g>
  279. </svg>
  280. </t-option>
  281. <t-option :key="2" :value="2">
  282. <svg
  283. xmlns="http://www.w3.org/2000/svg"
  284. version="1.1"
  285. style="width: 80px; height: 14px"
  286. >
  287. <g fill="none" stroke="var(--color)" stroke-width="1">
  288. <path stroke-dasharray="10 10" d="M0 9 l85 0" />
  289. </g>
  290. </svg>
  291. </t-option>
  292. <t-option :key="3" :value="3">
  293. <svg
  294. xmlns="http://www.w3.org/2000/svg"
  295. version="1.1"
  296. style="width: 80px; height: 14px"
  297. >
  298. <g fill="none" stroke="var(--color)" stroke-width="1">
  299. <path stroke-dasharray="10 10 2 10" d="M0 9 l85 0" />
  300. </g>
  301. </svg>
  302. </t-option>
  303. </t-select>
  304. <t-input-number
  305. theme="normal"
  306. :placeholder="$t('线条宽度')"
  307. v-model="data.pen.lineWidth"
  308. :min="0"
  309. :decimalPlaces="0"
  310. @change="changeValue('lineWidth')"
  311. class="ml-4"
  312. style="width: 40px"
  313. />
  314. <t-tooltip
  315. v-if="['polyline','line'].includes(data.pen.lineName)"
  316. :content="$t('平滑度')"
  317. placement="top"
  318. >
  319. <t-input-number
  320. theme="normal"
  321. placeholder="1-3"
  322. v-model="data.pen.lineSmooth"
  323. :min="0"
  324. :decimalPlaces="0"
  325. @change="changeValue('lineSmooth')"
  326. class="ml-4"
  327. style="width: 44px"
  328. />
  329. </t-tooltip>
  330. <t-tooltip placement="top" :content="$t('线条渐变')">
  331. <div class="flex middle ml-8">
  332. <t-checkbox
  333. v-model="data.pen.strokeType"
  334. @change="changeValue('strokeType')"
  335. style="width: 22px"
  336. />
  337. <t-color-picker
  338. v-if="data.pen.strokeType"
  339. class="simple mr-4"
  340. format="CSS"
  341. :swatch-colors="defaultGradientColor"
  342. :color-modes="['linear-gradient']"
  343. :show-primary-color-preview="false"
  344. :recent-colors="null"
  345. :enableAlpha="true"
  346. v-model="data.pen.lineGradientColors"
  347. @change="changeValue('lineGradientColors')"
  348. :placeholder="$t('无')"
  349. />
  350. </div>
  351. </t-tooltip>
  352. </div>
  353. <div v-if="data.pen.type" class="form-item">
  354. <label style="width: 52px">{{$t('边框宽度')}} </label>
  355. <t-input-number
  356. theme="normal"
  357. placeholder="边框宽度"
  358. v-model="data.pen.borderWidth"
  359. :min="0"
  360. :decimalPlaces="0"
  361. @change="changeValue('borderWidth')"
  362. style="width: 73px"
  363. />
  364. <label style="width: 52px;" class="ml-8">{{$t('边框颜色')}} </label>
  365. <t-color-picker
  366. class="simple mt-8 ml-8"
  367. format="CSS"
  368. :enable-alpha="true"
  369. :recent-colors="null"
  370. :swatch-colors="defaultPureColor"
  371. :color-modes="['monochrome']"
  372. :show-primary-color-preview="false"
  373. :clearable="true"
  374. v-model="data.pen.borderColor"
  375. @change="changeValue('borderColor')"
  376. />
  377. </div>
  378. <div class="form-item">
  379. <label style="width: 52px">{{$t('起点箭头')}} </label>
  380. <t-select
  381. v-model="data.pen.fromArrow"
  382. :placeholder="$t('线条样式')"
  383. @change="changeValue('fromArrow')"
  384. style="width: 80px"
  385. >
  386. <template #valueDisplay="{ value }">
  387. <svg v-if="value" class="l-icon" aria-hidden="true">
  388. <use :xlink:href="fromArrows.find(item=>item.value===value).icon"></use>
  389. </svg>
  390. </template>
  391. <t-option v-for="item in fromArrows" :key="item.value" :value="item.value">
  392. <svg class="l-icon" aria-hidden="true">
  393. <use :xlink:href="item.icon"></use>
  394. </svg>
  395. </t-option>
  396. </t-select>
  397. <label style="width: 52px" class="ml-4">{{$t('终点箭头')}} </label>
  398. <t-select v-model="data.pen.toArrow" @change="changeValue('toArrow')" style="width: 80px" :placeholder="$t('线条样式')">
  399. <template #valueDisplay="{ value }">
  400. <svg v-if="value" class="l-icon" aria-hidden="true">
  401. <use :xlink:href="toArrows.find(item=>item.value===value).icon"></use>
  402. </svg>
  403. </template>
  404. <t-option v-for="item in toArrows" :key="item.value" :value="item.value">
  405. <svg class="l-icon" aria-hidden="true">
  406. <use :xlink:href="item.icon"></use>
  407. </svg>
  408. </t-option>
  409. </t-select>
  410. </div>
  411. <div class="flex" style="margin-left: 40px">
  412. <div class="flex column middle">
  413. <t-radio-group
  414. size="small"
  415. v-model="data.pen.lineCap"
  416. default-value="butt"
  417. @change="changeValue('lineCap')"
  418. >
  419. <t-radio-button value="butt">
  420. <t-tooltip placement="top" :content="$t('默认')">
  421. <svg class="l-icon" aria-hidden="true">
  422. <use xlink:href="#l-duandian1"></use>
  423. </svg>
  424. </t-tooltip>
  425. </t-radio-button>
  426. <t-radio-button value="round">
  427. <t-tooltip placement="top" :content="$t('圆形')">
  428. <svg class="l-icon" aria-hidden="true">
  429. <use xlink:href="#l-duandian2"></use>
  430. </svg>
  431. </t-tooltip>
  432. </t-radio-button>
  433. <t-radio-button value="square">
  434. <t-tooltip placement="top" :content="$t('方形')">
  435. <svg class="l-icon" aria-hidden="true">
  436. <use xlink:href="#l-duandian3"></use>
  437. </svg>
  438. </t-tooltip>
  439. </t-radio-button>
  440. </t-radio-group>
  441. <div class="mt-4" style="font-size: 12px">{{$t('末端样式')}}</div>
  442. </div>
  443. <div class="flex column middle ml-16">
  444. <t-radio-group
  445. size="small"
  446. v-model="data.pen.lineJoin"
  447. default-value="miter"
  448. @change="changeValue('lineJoin')"
  449. >
  450. <t-radio-button value="miter">
  451. <t-tooltip placement="top" :content="$t('默认')">
  452. <svg class="l-icon" aria-hidden="true">
  453. <use xlink:href="#l-jiedian1"></use>
  454. </svg>
  455. </t-tooltip>
  456. </t-radio-button>
  457. <t-radio-button value="round">
  458. <t-tooltip placement="top" :content="$t('圆形')">
  459. <svg class="l-icon" aria-hidden="true">
  460. <use xlink:href="#l-jiedian2"></use>
  461. </svg>
  462. </t-tooltip>
  463. </t-radio-button>
  464. <t-radio-button value="bevel">
  465. <t-tooltip placement="top" :content="$t('斜角')">
  466. <svg class="l-icon" aria-hidden="true">
  467. <use xlink:href="#l-jiedian3"></use>
  468. </svg>
  469. </t-tooltip>
  470. </t-radio-button>
  471. </t-radio-group>
  472. <div class="mt-4" style="font-size: 12px">{{$t('连接样式')}}</div>
  473. </div>
  474. </div>
  475. <div class="form-item" v-if="!data.pen.type">
  476. <label style="width: 32px">{{$t('背景')}}</label>
  477. <div class="ml-8">
  478. <t-radio-group size="small" v-model="data.pen.bkType" :default-value="0" @change="changeValue('bkType')">
  479. <t-radio-button :value="0"> {{$t('纯色')}} </t-radio-button>
  480. <t-radio-button :value="1"> {{$t('线性渐变')}} </t-radio-button>
  481. <t-radio-button :value="2"> {{$t('径向渐变')}} </t-radio-button>
  482. </t-radio-group>
  483. <div v-if="data.pen.bkType === 0" class="mt-8 -ml-8">
  484. <t-color-picker
  485. class="w-full"
  486. format="CSS"
  487. :swatch-colors="defaultPureColor"
  488. :color-modes="['monochrome']"
  489. :recent-colors="null"
  490. :enable-alpha="true"
  491. :show-primary-color-preview="false"
  492. v-model="data.pen.background"
  493. @change="changeValue('background')"
  494. />
  495. </div>
  496. <div
  497. v-else-if="data.pen.bkType === 1"
  498. class="mt-8 -ml-8"
  499. style="width: 200px"
  500. >
  501. <t-color-picker
  502. class="w-full"
  503. format="CSS"
  504. :enable-alpha="true"
  505. :recent-colors="null"
  506. :swatch-colors="defaultGradientColor"
  507. :color-modes="['linear-gradient']"
  508. :show-primary-color-preview="false"
  509. v-model="data.pen.gradientColors"
  510. @change="changeValue('gradientColors')"
  511. />
  512. </div>
  513. <div
  514. v-else-if="data.pen.bkType === 2"
  515. class="mt-8 flex middle"
  516. >
  517. <t-color-picker
  518. class="simple"
  519. format="CSS"
  520. :enable-alpha="true"
  521. :recent-colors="null"
  522. :swatch-colors="defaultGradientColor"
  523. :color-modes="['linear-gradient']"
  524. :show-primary-color-preview="false"
  525. v-model="data.pen.gradientColors"
  526. @change="changeValue('gradientColors')"
  527. />
  528. <t-input-number
  529. theme="column"
  530. :placeholder="$t('渐变半径')"
  531. v-model="data.pen.gradientRadius"
  532. :min="0"
  533. :max="1"
  534. :step="0.1"
  535. @change="changeValue('gradientRadius')"
  536. class="ml-8"
  537. style="width: 100px"
  538. />
  539. </div>
  540. </div>
  541. </div>
  542. <div v-if="data.pen.switch" class="form-item">
  543. <label style="width: 32px">{{$t('选中')}} </label>
  544. <div v-if="data.pen.bkType === 0">
  545. <t-color-picker
  546. class="w-full"
  547. format="CSS"
  548. :swatch-colors="defaultPureColor"
  549. :color-modes="['monochrome']"
  550. :recent-colors="null"
  551. :enable-alpha="true"
  552. :show-primary-color-preview="false"
  553. v-model="data.pen.onBackground"
  554. @change="changeValue('onBackground')"
  555. />
  556. </div>
  557. <div
  558. v-else-if="data.pen.bkType === 1"
  559. style="width: 200px"
  560. >
  561. <t-color-picker
  562. class="w-full"
  563. format="CSS"
  564. :enable-alpha="true"
  565. :recent-colors="null"
  566. :swatch-colors="defaultGradientColor"
  567. :color-modes="['linear-gradient']"
  568. :show-primary-color-preview="false"
  569. v-model="data.pen.onGradientColors"
  570. @change="changeValue('onGradientColors')"
  571. />
  572. </div>
  573. <div
  574. v-else-if="data.pen.bkType === 2"
  575. style="width: 200px" class="mt-8 ml-8"
  576. >
  577. <t-color-picker
  578. class="simple"
  579. format="CSS"
  580. :enable-alpha="true"
  581. :recent-colors="null"
  582. :swatch-colors="defaultGradientColor"
  583. :color-modes="['linear-gradient']"
  584. :show-primary-color-preview="false"
  585. v-model="data.pen.onGradientColors"
  586. @change="changeValue('onGradientColors')"
  587. />
  588. </div>
  589. </div>
  590. <div class="form-item">
  591. <label style="width: 32px">{{$t('阴影')}} </label>
  592. <div class="flex middle ml-8">
  593. <t-checkbox
  594. v-model="data.pen.shadow"
  595. @change="changeValue('shadow')"
  596. style="width: 22px"
  597. />
  598. <t-color-picker
  599. v-if="data.pen.shadow"
  600. class="simple"
  601. format="CSS"
  602. :enable-alpha="true"
  603. :recent-colors="null"
  604. :swatch-colors="defaultPureColor"
  605. :color-modes="['monochrome']"
  606. :show-primary-color-preview="false"
  607. v-model="data.pen.shadowColor"
  608. @change="changeValue('shadowColor')"
  609. />
  610. </div>
  611. <label v-if="data.pen.shadow" style="width: 50px; margin-left: 25px">{{$t('文字阴影')}}
  612. </label>
  613. <div v-if="data.pen.shadow" class="flex middle ml-8">
  614. <t-checkbox
  615. v-model="data.pen.textHasShadow"
  616. @change="changeValue('textHasShadow')"
  617. style="width: 22px"
  618. />
  619. </div>
  620. </div>
  621. <div class="form-item" v-if="data.pen.shadow">
  622. <label style="width: 28px"></label>
  623. <div class="flex" style="margin-top: -8px">
  624. <t-input class="ml-4" label="X" placeholder="0" v-model.number="data.pen.shadowOffsetX" style="width: 60px" @change="changeValue('shadowOffsetX')" :title="$t('X偏移')"></t-input>
  625. <t-input class="ml-4" label="Y" placeholder="0" v-model.number="data.pen.shadowOffsetY" style="width: 60px" @change="changeValue('shadowOffsetY')" :title="$t('Y偏移')"></t-input>
  626. <t-input class="ml-4" placeholder="0" v-model.number="data.pen.shadowBlur" style="width: 64px" @change="changeValue('shadowBlur')" :label="$t('模糊')" :title="$t('模糊大小')"></t-input>
  627. </div>
  628. </div>
  629. </t-space>
  630. </t-collapse-panel>
  631. <t-collapse-panel v-if="data.pen.props.text" value="2" :header="$t('文字')">
  632. <t-space direction="vertical" size="small" class="w-full">
  633. <div class="form-item">
  634. <div class="flex middle" style="margin-left: -10px">
  635. <t-select-input
  636. :value="data.pen.fontFamily"
  637. :popup-visible="data.fontFamilyPopupVisible"
  638. :placeholder="$t('字体名')"
  639. allow-input
  640. style="width: 170px"
  641. @change="changeValue('fontFamily')"
  642. @enter="changeValue('fontFamily')"
  643. @blur="changeValue('fontFamily')"
  644. @popup-visible-change="onFontPopupVisible"
  645. :popup-props="{
  646. overlayInnerStyle: { width: 'auto' },
  647. }"
  648. >
  649. <template #panel>
  650. <ul style="padding: 12px">
  651. <li
  652. v-for="item in fonts"
  653. :key="item"
  654. @click="onFontFamily(item)"
  655. >
  656. {{ item }}
  657. </li>
  658. </ul>
  659. </template>
  660. <template #suffixIcon>
  661. <chevron-down-icon />
  662. <!-- <t-icon name="chevron-down" /> -->
  663. </template>
  664. </t-select-input>
  665. <t-input
  666. class="ml-8"
  667. :placeholder="$t('字体大小')"
  668. v-model.number="data.pen.fontSize"
  669. style="width: 80px"
  670. :format="decimalRound"
  671. @change="changeValue('fontSize')"
  672. />
  673. </div>
  674. </div>
  675. <div class="flex middle">
  676. <t-radio-group
  677. size="small"
  678. v-model="data.pen.textAlign"
  679. default-value="center"
  680. @change="changeValue('textAlign')"
  681. >
  682. <t-radio-button value="left">
  683. <t-tooltip :content="$t('居左')" placement="top">
  684. <format-vertical-align-left-icon />
  685. <!-- <t-icon name="format-vertical-align-left" /> -->
  686. </t-tooltip>
  687. </t-radio-button>
  688. <t-radio-button value="center">
  689. <t-tooltip placement="top" :content="$t('水平居中')">
  690. <format-vertical-align-center-icon></format-vertical-align-center-icon>
  691. <!-- <t-icon name="format-vertical-align-center" /> -->
  692. </t-tooltip>
  693. </t-radio-button>
  694. <t-radio-button value="right">
  695. <t-tooltip placement="top" :content="$t('居右')">
  696. <format-vertical-align-right-icon></format-vertical-align-right-icon>
  697. <!-- <t-icon name="format-vertical-align-right" /> -->
  698. </t-tooltip>
  699. </t-radio-button>
  700. </t-radio-group>
  701. <t-radio-group
  702. class="ml-8"
  703. size="small"
  704. v-model="data.pen.textBaseline"
  705. default-value="top"
  706. @change="changeValue('textBaseline')"
  707. >
  708. <t-radio-button value="top">
  709. <t-tooltip placement="top" :content="$t('顶部对齐')">
  710. <format-horizontal-align-top-icon></format-horizontal-align-top-icon>
  711. <!-- <t-icon name="format-horizontal-align-top" /> -->
  712. </t-tooltip>
  713. </t-radio-button>
  714. <t-radio-button value="middle">
  715. <t-tooltip placement="top" :content="$t('垂直居中')">
  716. <format-horizontal-align-center-icon></format-horizontal-align-center-icon>
  717. <!-- <t-icon name="format-horizontal-align-center" /> -->
  718. </t-tooltip>
  719. </t-radio-button>
  720. <t-radio-button value="bottom">
  721. <t-tooltip placement="top" :content="$t('底部对齐')">
  722. <format-horizontal-align-bottom-icon></format-horizontal-align-bottom-icon>
  723. <!-- <t-icon name="format-horizontal-align-bottom" /> -->
  724. </t-tooltip>
  725. </t-radio-button>
  726. </t-radio-group>
  727. <t-button
  728. :class="{ active: data.pen.fontWeight === 'bold' }"
  729. class="ml-8 icon"
  730. shape="rectangle"
  731. variant="text"
  732. @click="
  733. data.pen.fontWeight === 'bold'
  734. ? (data.pen.fontWeight = 'normal')
  735. : (data.pen.fontWeight = 'bold');
  736. changeValue('fontWeight');
  737. ">
  738. B
  739. </t-button>
  740. <t-button
  741. :class="{ active: data.pen.fontStyle === 'italic' }"
  742. class="ml-4 icon"
  743. shape="rectangle"
  744. variant="text"
  745. @click="
  746. data.pen.fontStyle === 'italic'
  747. ? (data.pen.fontStyle = 'normal')
  748. : (data.pen.fontStyle = 'italic');
  749. changeValue('fontStyle');
  750. "
  751. style="font-style: italic; font-family: serif"
  752. >I</t-button
  753. >
  754. </div>
  755. <div class="form-item">
  756. <!-- <t-color-picker
  757. class="simple mt-8 mr-4"
  758. format="CSS"
  759. :enable-alpha="true"
  760. :recent-colors="null"
  761. :swatch-colors="defaultPureColor"
  762. :color-modes="['monochrome']"
  763. :show-primary-color-preview="false"
  764. v-model="data.pen.textColor"
  765. @change="changeValue('textColor')"
  766. />
  767. <label style="width: 44px">前景</label> -->
  768. <t-color-picker
  769. class="simple mt-8 mr-4"
  770. format="CSS"
  771. :enable-alpha="true"
  772. :recent-colors="null"
  773. :swatch-colors="defaultPureColor"
  774. :color-modes="['monochrome']"
  775. :show-primary-color-preview="false"
  776. v-model="data.pen.textBackground"
  777. @change="changeValue('textBackground')"
  778. />
  779. <label style="width: 64px">{{$t( '背景' )}}</label>
  780. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.hoverTextColor" @change="changeValue('hoverTextColor')"></t-color-picker>
  781. <label style="width: 64px">{{$t('悬停')}}</label>
  782. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.activeTextColor" @change="changeValue('activeTextColor')"></t-color-picker>
  783. <label style="width: 64px">{{$t('选中')}}</label>
  784. </div>
  785. <div class="form-item">
  786. <label style="width: 32px">{{$t('前景')}}</label>
  787. <div class="ml-8">
  788. <t-radio-group size="small" v-model="data.pen.textType" :default-value="0" @change="changeValue('textType')">
  789. <t-radio-button :value="0"> {{$t('纯色')}} </t-radio-button>
  790. <t-radio-button :value="1"> {{$t('线性渐变')}} </t-radio-button>
  791. <t-radio-button :value="2"> {{$t('径向渐变')}} </t-radio-button>
  792. </t-radio-group>
  793. <div v-if="data.pen.textType === 0" class="mt-8 -ml-8">
  794. <t-color-picker
  795. class="w-full"
  796. format="CSS"
  797. :swatch-colors="defaultPureColor"
  798. :color-modes="['monochrome']"
  799. :recent-colors="null"
  800. :enable-alpha="true"
  801. :show-primary-color-preview="false"
  802. v-model="data.pen.textColor"
  803. @change="changeValue('textColor')"
  804. />
  805. </div>
  806. <div v-else-if="data.pen.textType === 1" class="mt-8 -ml-8" style="width: 200px">
  807. <t-color-picker class="w-full" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultGradientColor" :color-modes="['linear-gradient']" :show-primary-color-preview="false" v-model="data.pen.textGradientColors" @change="changeValue('textGradientColors')"></t-color-picker>
  808. </div>
  809. <div v-else-if="data.pen.textType === 2" class="mt-8 -ml-8" style="width: 200px">
  810. <t-color-picker class="w-full" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultGradientColor" :color-modes="['linear-gradient']" :show-primary-color-preview="false" v-model="data.pen.textGradientColors" @change="changeValue('textGradientColors')"></t-color-picker>
  811. </div>
  812. </div>
  813. </div>
  814. <div class="form-item">
  815. <t-checkbox :checked="data.pen.whiteSpace != 'nowrap' ? true : false" @change="changeValue('whiteSpace')" style="width: 64px">
  816. {{$t('换行')}}
  817. </t-checkbox>
  818. <t-checkbox v-model="data.pen.ellipsis" @change="changeValue('ellipsis')" style="width: 68px">
  819. {{$t('省略号')}}
  820. </t-checkbox>
  821. <t-tooltip :content="$t('行高')">
  822. <t-input v-model.number="data.pen.lineHeight" style="width: 40px" @change="changeValue('lineHeight')" :placeholder="$t('行高')"></t-input>
  823. </t-tooltip>
  824. <t-tooltip :content="$t('显示时保留小数位数')">
  825. <t-input class="ml-4" v-model.number="data.pen.keepDecimal" style="width: 60px" @change="changeValue('keepDecimal')" :placeholder="$t('小数')"></t-input>
  826. </t-tooltip>
  827. </div>
  828. <div class="form-item" style="margin-top: -4px">
  829. <t-tooltip :content="$t('水平偏移')">
  830. <t-input placeholder="X" v-model.number="data.pen.textLeft" style="width: 60px; margin-left: -8px" @change="changeValue('textLeft')"></t-input>
  831. </t-tooltip>
  832. <t-tooltip :content="$t('垂直偏移')">
  833. <t-input class="ml-4" placeholder="Y" v-model.number="data.pen.textTop" style="width: 60px" @change="changeValue('textTop')"></t-input>
  834. </t-tooltip>
  835. <t-tooltip :content="$t('宽')">
  836. <t-input class="ml-4" v-model.number="data.pen.textWidth" style="width: 60px" @change="changeValue('textWidth')" :placeholder="$t('宽')"></t-input>
  837. </t-tooltip>
  838. <t-tooltip :content="$t('高')">
  839. <t-input class="ml-4" v-model.number="data.pen.textHeight" style="width: 60px" @change="changeValue('textHeight')" :placeholder="$t('高')"></t-input>
  840. </t-tooltip>
  841. </div>
  842. <div class="flex middle">
  843. <t-checkbox v-model="data.pen.disableInput" @change="changeValue('disableInput')" style="width: 64px">
  844. {{$t('只读')}}
  845. </t-checkbox>
  846. <t-checkbox v-model="data.pen.hiddenText" @change="changeValue('hiddenText')" style="width: 90px">
  847. {{$t('隐藏文字')}}
  848. </t-checkbox>
  849. <t-checkbox v-model="data.pen.textAutoAdjust" @change="changeValue('textAutoAdjust')" style="width: 90px">
  850. {{$t('自动调整')}}
  851. </t-checkbox>
  852. </div>
  853. <div class="form-item">
  854. <label style="width: 64px">{{$t('文本内容')}} </label>
  855. <t-textarea class="w-full" v-model="data.pen.text" @change="changeValue('text')" :placeholder="$t('文本内容')"></t-textarea>
  856. </div>
  857. </t-space>
  858. </t-collapse-panel>
  859. <t-collapse-panel v-if="data.pen.props.image" value="3" :header="$t('图片')">
  860. <t-space direction="vertical" size="small" class="w-full">
  861. <div>
  862. <t-upload
  863. ref="uploadRef"
  864. v-model="data.images"
  865. action="/api/image/upload"
  866. theme="image"
  867. accept="image/*"
  868. :headers="headers"
  869. :data="updataData"
  870. :before-upload="beforeUpload"
  871. draggable
  872. @success="fileSuccessed"
  873. @remove="fileRemoved"
  874. >
  875. <template #fileListDisplay>
  876. <div style="z-index: 20">
  877. <a class="mr-4" @click="upload"> {{$t('点击上传')}} </a>
  878. / {{$t('拖拽图片到此区域')}}
  879. </div>
  880. </template>
  881. </t-upload>
  882. </div>
  883. <div class="form-item hover-icons" style="margin-left: -12px">
  884. <t-input
  885. class="ml-4"
  886. label="W"
  887. v-model.number="data.pen.iconWidth"
  888. :placeholder="$t('自适应')"
  889. min="1"
  890. style="width: 80px"
  891. :format="decimalPlaces"
  892. @change="changeValue('iconWidth')"
  893. />
  894. <t-tooltip
  895. v-if="data.pen.imageRatio"
  896. :content="$t('固定比例')"
  897. placement="top"
  898. >
  899. <link-icon class="ml-4 hover"
  900. @click="data.pen.imageRatio = !data.pen.imageRatio"/>
  901. <!-- <t-icon
  902. name="link"
  903. class="ml-4 hover"
  904. @click="data.pen.imageRatio = !data.pen.imageRatio"
  905. /> -->
  906. </t-tooltip>
  907. <t-tooltip v-else placement="top" :content="$t('不固定比例')">
  908. <link-unlink-icon class="ml-4 hover icon" @click="data.pen.imageRatio = !data.pen.imageRatio"></link-unlink-icon>
  909. <!-- <t-icon
  910. name="link-unlink"
  911. class="ml-4 hover icon"
  912. @click="data.pen.imageRatio = !data.pen.imageRatio"
  913. /> -->
  914. </t-tooltip>
  915. <t-input
  916. class="ml-4"
  917. label="H"
  918. :placeholder="$t('自适应')"
  919. v-model.number="data.pen.iconHeight"
  920. min="1"
  921. style="width: 80px"
  922. :format="decimalPlaces"
  923. @change="changeValue('iconHeight')"
  924. />
  925. <t-checkbox class="ml-8" v-model="data.pen.toGif" @change="changeValue('toGif')">
  926. {{$t('转动图')}}
  927. </t-checkbox>
  928. </div>
  929. <div class="form-item">
  930. <label style="width: 30px; color: var(--color)">Url:</label>
  931. <!-- {{ data.pen.image }} -->
  932. <t-input class="w-full" v-model.number="data.pen.image" @change="changeValue('image')" :placeholder="$t('图片地址')"></t-input>
  933. </div>
  934. </t-space>
  935. </t-collapse-panel>
  936. <t-collapse-panel v-if="data.pen.props.icon" value="4" :header="$t('图标')">
  937. <t-space direction="vertical" size="small" class="w-full">
  938. <div class="form-item">
  939. <label style="width: 32px">{{$t('图标')}} </label>
  940. <i class="ml-8" :class="data.pen.iconFamily" style="line-height: 30px; height: 30px; color: var(--color)">
  941. {{ data.pen.icon }}
  942. </i>
  943. <a class="ml-12 mt-4" @click="iconsDrawer.show = true">
  944. {{$t('选择')}}
  945. </a>
  946. <t-drawer v-model:visible="iconsDrawer.show" :footer="null" :header="$t('选择图标')">
  947. <Iconfonts :urls="data.iconUrls" @change="onChangeIcon"></Iconfonts>
  948. </t-drawer>
  949. </div>
  950. </t-space>
  951. </t-collapse-panel>
  952. <!-- <t-collapse-panel
  953. v-if="data.pen.props.custom"
  954. value="5"
  955. header="属性"
  956. >
  957. <t-space direction="vertical" size="small" class="w-full">
  958. <div v-for="item in data.pen.props.custom" class="form-item">
  959. <label :title="item.label">{{ item.label }}</label>
  960. <t-checkbox
  961. class="ml-8"
  962. v-if="item.type === 'bool'"
  963. v-model="data.pen[item.key]"
  964. @change="changeValue(item.key)"
  965. />
  966. <t-input-number
  967. class="w-full"
  968. v-else-if="item.type === 'number'"
  969. v-model.number="data.pen[item.key]"
  970. theme="column"
  971. :max="item.max"
  972. :min="item.min"
  973. @change="changeValue(item.key)"
  974. :placeholder="item.placeholder"
  975. />
  976. <t-color-picker
  977. class="w-full"
  978. v-else-if="item.type === 'color'"
  979. :enable-alpha="true"
  980. :recent-colors="null"
  981. format="CSS"
  982. :swatch-colors="defaultPureColor"
  983. :color-modes="['monochrome']"
  984. :show-primary-color-preview="false"
  985. v-model="data.pen[item.key]"
  986. @change="changeValue(item.key)"
  987. :placeholder="item.placeholder"
  988. />
  989. <t-select
  990. class="w-full"
  991. v-else-if="item.type === 'select'"
  992. size="small"
  993. :options="item.options"
  994. v-model="data.pen[item.key]"
  995. @change="changeValue(item.key)"
  996. :placeholder="item.placeholder"
  997. />
  998. <t-button
  999. v-else-if="item.type === 'code'"
  1000. shape="square"
  1001. variant="outline"
  1002. style="width: 24px"
  1003. @click="showPropsEdit(item)"
  1004. >
  1005. <t-icon name="ellipsis" slot="icon"
  1006. /></t-button>
  1007. <t-slider
  1008. v-else-if="item.type === 'slider'"
  1009. v-model="data.pen[item.key]"
  1010. :min="0"
  1011. :max="1"
  1012. :step="0.01"
  1013. @change="changeValue(item.key)"
  1014. />
  1015. <t-switch
  1016. v-else-if="item.type === 'switch'"
  1017. v-model="data.pen[item.key]"
  1018. @change="changeValue(item.key)"
  1019. />
  1020. <t-input
  1021. class="w-full"
  1022. v-else
  1023. v-model="data.pen[item.key]"
  1024. @change="changeValue(item.key)"
  1025. :placeholder="item.placeholder"
  1026. />
  1027. </div>
  1028. </t-space>
  1029. </t-collapse-panel> -->
  1030. </t-collapse>
  1031. <template v-if="!data.pen.externElement && data.pen.name !== 'image'&& data.pen.name !== 'gif'">
  1032. <t-divider style="margin: -8px 0" />
  1033. <div class="form-item px-16">
  1034. <label class="form-title">{{$t( '进度' )}} </label>
  1035. <t-slider
  1036. v-model="data.pen.progress"
  1037. :min="0"
  1038. :max="1"
  1039. :step="0.01"
  1040. @change="changeValue('progress')"
  1041. />
  1042. <span class="ml-16" style="width: 50px; line-height: 30px">
  1043. {{ data.pen.progress }}
  1044. </span>
  1045. </div>
  1046. <div class="form-item" style="padding-left: 17px">
  1047. <t-color-picker
  1048. class="simple mr-25"
  1049. format="CSS"
  1050. :enable-alpha="true"
  1051. :recent-colors="null"
  1052. :swatch-colors="defaultPureColor"
  1053. :color-modes="['monochrome']"
  1054. :show-primary-color-preview="false"
  1055. v-model="data.pen.progressColor"
  1056. @change="changeValue('progressColor')"
  1057. />
  1058. <t-tooltip placement="top" :content="$t('垂直进度')">
  1059. <t-checkbox class="mr-25" v-model="data.pen.verticalProgress" @change="changeValue('verticalProgress')" style="width: 22px"></t-checkbox>
  1060. </t-tooltip>
  1061. <t-tooltip placement="top" :content="$t('反向进度')">
  1062. <t-checkbox class="mr-25" v-model="data.pen.reverseProgress" @change="changeValue('reverseProgress')" style="width: 22px"></t-checkbox>
  1063. </t-tooltip>
  1064. <t-tooltip placement="top" :content="$t('进度渐变')">
  1065. <t-checkbox class="mr-25" v-model="data.pen.temProgressFlag" @change="changetemProgressFlag(data.pen)" style="width: 22px"></t-checkbox>
  1066. </t-tooltip>
  1067. <t-color-picker v-if="data.pen.temProgressFlag" class="simple" format="CSS" :swatch-colors="defaultGradientColor" :color-modes="['linear-gradient']" :show-primary-color-preview="false" :recent-colors="null" :enableAlpha="true" v-model="data.pen.progressGradientColors" @change="changeValue('progressGradientColors')" :placeholder="$t('无')"></t-color-picker>
  1068. </div>
  1069. </template>
  1070. <t-divider style="margin: -8px 0" />
  1071. <div class="form-item px-16" style="margin-top: -12px">
  1072. <t-checkbox v-model="data.pen.flipX" @change="changeValue('flipX')" style="width: 90px">
  1073. {{$t('水平翻转')}}
  1074. </t-checkbox>
  1075. <t-checkbox v-model="data.pen.flipY" @change="changeValue('flipY')" style="width: 90px">
  1076. {{$t('垂直翻转')}}
  1077. </t-checkbox>
  1078. <label style="width: 50px">{{$t('锚点半径')}}</label>
  1079. <input class="ml-4" v-model.number="data.pen.anchorRadius" style="width: 20px" @change="changeValue('anchorRadius')" placeholder="4">
  1080. </div>
  1081. <t-divider style="margin: -8px 0" />
  1082. <div class="form-item px-16" style="margin-top: -12px;margin-bottom: -8px;">
  1083. <label class="form-title" style="width: 90px">{{$t('禁止')}} </label>
  1084. <t-checkbox v-model="data.pen.disabled" @change="changeValue('disabled')" style="width: 90px">
  1085. {{$t('禁用')}}
  1086. </t-checkbox>
  1087. </div>
  1088. <div class="form-item px-16">
  1089. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" :clearable="true" v-model="data.pen.disabledBackground" @change="changeValue('disabledBackground')"></t-color-picker>
  1090. <label style="width: 64px">{{$t('禁用背景')}}</label>
  1091. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.disabledColor" :clearable="true" @change="changeValue('disabledColor')"></t-color-picker>
  1092. <label style="width: 64px">{{$t('禁用颜色')}}</label>
  1093. <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.pen.disabledTextColor" :clearable="true" @change="changeValue('disabledTextColor')"></t-color-picker>
  1094. <label style="width: 164px">{{$t('禁用文字颜色')}}</label>
  1095. </div>
  1096. <div class="form-item px-16" style="margin-top: -12px">
  1097. <t-checkbox v-model="data.pen.disableRotate" @change="changeValue('disableRotate')" style="width: 84px">
  1098. {{$t('禁止旋转')}}
  1099. </t-checkbox>
  1100. <t-checkbox v-model="data.pen.disableSize" @change="changeValue('disableSize')" style="width: 84px">
  1101. {{$t('禁止缩放')}}
  1102. </t-checkbox>
  1103. <t-checkbox v-model="data.pen.disableAnchor" @change="changeValue('disableAnchor')" style="width: 84px">
  1104. {{$t('禁用锚点')}}
  1105. </t-checkbox>
  1106. </div>
  1107. <t-divider style="margin: -8px 0" />
  1108. <div class="form-item px-16" style="margin-top: -12px">
  1109. <label style="width: 60px">{{$t('鼠标提示')}}</label>
  1110. <t-button shape="square" variant="outline" style="width: 24px" @click="showTooltip">
  1111. <ellipsis-icon slot="icon"></ellipsis-icon>
  1112. <!-- <t-icon name="ellipsis" slot="icon" /> -->
  1113. </t-button>
  1114. </div>
  1115. <t-dialog v-if="tooltipDialog.show" :visible="true" @confirm="onOkTooltip" @close="tooltipDialog.show = false" :width="700" :header="$t('鼠标提示')">
  1116. <t-radio-group v-model="tooltipDialog.type">
  1117. <t-radio value="1">{{$t('文字')}}</t-radio>
  1118. <t-radio value="2">{{$t('函数')}}</t-radio>
  1119. </t-radio-group>
  1120. <div class="py-8">
  1121. <CodeEditor
  1122. v-show="tooltipDialog.type == 1"
  1123. v-model="tooltipDialog.title"
  1124. style="height: 300px"
  1125. />
  1126. <div v-show="tooltipDialog.type == 2">
  1127. <div>function tooltip(pen) {</div>
  1128. <CodeEditor
  1129. v-model="tooltipDialog.titleFnJs"
  1130. class="mt-4"
  1131. style="height: 248px"
  1132. />
  1133. <div class="mt-4">}</div>
  1134. </div>
  1135. </div>
  1136. <div class="gray" style="font-size: 12px">{{$t('支持')}}Markdown{{$t('格式')}}</div>
  1137. </t-dialog>
  1138. <t-dialog
  1139. v-if="propsDialog.show"
  1140. :visible="true"
  1141. :header="propsDialog.header"
  1142. @confirm="onOkPropsEdit"
  1143. @close="propsDialog.show = false"
  1144. :width="700"
  1145. >
  1146. <div class="py-8">
  1147. <CodeEditor
  1148. :json="true"
  1149. :language="'json'"
  1150. v-model="propsDialog.value"
  1151. style="height: 300px"
  1152. />
  1153. </div>
  1154. <div class="gray" style="font-size: 12px">
  1155. {{ propsDialog.placeholder }}
  1156. </div>
  1157. </t-dialog>
  1158. <t-space />
  1159. </t-space>
  1160. </t-tab-panel>
  1161. <t-tab-panel :value="2" :label="$t('动画')">
  1162. <PenAnimates :pen="data.pen"></PenAnimates>
  1163. </t-tab-panel>
  1164. <t-tab-panel :value="3" :label="$t('数据')">
  1165. <PenDatas :pen="data.pen" @tabchange="tabChange"></PenDatas>
  1166. </t-tab-panel>
  1167. <t-tab-panel :value="5" :label="$t('状态')">
  1168. <PenStatus :pen="data.pen" ref="status"></PenStatus>
  1169. </t-tab-panel>
  1170. <t-tab-panel :value="4" :label="$t('交互')">
  1171. <PenEvents :key="data.key" :pen="data.pen"></PenEvents>
  1172. </t-tab-panel>
  1173. <!-- <t-tab-panel :value="5" label="结构">
  1174. <ElementTree />
  1175. </t-tab-panel> -->
  1176. </t-tabs>
  1177. </div>
  1178. </template>
  1179. <script lang="ts" setup>
  1180. import { onBeforeMount, onUnmounted, reactive, ref, watch, computed, getCurrentInstance } from 'vue';
  1181. import CodeEditor from './common/CodeEditor.vue';
  1182. import Iconfonts from './common/Iconfonts.vue';
  1183. import PenAnimates from './PenAnimates.vue';
  1184. import PenDatas from './PenDatas.vue';
  1185. import PenEvents from './PenEvents.vue';
  1186. import PenStatus from './PenStatus.vue';
  1187. import Custom from './Custom.vue';
  1188. // import ElementTree from './ElementTree.vue';
  1189. import { getCookie } from '@/services/cookie';
  1190. import { useSelection } from '@/services/selections';
  1191. import { autoSave, fonts, inTreePanel } from '@/services/common';
  1192. import { updatePen } from './pen';
  1193. import { MessagePlugin } from 'tdesign-vue-next';
  1194. import { useUser } from '@/services/user';
  1195. import { getter, queryURLParams, isDomShapes } from '@meta2d/core';
  1196. import { defaultGradientColor, defaultPureColor, fromArrows, toArrows } from '@/services/defaults';
  1197. import { getLe5le3d, getLe5leV, getLe5le2d } from '@/services/api';
  1198. import { s8 } from '@/services/random';
  1199. import { EllipsisIcon, LinkIcon, LinkUnlinkIcon, ChevronDownIcon, FormatVerticalAlignLeftIcon, FormatHorizontalAlignCenterIcon, FormatVerticalAlignCenterIcon, FormatVerticalAlignRightIcon, FormatHorizontalAlignTopIcon, FormatHorizontalAlignBottomIcon } from 'tdesign-icons-vue-next';
  1200. const { user } = useUser();
  1201. const headers = {
  1202. Authorization: 'Bearer ' + (getCookie('token') || ''),
  1203. };
  1204. const updataData = {
  1205. directory: '/大屏/图片/默认' ,
  1206. conflict:'new'
  1207. };
  1208. const { proxy } = getCurrentInstance();
  1209. const $t = proxy.$t
  1210. const uploadRef = ref();
  1211. const childUploadRef = ref();
  1212. const data = reactive<any>({
  1213. tab: 1,
  1214. pen: {},
  1215. rect: {},
  1216. key: s8(),
  1217. childPen: {},
  1218. });
  1219. const { selections } = useSelection();
  1220. const tooltipDialog = reactive<any>({
  1221. show: false,
  1222. });
  1223. const propsDialog = reactive<any>({
  1224. show: false,
  1225. });
  1226. const iconsDrawer = reactive<any>({
  1227. show: false,
  1228. });
  1229. const aligns = [
  1230. {
  1231. value: 'left',
  1232. label: $t('左对齐'),
  1233. icon: '#l-align-left',
  1234. },
  1235. {
  1236. value: 'center',
  1237. label: $t('垂直居中对齐'),
  1238. icon: '#l-align-center',
  1239. },
  1240. {
  1241. value: 'right',
  1242. label: $t('右对齐'),
  1243. icon: '#l-align-right',
  1244. },
  1245. {
  1246. value: 'top',
  1247. label: $t('顶部对齐'),
  1248. icon: '#l-align-top',
  1249. },
  1250. {
  1251. value: 'middle',
  1252. label: $t('水平居中对齐'),
  1253. icon: '#l-align-middle',
  1254. },
  1255. {
  1256. value: 'bottom',
  1257. label: $t('底部对齐'),
  1258. icon: '#l-align-bottom',
  1259. },
  1260. ];
  1261. const align = (align: string) => {
  1262. meta2d.alignNodesV(align, meta2d.store.active);
  1263. getRect();
  1264. meta2d.render();
  1265. };
  1266. onBeforeMount(() => {
  1267. if (inTreePanel.value) {
  1268. // data.tab = 5;
  1269. }
  1270. const d = meta2d.store.data as any;
  1271. if (!d.groups) {
  1272. d.groups = [];
  1273. }
  1274. if (!d.iconUrls) {
  1275. d.iconUrls = [];
  1276. }
  1277. data.iconUrls = d.iconUrls;
  1278. data.groups = d.groups;
  1279. initPenData();
  1280. meta2d.on('translatePens', getRect);
  1281. meta2d.on('resizePens',detailResizePens);
  1282. meta2d.on('rotatePens', getRect);
  1283. });
  1284. function initPenData() {
  1285. data.key = s8(); //触发更新
  1286. data.pen = selections.pen;
  1287. if (!data.pen.props) {
  1288. data.pen.props = {};
  1289. }
  1290. if (!data.pen.globalAlpha && data.pen.globalAlpha !== 0) {
  1291. data.pen.globalAlpha = 1;
  1292. }
  1293. if (!data.pen.dash) {
  1294. data.pen.dash = 0;
  1295. }
  1296. if(data.pen.props?.custom?.length && !data.pen.props?.look){
  1297. data.pen.props.look = false;
  1298. }
  1299. if (!data.pen.props.text) {
  1300. if (data.pen.text || data.pen.name === 'text') {
  1301. data.pen.props.text = true;
  1302. }
  1303. }
  1304. if(['tablePlus','notification','menuDom','radio','checkbox','thermometer','thermometer1','rectangle','tab'].includes(data.pen.name)){
  1305. data.pen.props.look = true;
  1306. data.pen.props.text = true;
  1307. }
  1308. if(['indicatorLight','battery'].includes(data.pen.name)||data.pen.name.endsWith('Switch')){
  1309. data.pen.props.look = true;
  1310. }
  1311. if(data.pen.name === 'combine'){
  1312. if(!data.pen.props){
  1313. data.pen.props = {};
  1314. }
  1315. if(!data.pen.props.custom){
  1316. data.pen.props.custom = [];
  1317. }
  1318. }
  1319. if (!data.pen.props.image) {
  1320. if (data.pen.image) {
  1321. data.pen.props.image = true;
  1322. }
  1323. }
  1324. if (!data.pen.props.icon) {
  1325. if (data.pen.icon) {
  1326. data.pen.props.icon = true;
  1327. }
  1328. }
  1329. if (data.pen.image) {
  1330. data.images = [
  1331. {
  1332. url: data.pen.image,
  1333. },
  1334. ];
  1335. }
  1336. if (!data.pen.tags) {
  1337. data.pen.tags = [];
  1338. }
  1339. if (data.pen.bkType == undefined) {
  1340. data.pen.bkType = 0;
  1341. }
  1342. if (data.pen.textType == undefined) {
  1343. data.pen.textType = 0;
  1344. }
  1345. if (!data.pen.animations) {
  1346. data.pen.animations = [];
  1347. }
  1348. if (!data.pen.whiteSpace) {
  1349. data.pen.whiteSpace = 'break-all';
  1350. }
  1351. if (data.pen.ellipsis == undefined) {
  1352. data.pen.ellipsis = false;
  1353. }
  1354. data.pen.shadow = !!data.pen.shadowColor;
  1355. getRect();
  1356. if(data.pen.name === 'combine' && data.pen.showChild !== undefined){
  1357. data.childPen = meta2d.store.pens[data.pen.children[data.pen.showChild]];
  1358. data.childImages = [
  1359. {
  1360. url: data.childPen.image,
  1361. },
  1362. ];
  1363. }
  1364. }
  1365. const watcher = watch(() => selections.pen.id, initPenData);
  1366. const getRect = () => {
  1367. if(data.pen.parentId){
  1368. const origin = meta2d.store.data.origin;
  1369. const scale = meta2d.store.data.scale;
  1370. data.rect = {
  1371. x: (data.pen.calculative.worldRect.x - origin.x) / scale,
  1372. y: (data.pen.calculative.worldRect.y - origin.y) / scale,
  1373. width: data.pen.calculative.worldRect.width / scale,
  1374. height: data.pen.calculative.worldRect.height / scale
  1375. }
  1376. return;
  1377. }
  1378. data.rect = meta2d.getPenRect(data.pen);
  1379. };
  1380. const detailResizePens = () => {
  1381. getRect();
  1382. updateTabBtnData();
  1383. }
  1384. const updateTabBtnData = () => {//更新tab按钮的宽高
  1385. if(data.pen.name === 'tab') {
  1386. const len = data.pen.data.length;
  1387. const gap = data.pen.gap;
  1388. const {width: w, height: h} = data.rect;
  1389. let btnWidth = 0, btnHeight = 0;
  1390. if (data.pen.direction == 'horizontal') {
  1391. btnWidth = (w - (len + 1) * gap) / len;
  1392. btnHeight = h - gap * 2;
  1393. } else {
  1394. btnWidth = w - gap * 2;
  1395. btnHeight = (h - (len + 1) * gap) / len;
  1396. }
  1397. data.pen.btnWidth = btnWidth;
  1398. data.pen.btnHeight = btnHeight;
  1399. }
  1400. }
  1401. const decimalPlaces = (val: number) => {
  1402. if (!val) {
  1403. return 0;
  1404. }
  1405. return Math.round(+val * 100) / 100;
  1406. };
  1407. const decimalRound = (val: number) => {
  1408. return Math.round(+val || 0);
  1409. };
  1410. const changeValue = (prop: string) => {
  1411. if(prop.indexOf('radient')!==-1){
  1412. let collect = document.querySelectorAll('[class^="t-color-picker"]')
  1413. collect.forEach((i:HTMLElement)=> {
  1414. if(!i.dataset.meta2dIgnore){
  1415. i.dataset.meta2dIgnore = 'true';
  1416. }
  1417. })
  1418. }
  1419. if(prop === 'toGif'){
  1420. if(data.pen.toGif){
  1421. meta2d.setValue({id:data.pen.id,name:'gif'});
  1422. }else{
  1423. meta2d.setValue({id:data.pen.id,name:'image'});
  1424. }
  1425. return;
  1426. }
  1427. if(prop === 'showChild'){
  1428. data.childPen = meta2d.store.pens[data.pen.children[data.pen.showChild]];
  1429. data.childImages = [
  1430. {
  1431. url: data.childPen.image,
  1432. },
  1433. ];
  1434. }
  1435. updatePen(data.pen, prop);
  1436. selections.pen[prop] = getter(data.pen, prop);
  1437. if (prop === 'iframe') {
  1438. getThumbImg();
  1439. }
  1440. if(prop === 'image'){
  1441. data.images = [
  1442. {
  1443. url: data.pen.image,
  1444. },
  1445. ];
  1446. }
  1447. };
  1448. const getThumbImg = async () => {
  1449. //改iframe地址后
  1450. let arr = data.pen.iframe.split('?');
  1451. let id = queryURLParams(arr[1]).id;
  1452. if (!id) {
  1453. return;
  1454. }
  1455. let projection = 'image,id,name';
  1456. let res: any;
  1457. if (arr[0].indexOf('2d.le5le') !== -1) {
  1458. res = await getLe5le2d(id, projection);
  1459. } else if (arr[0].indexOf('v.le5le') !== -1) {
  1460. res = await getLe5leV(id, projection);
  1461. } else if (arr[0].indexOf('3d.le5le') !== -1) {
  1462. res = await getLe5le3d(id, projection);
  1463. }
  1464. if (res) {
  1465. data.pen.thumbImg = res.image;
  1466. }
  1467. data.pen.onRenderPenRaw?.(data.pen);
  1468. };
  1469. const changeID = (value: any) => {
  1470. if (!value) {
  1471. initPenData();
  1472. MessagePlugin.error($t('id 不能为空'));
  1473. return;
  1474. }
  1475. const oldID: string = data.pen.id;
  1476. try {
  1477. meta2d.changePenId(oldID, value);
  1478. initPenData();
  1479. } catch (error) {
  1480. console.warn(error.message);
  1481. MessagePlugin.error($t('id 修改失败,请检查 id 是否重复'));
  1482. return;
  1483. }
  1484. };
  1485. const changeRectValue = (prop: string) => {
  1486. if(['width','height'].includes(prop)){
  1487. data.rect[prop] = data.rect[prop]||1;
  1488. }
  1489. if(data.pen.parentId){
  1490. if(['x','y','width','height'].includes(prop)){
  1491. const scale = meta2d.store.data.scale;
  1492. const origin = meta2d.store.data.origin;
  1493. let rect = {
  1494. x:data.rect.x*scale+origin.x,
  1495. y:data.rect.y*scale+origin.y,
  1496. width:data.rect.width*scale,
  1497. height:data.rect.height*scale,
  1498. }
  1499. meta2d.updateRectbyChild(rect,data.pen,meta2d.store.pens[data.pen.parentId]);
  1500. return;
  1501. }
  1502. }
  1503. data.rect.id = data.pen.id;
  1504. data.rect.ratio = data.pen.ratio;
  1505. updatePen(data.rect, prop);
  1506. };
  1507. const onFontPopupVisible = (val: boolean) => {
  1508. data.fontFamilyPopupVisible = val;
  1509. };
  1510. const onFontFamily = (fontFamily: string) => {
  1511. data.pen.fontFamily = fontFamily;
  1512. data.fontFamilyPopupVisible = false;
  1513. changeValue('fontFamily');
  1514. };
  1515. const beforeUpload = (file: any) => {
  1516. // if (file.size > 5 * 1024 * 1024) {
  1517. // MessagePlugin.warning($t('上传的图片不能大于5M'));
  1518. // return false;
  1519. // }
  1520. if (!(user && user.id)) {
  1521. MessagePlugin.warning($t('请先登录!'));
  1522. return false;
  1523. }
  1524. return true;
  1525. };
  1526. const fileSuccessed = async (content: any) => {
  1527. // meta2d.store.patchFlagsBackground = true;
  1528. // meta2d.setBackgroundImage(content.response.url);
  1529. // meta2d.store.patchFlagsBackground = true;
  1530. data.pen.image = content.response.url || `/file${content.response.filename}`;
  1531. updatePen(data.pen, 'image');
  1532. meta2d.canvas.canvasImage.init();
  1533. meta2d.canvas.canvasImageBottom.init();
  1534. meta2d.render();
  1535. };
  1536. const fileRemoved = () => {
  1537. // meta2d.setBackgroundImage('');
  1538. // meta2d.store.patchFlagsBackground = true;
  1539. data.pen.image = '';
  1540. updatePen(data.pen, 'image');
  1541. meta2d.render();
  1542. // data.background = [];
  1543. };
  1544. const fileChildSuccessed = async (content: any) => {
  1545. data.childPen.image = content.response.url || `/file${content.response.filename}`;
  1546. updatePen(data.childPen, 'image');
  1547. meta2d.canvas.canvasImage.init();
  1548. meta2d.canvas.canvasImageBottom.init();
  1549. meta2d.render();
  1550. };
  1551. const childUpload = () => {
  1552. childUploadRef.value.triggerUpload();
  1553. };
  1554. const changeChildValue = (prop: string) => {
  1555. updatePen(data.childPen, prop);
  1556. if(prop === 'image'){
  1557. data.childImages = [
  1558. {
  1559. url: data.childPen.image,
  1560. },
  1561. ];
  1562. }
  1563. };
  1564. const upload = () => {
  1565. uploadRef.value.triggerUpload();
  1566. };
  1567. const onSelectTag = (tag: string) => {
  1568. data.tagPopupVisible = false;
  1569. if (data.pen.tags.includes(tag)) {
  1570. return;
  1571. }
  1572. data.pen.tags.push(tag);
  1573. changeValue('tags');
  1574. };
  1575. const onChangeInputTag = (currentTags: any, context: any) => {
  1576. const { trigger, index, item } = context;
  1577. if (['tag-remove', 'backspace'].includes(trigger)) {
  1578. data.pen.tags.splice(index, 1);
  1579. }
  1580. if (trigger === 'enter') {
  1581. onSelectTag(item);
  1582. const d = meta2d.store.data as any;
  1583. if (!d.groups.includes(item)) {
  1584. d.groups.push(item);
  1585. data.groups = d.groups;
  1586. }
  1587. data.inputTag = '';
  1588. }
  1589. data.tagPopupVisible = false;
  1590. };
  1591. const showTooltip = () => {
  1592. tooltipDialog.title = data.pen.title || '';
  1593. tooltipDialog.titleFnJs =
  1594. data.pen.titleFnJs || '// 例如:return `${pen.name}<br/>${pen.text}`;';
  1595. tooltipDialog.type = data.pen.titleFnJs ? '2' : '1';
  1596. tooltipDialog.show = true;
  1597. };
  1598. const onOkTooltip = () => {
  1599. data.pen.titleFn = null;
  1600. if (tooltipDialog.type === '1') {
  1601. data.pen.title = tooltipDialog.title;
  1602. data.pen.titleFnJs = '';
  1603. } else {
  1604. data.pen.title = '';
  1605. data.pen.titleFnJs = tooltipDialog.titleFnJs;
  1606. }
  1607. tooltipDialog.show = false;
  1608. };
  1609. const showPropsEdit = (item: any) => {
  1610. propsDialog.key = item.key;
  1611. propsDialog.header = `${item.label}(${item.key})`;
  1612. propsDialog.value = data.pen[item.key];
  1613. propsDialog.placeholder = item.placeholder;
  1614. propsDialog.show = true;
  1615. };
  1616. const onOkPropsEdit = () => {
  1617. if (!propsDialog.value) {
  1618. MessagePlugin.error($t('数据不满足json格式'));
  1619. return;
  1620. }
  1621. data.pen[propsDialog.key] = propsDialog.value;
  1622. updatePen(data.pen, propsDialog.key);
  1623. propsDialog.show = false;
  1624. };
  1625. const onChangeIcon = (params: any) => {
  1626. Object.assign(data.pen, params);
  1627. meta2d.setValue({
  1628. id: data.pen.id,
  1629. icon: params.icon,
  1630. iconFamily: params.iconFamily,
  1631. });
  1632. autoSave(true);
  1633. };
  1634. const changetemProgressFlag = (pen: any) => {
  1635. if (pen.temProgressFlag) {
  1636. } else {
  1637. pen.progressGradientColors = undefined;
  1638. changeValue('progressGradientColors');
  1639. }
  1640. };
  1641. const isDom = computed(() => {
  1642. return isDomShapes.includes(data.pen.name) ||
  1643. data.pen.name.endsWith('Dom') ||
  1644. meta2d.store.options.domShapes.includes(data.pen.name)
  1645. });
  1646. const status = ref<any>(null);
  1647. const tabChange = (index: number) => {
  1648. data.tab = 5;
  1649. setTimeout(()=>{
  1650. status.value.editLast(index);
  1651. },1000);
  1652. };
  1653. onUnmounted(() => {
  1654. watcher();
  1655. meta2d.off('translatePens', getRect);
  1656. meta2d.off('resizePens', detailResizePens);
  1657. meta2d.off('rotatePens', getRect);
  1658. });
  1659. </script>
  1660. <style lang="postcss" scoped>
  1661. .props {
  1662. .icons {
  1663. display: flex;
  1664. svg:hover {
  1665. cursor: pointer;
  1666. color: var(--color-primary);
  1667. }
  1668. .btn {
  1669. font-size: 16px;
  1670. margin-right: 16px;
  1671. color: var(--color);
  1672. }
  1673. }
  1674. .form-title{
  1675. font-size: 13px;
  1676. font-weight: 700;
  1677. color: var(--color-title);
  1678. }
  1679. .t-upload__dragger-btns{
  1680. display: none !important;
  1681. }
  1682. .t-textarea{
  1683. :deep(.t-textarea__inner){
  1684. font-size: 12px;
  1685. height: 80px;
  1686. }
  1687. }
  1688. }
  1689. </style>