Actions.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. <template>
  2. <div class="props">
  3. <div v-for="(a, index) in data.actions" class="mb-12">
  4. <div class="flex middle between">
  5. <div class="flex middle">动作{{ index + 1 }}</div>
  6. <t-icon
  7. name="close"
  8. class="hover"
  9. @click="data.actions.splice(index, 1)"
  10. />
  11. </div>
  12. <div class="py-4">
  13. <div class="form-item mt-4">
  14. <label>动作类型</label>
  15. <t-select
  16. v-model="a.action"
  17. placeholder="请选择"
  18. @change="onChangeAction(a)"
  19. >
  20. <t-option
  21. v-for="option in actionOptions"
  22. :key="option.value"
  23. :value="option.value"
  24. :label="option.label"
  25. />
  26. </t-select>
  27. </div>
  28. <template v-if="a.action == 0">
  29. <div class="form-item mt-8">
  30. <label>链接地址</label>
  31. <t-input v-model="a.value" placeholder="URL" />
  32. </div>
  33. <div class="form-item mt-8">
  34. <label>打开方式</label>
  35. <t-radio-group v-model="a.params">
  36. <t-radio value="_blank">新页面</t-radio>
  37. <t-radio value="_self">当前页面</t-radio>
  38. </t-radio-group>
  39. </div>
  40. </template>
  41. <template v-else-if="a.action == 13">
  42. <div class="form-item mt-8">
  43. <label>视图</label>
  44. <t-input v-model="a.value" placeholder="ID" />
  45. </div>
  46. </template>
  47. <template v-else-if="a.action == 2 || a.action == 3 || a.action == 4">
  48. <div class="form-item mt-8">
  49. <label>对象类型</label>
  50. <t-radio-group v-model="a.targetType" @change="a.value = ''">
  51. <t-radio value="id">图元</t-radio>
  52. <t-radio value="tag">组</t-radio>
  53. </t-radio-group>
  54. </div>
  55. <div class="form-item mt-8">
  56. <label>播放对象</label>
  57. <t-tree-select
  58. v-if="a.targetType === 'id'"
  59. v-model="a.value"
  60. :data="penTree"
  61. filterable
  62. placeholder="默认自己"
  63. @change="getAnimations(a.value)"
  64. />
  65. <t-select
  66. v-else
  67. v-model="a.value"
  68. :options="groups"
  69. placeholder="组"
  70. @change="getAnimations(a.value)"
  71. />
  72. </div>
  73. <div class="form-item mt-8">
  74. <label>动画名称</label>
  75. <t-select-input
  76. v-model:inputValue="a.params"
  77. :value="a.params"
  78. v-model:popupVisible="a.popupVisible"
  79. allow-input
  80. clearable
  81. @clear="a.params = undefined"
  82. @focus="a.popupVisible = true"
  83. @blur="a.popupVisible = undefined"
  84. placeholder="缺省第一个动画"
  85. >
  86. <template #panel>
  87. <ul style="padding: 8px 12px">
  88. <li
  89. v-for="item in animations"
  90. :key="item"
  91. @click="a.params = item"
  92. >
  93. {{ item }}
  94. </li>
  95. </ul>
  96. </template>
  97. </t-select-input>
  98. </div>
  99. </template>
  100. <template v-else-if="a.action == 1">
  101. <div class="form-item mt-8">
  102. <label>对象类型</label>
  103. <t-radio-group v-model="a.targetType" @change="a.params = ''">
  104. <t-radio value="id">图元</t-radio>
  105. <t-radio value="tag">组</t-radio>
  106. </t-radio-group>
  107. </div>
  108. <div class="form-item mt-8">
  109. <label>更改对象</label>
  110. <t-tree-select
  111. v-if="a.targetType === 'id'"
  112. v-model="a.params"
  113. :data="penTree"
  114. filterable
  115. placeholder="默认自己"
  116. @change="getProps(a)"
  117. />
  118. <t-select
  119. v-else
  120. v-model="a.params"
  121. :options="groups"
  122. placeholder="组"
  123. />
  124. </div>
  125. <div class="form-item mt-8">
  126. <label>属性数据</label>
  127. <div class="w-full">
  128. <div class="prop-grid head">
  129. <div>属性名</div>
  130. <div>属性值</div>
  131. <div class="right">
  132. <t-dropdown
  133. :min-column-width="160"
  134. @click="onAddValue(a, $event)"
  135. >
  136. <t-icon name="add-circle" class="hover" />
  137. <t-dropdown-menu>
  138. <t-dropdown-item
  139. key="custom"
  140. value="custom"
  141. disabled="true"
  142. divider="true"
  143. class="input"
  144. >
  145. <t-input
  146. v-model="a.input"
  147. placeholder="自定义"
  148. @enter="
  149. onAddValue(a, { key: a.input });
  150. a.input = '';
  151. "
  152. />
  153. </t-dropdown-item>
  154. <t-dropdown-item
  155. v-for="prop in a.props"
  156. :key="prop.value"
  157. :value="prop.value"
  158. >
  159. {{ prop.label }}
  160. </t-dropdown-item>
  161. </t-dropdown-menu>
  162. </t-dropdown>
  163. </div>
  164. </div>
  165. <template
  166. v-if="Object.keys(a.value).length"
  167. class="center gray mt-8"
  168. >
  169. <div class="prop-grid mt-8" v-for="(value, key) in a.value">
  170. <div class="ml-8">
  171. <t-tooltip :content="key">
  172. {{ getPropDesc(a, key) }}
  173. </t-tooltip>
  174. </div>
  175. <div>
  176. <t-input v-model="a.value[key]" placeholder="值" />
  177. </div>
  178. <div class="right px-8" style="line-height: 20px">
  179. <t-icon
  180. name="delete"
  181. class="hover"
  182. @click="delete a.value[key]"
  183. />
  184. </div>
  185. </div>
  186. </template>
  187. <div v-else class="center gray mt-8">暂无数据</div>
  188. </div>
  189. </div>
  190. </template>
  191. <template v-else-if="a.action == 14">
  192. <div class="form-item mt-8">
  193. <label>窗口标题</label>
  194. <t-input v-model="a.value" placeholder="弹框标题" />
  195. </div>
  196. <div class="form-item mt-8">
  197. <label>画面URL</label>
  198. <t-input v-model="a.params" placeholder="窗口画面URL" />
  199. </div>
  200. </template>
  201. <template v-else-if="a.action == 7">
  202. <div class="form-item mt-8">
  203. <label>消息名称</label>
  204. <t-input v-model="a.value" placeholder="名称" />
  205. </div>
  206. <div class="form-item mt-8">
  207. <label>消息参数</label>
  208. <t-input v-model="a.params" placeholder="参数" />
  209. </div>
  210. </template>
  211. <template v-else-if="a.action == 15">
  212. <Network v-model="a.network" type="publish" mode="1" />
  213. <div class="form-item mt-8">
  214. <label>数据对象</label>
  215. <t-tree-select
  216. v-model="a.params"
  217. :data="penTree"
  218. filterable
  219. placeholder="默认自己"
  220. @change="getProps(a)"
  221. />
  222. </div>
  223. <div class="form-item mt-8">
  224. <label>属性数据</label>
  225. <div class="w-full">
  226. <div class="prop-grid head">
  227. <div>属性名</div>
  228. <div>属性值</div>
  229. <div class="right">
  230. <t-dropdown
  231. :min-column-width="160"
  232. @click="onAddValue(a, $event)"
  233. >
  234. <t-icon name="add-circle" class="hover" />
  235. <t-dropdown-menu>
  236. <t-dropdown-item
  237. key="custom"
  238. value="custom"
  239. disabled="true"
  240. divider="true"
  241. class="input"
  242. >
  243. <t-input
  244. v-model="a.input"
  245. placeholder="自定义"
  246. @enter="
  247. onAddValue(a, { key: a.input });
  248. a.input = '';
  249. "
  250. />
  251. </t-dropdown-item>
  252. <t-dropdown-item
  253. v-for="prop in a.props"
  254. :key="prop.value"
  255. :value="prop.value"
  256. >
  257. {{ prop.label }}
  258. </t-dropdown-item>
  259. </t-dropdown-menu>
  260. </t-dropdown>
  261. </div>
  262. </div>
  263. <template
  264. v-if="Object.keys(a.value).length"
  265. class="center gray mt-8"
  266. >
  267. <div class="prop-grid mt-8" v-for="(value, key) in a.value">
  268. <div class="ml-8">
  269. <t-tooltip :content="key">
  270. {{ getPropDesc(a, key) }}
  271. </t-tooltip>
  272. </div>
  273. <div>
  274. <t-input v-model="a.value[key]" placeholder="值" />
  275. </div>
  276. <div class="right px-8" style="line-height: 20px">
  277. <t-icon
  278. name="delete"
  279. class="hover"
  280. @click="delete a.value[key]"
  281. />
  282. </div>
  283. </div>
  284. </template>
  285. <div v-else class="center gray mt-8">暂无数据</div>
  286. </div>
  287. </div>
  288. </template>
  289. <template v-else-if="a.action == 8 || a.action == 9 || a.action == 10">
  290. <div class="form-item mt-8">
  291. <label>对象类型</label>
  292. <t-radio-group v-model="a.targetType" @change="a.value = ''">
  293. <t-radio value="id">图元</t-radio>
  294. <t-radio value="tag">组</t-radio>
  295. </t-radio-group>
  296. </div>
  297. <div class="form-item mt-8">
  298. <label>播放对象</label>
  299. <t-tree-select
  300. v-if="a.targetType === 'id'"
  301. v-model="a.value"
  302. :data="penTree"
  303. filterable
  304. placeholder="默认自己"
  305. />
  306. <t-select
  307. v-else
  308. v-model="a.value"
  309. :options="groups"
  310. placeholder="组"
  311. />
  312. </div>
  313. </template>
  314. <template v-else-if="a.action == 5">
  315. <div class="form-item mt-8">
  316. <label>函数</label>
  317. <div class="w-full">
  318. <div>function javascriptFn(pen) {</div>
  319. <CodeEditor
  320. v-model="a.value"
  321. class="mt-4"
  322. style="height: 200px"
  323. />
  324. <div class="mt-4">}</div>
  325. </div>
  326. </div>
  327. </template>
  328. </div>
  329. </div>
  330. <div class="mt-8">
  331. <a @click="data.actions.push({})"> + 添加动作 </a>
  332. </div>
  333. </div>
  334. </template>
  335. <script lang="ts" setup>
  336. import { onBeforeMount, ref } from 'vue';
  337. import CodeEditor from '@/views/components/common/CodeEditor.vue';
  338. import Network from './Network.vue';
  339. import { getPenAnimations, getPenTree } from '@/services/common';
  340. const { data } = defineProps<{
  341. data: any;
  342. }>();
  343. const actionOptions = [
  344. {
  345. label: '打开链接',
  346. value: 0,
  347. },
  348. {
  349. label: '打开视图',
  350. value: 13,
  351. },
  352. {
  353. label: '播放动画',
  354. value: 2,
  355. },
  356. {
  357. label: '暂停动画',
  358. value: 3,
  359. },
  360. {
  361. label: '停止动画',
  362. value: 4,
  363. },
  364. {
  365. label: '更改属性',
  366. value: 1,
  367. },
  368. {
  369. label: '打开弹框',
  370. value: 14,
  371. },
  372. {
  373. label: '发送消息',
  374. value: 7,
  375. },
  376. {
  377. label: '发送数据',
  378. value: 15,
  379. },
  380. {
  381. label: '播放视频',
  382. value: 8,
  383. },
  384. {
  385. label: '暂停视频',
  386. value: 9,
  387. },
  388. {
  389. label: '停止视频',
  390. value: 10,
  391. },
  392. {
  393. label: '自定义函数',
  394. value: 5,
  395. },
  396. ];
  397. const penTree: any = ref([]);
  398. const groups: any = ref([]);
  399. const animations: any = ref([]);
  400. onBeforeMount(() => {
  401. if (!data.actions) {
  402. data.actions = [];
  403. }
  404. penTree.value = getPenTree();
  405. groups.value = [];
  406. const d = meta2d.store.data as any;
  407. if (d.groups) {
  408. for (const item of d.groups) {
  409. groups.value.push({ label: item, value: item });
  410. }
  411. }
  412. animations.value = getPenAnimations();
  413. });
  414. const getAnimations = (idOrTag: string) => {
  415. animations.value = getPenAnimations(idOrTag);
  416. };
  417. const onChangeAction = (action: any) => {
  418. switch (action.action) {
  419. case 0:
  420. action.value = '';
  421. action.params = '_blank';
  422. break;
  423. case 1:
  424. action.params = '';
  425. action.value = {};
  426. action.targetType = 'id';
  427. getProps(action);
  428. break;
  429. case 2:
  430. case 3:
  431. case 4:
  432. action.value = '';
  433. action.targetType = 'id';
  434. break;
  435. case 15:
  436. action.network = { options: {} };
  437. action.params = '';
  438. action.value = {};
  439. action.targetType = 'id';
  440. getProps(action);
  441. break;
  442. default:
  443. action.value = '';
  444. action.params = '';
  445. break;
  446. }
  447. };
  448. const getProps = (c: any) => {
  449. c.props = [
  450. {
  451. value: 'x',
  452. label: 'X',
  453. },
  454. {
  455. value: 'y',
  456. label: 'Y',
  457. },
  458. {
  459. value: 'width',
  460. label: '宽',
  461. },
  462. {
  463. value: 'height',
  464. label: '高',
  465. },
  466. {
  467. value: 'visible',
  468. label: '显示',
  469. },
  470. {
  471. value: 'text',
  472. label: '文字',
  473. },
  474. {
  475. value: 'progress',
  476. label: '进度',
  477. },
  478. {
  479. value: 'showChild',
  480. label: '状态',
  481. },
  482. {
  483. value: 'rotate',
  484. label: '旋转',
  485. },
  486. ];
  487. let target: any;
  488. if (c.params) {
  489. target = meta2d.findOne(c.params);
  490. } else if (meta2d.store.active) {
  491. target = meta2d.store.active[0];
  492. }
  493. if (target) {
  494. for (const item of target.realTimes) {
  495. const found = c.props.findIndex((elem: any) => elem.value === item.key);
  496. if (found < 0) {
  497. c.props.push({
  498. value: item.key,
  499. label: item.label,
  500. });
  501. }
  502. }
  503. }
  504. };
  505. const getPropDesc = (a: any, key: any) => {
  506. const found = a.props.find((elem: any) => elem.value === key);
  507. if (found) {
  508. return found.label;
  509. }
  510. return key;
  511. };
  512. const onAddValue = (action: any, data: any) => {
  513. if (!action.value[data.key]) {
  514. action.value[data.key] = undefined;
  515. }
  516. };
  517. </script>
  518. <style lang="postcss" scoped>
  519. .props {
  520. .prop-grid {
  521. display: grid;
  522. grid-template-columns: 2fr 3fr 32px;
  523. line-height: 30px;
  524. &.head {
  525. background: var(--color-background-input);
  526. padding: 0 8px;
  527. }
  528. }
  529. }
  530. </style>