PenProps.vue 78 KB

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