Upload.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. <script setup lang="ts">
  2. import { ref, reactive, watch, computed } from "vue";
  3. import { useMainStore } from "@/stores/main";
  4. import { required } from "@/utils";
  5. import { useI18n } from "vue-i18n";
  6. import { wsUrl } from "@/env";
  7. import type { VideoCreate } from "@/interfaces";
  8. import type { VideoUploaded } from "@/interfaces";
  9. import router from "@/router";
  10. import Dialog from "@/components/Dialog.vue";
  11. const { t } = useI18n();
  12. const mainStore = useMainStore();
  13. const WS = mainStore.videosWebSocket;
  14. const valid = ref(true);
  15. const title = ref("");
  16. const zipFiles = ref();
  17. const Form = ref();
  18. let anchor = ref(0);
  19. let templateId = ref(0);
  20. let selectAnchor = ref("angela");
  21. let selectTemplate = ref("style1");
  22. // props
  23. let dialog = reactive({
  24. msg: "",
  25. state: "info",
  26. show: false,
  27. });
  28. const anchorList = reactive([
  29. {
  30. anchor_id: "african2",
  31. name: "African",
  32. },
  33. {
  34. anchor_id: "blonde1",
  35. name: "Blonde-1",
  36. },
  37. {
  38. anchor_id: "blonde2",
  39. name: "Blonde-2",
  40. },
  41. {
  42. anchor_id: "blonde3",
  43. name: "Blonde-3",
  44. },
  45. {
  46. anchor_id: "victoria",
  47. name: "Victoria",
  48. },
  49. {
  50. anchor_id: "odelia-1",
  51. name: "Odelia-1",
  52. },
  53. {
  54. anchor_id: "odelia-2",
  55. name: "Odelia-2",
  56. },
  57. {
  58. anchor_id: "odelia-3",
  59. name: "Odelia-3",
  60. },
  61. {
  62. anchor_id: "hannah-1",
  63. name: "Hannah-1",
  64. },
  65. {
  66. anchor_id: "hannah-2",
  67. name: "Hannah-2",
  68. },
  69. {
  70. anchor_id: "nelly",
  71. name: "Nelly",
  72. },
  73. {
  74. anchor_id: "teresa2",
  75. name: "Teresa-2",
  76. },
  77. {
  78. anchor_id: "zoya1",
  79. name: "Zoya-1",
  80. },
  81. {
  82. anchor_id: "zoya2",
  83. name: "Zoya-2",
  84. },
  85. {
  86. anchor_id: "aima",
  87. name: "Aima",
  88. },
  89. {
  90. anchor_id: "alitia",
  91. name: "Alitia",
  92. },
  93. {
  94. anchor_id: "cora",
  95. name: "Cora",
  96. },
  97. // {
  98. // anchor_id: "elara",
  99. // name: "Elara",
  100. // },
  101. // {
  102. // anchor_id: "sporty",
  103. // name: "Sporty",
  104. // },
  105. // {
  106. // anchor_id: "angela",
  107. // name: "Angela",
  108. // },
  109. // {
  110. // anchor_id: "jocelyn",
  111. // name: "Jocelyn",
  112. // },
  113. // {
  114. // anchor_id: "summer",
  115. // name: "Summer",
  116. // },
  117. // {
  118. // anchor_id: "peggy",
  119. // name: "Peggy",
  120. // },
  121. // {
  122. // anchor_id: "角色1",
  123. // name: "友量主播-01",
  124. // },
  125. // {
  126. // anchor_id: "角色2",
  127. // name: "友量主播-02",
  128. // },
  129. // {
  130. // anchor_id: "itri-1",
  131. // name: "ITRI-1",
  132. // },
  133. // {
  134. // anchor_id: "itri-2",
  135. // name: "ITRI-2",
  136. // },
  137. // {
  138. // anchor_id: "itri-3",
  139. // name: "ITRI-3",
  140. // },
  141. // {
  142. // anchor_id: "syscom",
  143. // name: "James Liu",
  144. // },
  145. // {
  146. // anchor_id: "星展1",
  147. // name: "星展",
  148. // },
  149. ]);
  150. const templateList = reactive([
  151. {
  152. template_id: "style13",
  153. img: "鏡面-13",
  154. },
  155. {
  156. template_id: "style12",
  157. img: "鏡面-12",
  158. },
  159. {
  160. template_id: "style11",
  161. img: "鏡面-11",
  162. },
  163. {
  164. template_id: "style10",
  165. img: "鏡面-10",
  166. },
  167. {
  168. template_id: "style9",
  169. img: "鏡面-09",
  170. },
  171. {
  172. template_id: "style8",
  173. img: "鏡面-08",
  174. },
  175. {
  176. template_id: "style5",
  177. img: "鏡面-05",
  178. },
  179. {
  180. template_id: "style4",
  181. img: "鏡面-04",
  182. },
  183. {
  184. template_id: "style3",
  185. img: "鏡面-03",
  186. },
  187. {
  188. template_id: "style2",
  189. img: "鏡面-02",
  190. },
  191. {
  192. template_id: "style1",
  193. img: "鏡面-01",
  194. },
  195. // {
  196. // template_id: "ITRI_1",
  197. // img: "ITRI背景-1",
  198. // },
  199. // {
  200. // template_id: "ITRI_2",
  201. // img: "ITRI背景-2",
  202. // },
  203. // {
  204. // template_id: "ITRI_3",
  205. // img: "ITRI背景-3",
  206. // },
  207. // {
  208. // template_id: "ITRI_4",
  209. // img: "ITRI背景-4",
  210. // },
  211. // {
  212. // template_id: "ITRI_5",
  213. // img: "ITRI背景-5",
  214. // },
  215. // {
  216. // template_id: "ITRI_6",
  217. // img: "ITRI背景-6",
  218. // },
  219. // {
  220. // template_id: "ITRI_7",
  221. // img: "ITRI背景-7",
  222. // },
  223. // {
  224. // template_id: "ITRI_8",
  225. // img: "ITRI背景-8",
  226. // },
  227. // {
  228. // template_id: "ITRI_9",
  229. // img: "ITRI背景-9",
  230. // },
  231. // {
  232. // template_id: "ITRI_10",
  233. // img: "ITRI背景-10",
  234. // },
  235. {
  236. template_id: "syscom",
  237. img: "syscom",
  238. },
  239. {
  240. template_id: "凌群2",
  241. img: "syscom-2",
  242. },
  243. // {
  244. // template_id: "星展1",
  245. // img: "星展",
  246. // },
  247. ]);
  248. let anchorLang = ref("中文");
  249. let items = reactive([
  250. { lang: "中文", id: 0 },
  251. { lang: "英文", id: 1 },
  252. ]);
  253. // 取得圖片路徑
  254. const getImageUrl = (imgFolder: string, name: string) => {
  255. return new URL(`../../assets/img/${imgFolder}/${name}.webp`, import.meta.url)
  256. .href;
  257. };
  258. watch(dialog, (newVal) => {
  259. if (!newVal.show && newVal.state === "error") {
  260. return;
  261. } else if (!newVal.show && newVal.state === "success") {
  262. router.push("/main/progress");
  263. }
  264. });
  265. watch(anchor, (newVal) => {
  266. selectAnchor.value = anchorList[newVal].anchor_id;
  267. console.log("selectAnchor", selectAnchor.value);
  268. });
  269. watch(templateId, (newVal) => {
  270. selectTemplate.value = templateList[newVal].template_id;
  271. });
  272. async function submit() {
  273. WS.send("subscribe");
  274. await (Form as any).value.validate();
  275. if (valid.value) {
  276. valid.value = false;
  277. const video_data: VideoCreate = {
  278. title: title.value,
  279. anchor: selectAnchor.value,
  280. style: selectTemplate.value,
  281. lang: "zh",
  282. };
  283. const ret: VideoUploaded = await mainStore.uploadPlot(
  284. video_data,
  285. zipFiles.value[0]
  286. );
  287. if (ret.accepted) {
  288. dialog.msg = t("acceptZipMessage");
  289. dialog.state = "success";
  290. dialog.show = true;
  291. } else {
  292. dialog.msg = ret.error_message!;
  293. dialog.state = "error";
  294. dialog.show = true;
  295. }
  296. valid.value = true;
  297. // (Form as any).value.reset();
  298. }
  299. }
  300. </script>
  301. <template>
  302. <v-container fluid>
  303. <v-card class="ma-3 pa-3">
  304. <v-card-title primary-title>
  305. <h3 class="card-title mb-3">{{ t("makeVideo") }}</h3>
  306. </v-card-title>
  307. <v-card-text>
  308. <v-form v-model="valid" ref="Form">
  309. <v-text-field
  310. :label="$t('videoTitle')"
  311. v-model="title"
  312. :rules="required()"
  313. prepend-icon="title"
  314. >
  315. </v-text-field>
  316. <v-file-input
  317. v-model="zipFiles"
  318. :rules="[(v) => v.length || 'select zip file.']"
  319. accept=".zip"
  320. :label="$t('fileInput')"
  321. prepend-icon="folder_zip"
  322. ></v-file-input>
  323. <div class="mb-5 ms-10">
  324. <router-link to="/main/generate-zip"
  325. >還沒有準備好 ZIP 檔案?請點此製作素材</router-link
  326. >
  327. </div>
  328. <!-- <v-select
  329. v-model="anchorLang"
  330. :items="items"
  331. item-title="lang"
  332. item-value="id"
  333. prepend-icon="language"
  334. label="選擇語言"
  335. ></v-select> -->
  336. </v-form>
  337. <v-expansion-panels class="anchor-list">
  338. <v-expansion-panel title="選擇主播">
  339. <v-expansion-panel-text class="p-0">
  340. <v-item-group mandatory v-model="anchor">
  341. <v-container fluid>
  342. <ul>
  343. <li v-for="n in anchorList" :key="n.anchor_id">
  344. <v-item v-slot="{ isSelected, toggle }">
  345. <v-card
  346. :color="isSelected ? 'primary' : ''"
  347. class="d-flex flex-column align-center"
  348. dark
  349. @click="toggle"
  350. :title="n.name"
  351. >
  352. <v-scroll-y-transition>
  353. <!-- <div v-if="n.anchor_id !== 0" class="img-disabled">
  354. <img
  355. :src="getImageUrl('anchor', n.name)"
  356. alt=""
  357. />
  358. <p>Coming Soon</p>
  359. </div> -->
  360. <img :src="getImageUrl('anchor', n.name)" alt="" />
  361. </v-scroll-y-transition>
  362. </v-card>
  363. </v-item>
  364. </li>
  365. </ul>
  366. </v-container>
  367. </v-item-group>
  368. </v-expansion-panel-text>
  369. </v-expansion-panel>
  370. </v-expansion-panels>
  371. <v-expansion-panels class="template-list mt-6">
  372. <v-expansion-panel title="選擇模板">
  373. <v-expansion-panel-text class="p-0">
  374. <v-sheet class="mx-auto">
  375. <v-slide-group
  376. v-model="templateId"
  377. selected-class="bg-primary"
  378. show-arrows
  379. >
  380. <v-slide-group-item
  381. v-for="n in templateList"
  382. :key="n.template_id"
  383. v-slot="{ isSelected, toggle, selectedClass }"
  384. >
  385. <v-card
  386. color="grey-lighten-1"
  387. :class="['ma-4', selectedClass]"
  388. @click="toggle"
  389. >
  390. <span
  391. class="choose-btn"
  392. :class="{ 'active-color': isSelected }"
  393. >
  394. <v-icon icon="done" color="white" />
  395. </span>
  396. <img :src="getImageUrl('template', n.img)" alt="" />
  397. <!-- <div :class="{ 'img-disabled': n.template_id !== 0 }">
  398. <img :src="getImageUrl('template', n.img)" alt="" />
  399. <p v-if="n.template_id !== 0">Coming Soon</p>
  400. </div> -->
  401. </v-card>
  402. </v-slide-group-item>
  403. </v-slide-group>
  404. </v-sheet>
  405. </v-expansion-panel-text>
  406. </v-expansion-panel>
  407. </v-expansion-panels>
  408. </v-card-text>
  409. <v-card-actions>
  410. <v-spacer></v-spacer>
  411. <v-btn @click="submit" :disabled="!valid" variant="outlined">
  412. {{ t("send") }}
  413. </v-btn>
  414. </v-card-actions>
  415. </v-card>
  416. <v-card class="ma-3 pa-3 mt-8">
  417. <v-card-title primary-title>
  418. <h3 class="text-center">使用教學</h3>
  419. </v-card-title>
  420. <v-card-text>
  421. <!-- <v-container>
  422. <v-row no-gutters class="step-list">
  423. <v-col cols="12" sm="3">
  424. <v-sheet class="ma-2 pa-2">
  425. <h4>1. 取得快速製作模板</h4>
  426. <p class="excerpt">請點擊下方按鈕取得模板範例</p>
  427. <div class="mb-5">
  428. <a :href="'/example/影片範例.zip'" class="link-btn" download
  429. >點我下載</a
  430. >
  431. </div>
  432. </v-sheet>
  433. </v-col>
  434. <v-col cols="12" sm="3">
  435. <v-sheet class="ma-2 pa-2"> </v-sheet>
  436. </v-col>
  437. <v-col cols="12" sm="3">
  438. <v-sheet class="ma-2 pa-2"> </v-sheet>
  439. </v-col>
  440. <v-col cols="12" sm="3">
  441. <v-sheet class="ma-2 pa-2"> </v-sheet>
  442. </v-col>
  443. <v-col cols="12" sm="3">
  444. <v-sheet class="ma-2 pa-2"> </v-sheet>
  445. </v-col>
  446. </v-row>
  447. </v-container> -->
  448. <ul class="mt-5 step-list">
  449. <li>
  450. <h4>1. 取得快速製作模板</h4>
  451. <p class="excerpt">請點擊下方按鈕取得模板範例</p>
  452. <div class="mb-5">
  453. <a :href="'/example/影片範例_0719.zip'" class="link-btn" download
  454. >點我下載</a
  455. >
  456. </div>
  457. </li>
  458. <li>
  459. <h4>2. 準備影片內容</h4>
  460. <p class="excerpt text-center">
  461. 範例的資料夾內,有 "素材資料夾" 跟 "EXCEL 檔" <br />
  462. (您也可以自行創建資料夾)
  463. </p>
  464. <img src="@/assets/img/step/step-01.png" alt="" class="mb-4" />
  465. <p class="excerpt">素材資料夾裡面放照片或影片</p>
  466. <img src="@/assets/img/step/step-02.png" alt="" />
  467. <small class="d-block ms-4 mb-6"
  468. >包含內容:圖片/影片(.jpg/.mp4)</small
  469. >
  470. <p class="mt-15 text-h5">影片內容要放哪些好?</p>
  471. <p class="mt-3 mb-15 text-h5">
  472. 請參考
  473. <router-link to="/main/knowledge-graph" class="font-weight-bold"
  474. >熱搜關聯分析</router-link
  475. >
  476. </p>
  477. <p class="mb-5 pt-5 text-h6 excerpt">
  478. EXCEL 檔整理成這個格式-大標、字幕、素材、發音
  479. </p>
  480. <img src="@/assets/img/step/step-03.png" alt="" />
  481. <div class="point-content">
  482. <div class="base">
  483. <h5>基礎應用:</h5>
  484. <ul>
  485. <li>
  486. 1. 字幕之間的斷句請使用符號【\】進行換行 (建議每 10
  487. 個字就要 使用往左邊倒的斜線\換行)
  488. </li>
  489. <li>2. 大標字數勿超過中文 15 字、英文 30 字</li>
  490. <li>3. 發音請留空白</li>
  491. </ul>
  492. </div>
  493. <div class="advanced">
  494. <h5>進階應用:發音</h5>
  495. <p>發音欄為修正聲音用。 尤其中文一字多音,特別會需要修正發音</p>
  496. <p class="my-5">
  497. 寫法如下:<br />
  498. <strong>{"一":"1","二":"2"}</strong>
  499. </p>
  500. <p class="mb-5">
  501. 解說:<br />
  502. <strong
  503. >{"字幕寫法"對應"正確發音","字幕寫法"對應"正確發音"}</strong
  504. >
  505. <br />
  506. 使用破音字方法撰寫
  507. </p>
  508. <p>範例圖:</p>
  509. <img class="my-5" src="@/assets/img/step/example.jpg" alt="" />
  510. <p class="mb-5">
  511. 「重」塑品牌形象 & 成「為」品牌經營的特點<br />
  512. 「重」本應發音"從"但系統唸成"眾" &
  513. 「為」本應發音"維"但系統唸成"味"
  514. <br />
  515. 就要寫成{"重":"從","為":"位"}
  516. </p>
  517. <strong>注意**符號一律使用英文小寫</strong>
  518. </div>
  519. </div>
  520. <!-- <ul class="point-list">
  521. <li>
  522. 1. 字幕之間的斷句請使用符號【\】進行換行
  523. <br />
  524. (建議 10 個字內,若超過請使用換行符號)
  525. </li>
  526. <li>2. 大標字數勿超過中文 15 字、英文 30 字</li>
  527. <li>3. 音檔請留空白</li>
  528. </ul> -->
  529. <p class="mt-5 excerpt">以下為顯示效果:</p>
  530. <img src="@/assets/img/step/step-04.png" alt="" />
  531. <p class="mt-5 excerpt">
  532. 接下來同時選素材資料夾跟 EXCEL 檔,壓縮成 ZIP 檔
  533. </p>
  534. <img src="@/assets/img/step/step-05.png" alt="" class="my-5" />
  535. </li>
  536. <li>
  537. <h4>3. 上傳 ZIP 資料夾至 AI Spokesgirl 平台</h4>
  538. <p class="excerpt">影片檔名請寫上影片名稱</p>
  539. <img src="@/assets/img/step/step-06.png" alt="" />
  540. <h4 class="my-5 caption">
  541. 點選“送出”之後需等待一段影片製作的時間 <br />
  542. 請您耐心等候,待製作完畢可於影片清單查看
  543. </h4>
  544. </li>
  545. </ul>
  546. </v-card-text>
  547. </v-card>
  548. <template>
  549. <div class="text-center">
  550. <Dialog
  551. :msg="dialog.msg"
  552. :state="dialog.state"
  553. :dialog="dialog.show"
  554. @close="dialog.show = false"
  555. ></Dialog>
  556. </div>
  557. </template>
  558. </v-container>
  559. </template>
  560. <style lang="scss" scoped>
  561. a {
  562. letter-spacing: 1px;
  563. }
  564. .anchor-list {
  565. ul {
  566. display: grid;
  567. grid-template-columns: repeat(auto-fit, minmax(185px, max-content));
  568. grid-gap: 20px;
  569. justify-content: center;
  570. padding: initial;
  571. li {
  572. list-style-type: none;
  573. }
  574. }
  575. img {
  576. width: 190px;
  577. height: 155px;
  578. object-fit: cover;
  579. }
  580. .v-card--variant-elevated {
  581. box-shadow: 0px 2px 5px 1px
  582. var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, 0.2)),
  583. 0px 1px 1px 0px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.14)),
  584. 0px 1px 3px 0px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.12));
  585. }
  586. .v-card-item {
  587. padding: 0;
  588. text-align: center;
  589. .v-card-title {
  590. font-size: 18px;
  591. }
  592. }
  593. .bg-success {
  594. background: linear-gradient(
  595. -225deg,
  596. rgb(234, 84, 19) 35%,
  597. rgb(178, 69, 146) 100%
  598. ) !important;
  599. }
  600. .v-expansion-panel-text__wrapper {
  601. padding: 0 !important;
  602. }
  603. }
  604. .anchor-list,
  605. .template-list {
  606. padding-left: 40px;
  607. .v-expansion-panel-title {
  608. height: 55px;
  609. min-height: 0;
  610. }
  611. }
  612. .template-list {
  613. img {
  614. width: 100%;
  615. height: 200px;
  616. }
  617. .choose-btn {
  618. padding: 5px;
  619. position: absolute;
  620. right: 8px;
  621. bottom: 13px;
  622. background: #ccc;
  623. border-radius: 100px;
  624. }
  625. .active-color {
  626. background: #ea5413;
  627. }
  628. }
  629. .step-list {
  630. list-style: none;
  631. img {
  632. width: 100%;
  633. max-width: 1000px;
  634. }
  635. li {
  636. display: flex;
  637. flex-direction: column;
  638. align-items: center;
  639. font-size: 16px;
  640. p {
  641. line-height: 32px;
  642. }
  643. h4 {
  644. margin: 20px auto;
  645. color: #ea5413;
  646. font-weight: bold;
  647. text-align: center;
  648. line-height: 34px;
  649. font-size: 20px;
  650. }
  651. }
  652. .link-btn {
  653. display: inline-block;
  654. padding: 12px 20px;
  655. margin-top: 25px;
  656. border-radius: 100px;
  657. text-decoration: none;
  658. color: #fff;
  659. background: #ea5413;
  660. transition: all 0.3s;
  661. &:hover {
  662. opacity: 0.8;
  663. }
  664. }
  665. .point-list {
  666. display: flex;
  667. flex-direction: column;
  668. align-items: baseline;
  669. margin-left: 40px;
  670. }
  671. .point-content {
  672. .base,
  673. .advanced {
  674. padding: 40px;
  675. margin-top: 50px;
  676. max-width: 1000px;
  677. letter-spacing: 1px;
  678. border-radius: 5px;
  679. }
  680. .base {
  681. border: 4px solid #ea5413;
  682. }
  683. .advanced {
  684. border: 4px dashed #ea5413;
  685. }
  686. ul {
  687. display: flex;
  688. flex-direction: column;
  689. align-items: flex-start;
  690. li {
  691. margin: 5px 0;
  692. }
  693. }
  694. h5 {
  695. margin-bottom: 20px;
  696. text-align: center;
  697. font-size: 1.25rem;
  698. }
  699. hr {
  700. margin: 30px;
  701. border-color: #f2f2f2;
  702. opacity: 0.3;
  703. }
  704. }
  705. .excerpt::before {
  706. content: "";
  707. font-weight: bold;
  708. display: inline-block;
  709. border: 5px solid #ea5413;
  710. border-radius: 20px;
  711. margin-right: 10px;
  712. margin-bottom: 2px;
  713. }
  714. }
  715. .img-disabled {
  716. position: relative;
  717. z-index: 999;
  718. background-color: #ccc;
  719. margin-bottom: -5px;
  720. img {
  721. opacity: 0.7;
  722. }
  723. p {
  724. position: absolute;
  725. top: 50%;
  726. left: 50%;
  727. color: #fff;
  728. transform: translate(-50%, -50%);
  729. font-size: 16px;
  730. text-align: center;
  731. letter-spacing: 1px;
  732. text-shadow: 2px 2px 6px #000;
  733. }
  734. }
  735. .v-card--disabled > :not(.v-card__loader) {
  736. opacity: 1 !important;
  737. }
  738. </style>