GuidebookCreateDialog.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <div>
  3. <q-dialog
  4. v-model="dialogOpen"
  5. :maximized="maximizedToggle"
  6. transition-show="slide-up"
  7. transition-hide="slide-down"
  8. >
  9. <q-card class="bg-cyan-1 text-black">
  10. <q-bar>
  11. <q-space />
  12. <q-btn
  13. dense
  14. flat
  15. icon="minimize"
  16. @click="maximizedToggle = false"
  17. :disable="!maximizedToggle"
  18. >
  19. <q-tooltip v-if="maximizedToggle" class="bg-white text-primary"
  20. >Minimize</q-tooltip
  21. >
  22. </q-btn>
  23. <q-btn
  24. dense
  25. flat
  26. icon="crop_square"
  27. @click="maximizedToggle = true"
  28. :disable="maximizedToggle"
  29. >
  30. <q-tooltip v-if="!maximizedToggle" class="bg-white text-primary"
  31. >Maximize</q-tooltip
  32. >
  33. </q-btn>
  34. <q-btn dense flat icon="close" v-close-popup>
  35. <q-tooltip class="bg-white text-primary">Close</q-tooltip>
  36. </q-btn>
  37. </q-bar>
  38. <q-card-section>
  39. <div class="text-h6">创建攻略书</div>
  40. </q-card-section>
  41. <q-card-section>
  42. <div style="width: 100vw" class="row justify-center">
  43. <div class="col-8">
  44. <q-input
  45. outlined
  46. class="col-8"
  47. label="头图URL"
  48. v-model="coverImageUrl"
  49. />
  50. </div>
  51. <div class="col-8">
  52. <img
  53. v-if="coverImageUrl != ''"
  54. style="height: 240px; width: 290px"
  55. :src="coverImageUrl"
  56. />
  57. </div>
  58. <div class="col-8">
  59. <q-input
  60. outlined
  61. class="col-8"
  62. label="下载地址"
  63. v-model="downloadUrl"
  64. />
  65. </div>
  66. <div class="col-8">
  67. <q-select
  68. outlined
  69. use-input
  70. input-debounce="100"
  71. @filter="filterFn"
  72. v-model="bindedDestination"
  73. :options="destinations"
  74. label="目的地"
  75. />
  76. </div>
  77. <div class="col-8">
  78. <q-input
  79. v-model="shortDescription"
  80. filled
  81. label="简述"
  82. type="textarea"
  83. />
  84. </div>
  85. <div class="col-8">
  86. <q-btn
  87. v-if="mode != 'edit'"
  88. label="提交"
  89. @click="submitNewGuidebook"
  90. color="primary"
  91. />
  92. <q-btn
  93. v-if="mode == 'edit'"
  94. label="更新"
  95. @click="submitUpdateGuidebook"
  96. color="primary"
  97. />
  98. </div>
  99. </div>
  100. </q-card-section>
  101. </q-card>
  102. </q-dialog>
  103. </div>
  104. </template>
  105. <script>
  106. import { api } from "boot/axios";
  107. import { useQuasar } from "quasar";
  108. export default {
  109. name: "GuideBookCreateComponent",
  110. setup() {
  111. const $q = useQuasar();
  112. return {
  113. showNotifyMessageFail(msg) {
  114. $q.notify({
  115. message: msg,
  116. color: "red",
  117. position: "top-right",
  118. });
  119. },
  120. showNotifyMessageSucceed(msg) {
  121. $q.notify({
  122. message: msg,
  123. color: "green",
  124. position: "top-right",
  125. });
  126. },
  127. showFullPageLoading() {
  128. this.disableAction = true;
  129. $q.loading.show();
  130. },
  131. hideFullPageLoading() {
  132. $q.loading.hide();
  133. this.disableAction = false;
  134. },
  135. };
  136. },
  137. mounted() {
  138. this.loadAllDestinationOption();
  139. },
  140. methods: {
  141. filterFn(val, update) {
  142. if (val === "") {
  143. update(() => {
  144. this.destinations = this.destinationsbak;
  145. });
  146. return;
  147. }
  148. update(() => {
  149. const needle = val.toLowerCase();
  150. this.destinations = this.destinationsbak.filter(
  151. (v) => v.label.toLowerCase().indexOf(needle) > -1
  152. );
  153. });
  154. },
  155. loadAllDestinationOption() {
  156. var params = {};
  157. params.page = -1;
  158. params.pageSize = 100;
  159. params.query = "";
  160. params.level = -1;
  161. var storeThis = this;
  162. api
  163. .get("/api/v1/destination", {
  164. params: params,
  165. })
  166. .then((response) => {
  167. this.destinations = [];
  168. for (var i in response.data.data.data) {
  169. var obj = {};
  170. obj.label = response.data.data.data[i].destinationName;
  171. obj.value = response.data.data.data[i].destinationId;
  172. this.destinations.push(obj);
  173. }
  174. this.destinationsbak = this.destinations;
  175. console.log("parent destination candidates:");
  176. console.log(this.destinations);
  177. })
  178. .catch((e) => {
  179. console.log(e);
  180. storeThis.showNotifyMessageFail(e.response);
  181. });
  182. },
  183. clearForm() {
  184. this.coverImageUrl = "";
  185. this.downloadUrl = "";
  186. this.shortDescription = "";
  187. this.bindedDestination = "";
  188. },
  189. validateParams() {
  190. if (this.coverImageUrl == null || this.coverImageUrl == "") {
  191. this.showNotifyMessageFail("封面图不得为空");
  192. return false;
  193. }
  194. if (this.downloadUrl == null || this.downloadUrl == "") {
  195. this.showNotifyMessageFail("下载链接不得为空");
  196. return false;
  197. }
  198. if (this.bindedDestination == null || this.bindedDestination == "") {
  199. this.showNotifyMessageFail("目的地不得为空");
  200. return false;
  201. }
  202. if (this.shortDescription == null || this.shortDescription == "") {
  203. this.showNotifyMessageFail("简述不得为空");
  204. return false;
  205. }
  206. return true;
  207. },
  208. submitUpdateGuidebook() {
  209. var params = {};
  210. params.destinationId = this.bindedDestination.value;
  211. params.coverImageUrl = this.coverImageUrl;
  212. params.shortDescription = this.shortDescription;
  213. params.downloadUrl = this.downloadUrl;
  214. if (!this.validateParams()) {
  215. return;
  216. }
  217. api
  218. .put("/api/v1/guidebook/" + this.focusedGuideId, params)
  219. .then((response) => {
  220. console.log(response.data);
  221. if (response.data.ok === true) {
  222. this.showNotifyMessageSucceed(response.data.message);
  223. this.dialogOpen = false;
  224. this.$emit("close-me-event");
  225. } else {
  226. this.showNotifyMessageFail(response.data.message);
  227. }
  228. })
  229. .catch((e) => {
  230. storeThis.showNotifyMessageFail(e.toString());
  231. });
  232. },
  233. submitNewGuidebook() {
  234. var params = {};
  235. params.destinationId = this.bindedDestination.value;
  236. params.coverImageUrl = this.coverImageUrl;
  237. params.shortDescription = this.shortDescription;
  238. params.downloadUrl = this.downloadUrl;
  239. if (!this.validateParams()) {
  240. return;
  241. }
  242. api
  243. .post("/api/v1/guidebook", params)
  244. .then((response) => {
  245. console.log(response.data);
  246. if (response.data.ok === true) {
  247. this.showNotifyMessageSucceed(response.data.message);
  248. this.dialogOpen = false;
  249. this.$emit("close-me-event");
  250. } else {
  251. this.showNotifyMessageFail(response.data.message);
  252. }
  253. })
  254. .catch((e) => {
  255. storeThis.showNotifyMessageFail(e.toString());
  256. });
  257. },
  258. toggleDialog() {
  259. this.mode = "";
  260. this.clearForm();
  261. this.dialogOpen = true;
  262. },
  263. toggleDialogEditMode(guideId) {
  264. this.clearForm();
  265. this.dialogOpen = true;
  266. this.focusedGuideId = guideId;
  267. this.loadDetailByGuideId(guideId);
  268. this.mode = "edit";
  269. },
  270. loadDetailByGuideId(guideId) {
  271. var storeThis = this;
  272. api
  273. .get("/api/v1/guidebook/" + guideId)
  274. .then((response) => {
  275. if (response.data.ok === true) {
  276. console.log("guide book detail: ");
  277. console.log(response.data.data);
  278. this.coverImageUrl = response.data.data.coverImageUrl;
  279. this.downloadUrl = response.data.data.downloadUrl;
  280. this.bindedDestination = response.data.data.destinationId;
  281. this.bindedDestination = response.data.data.destinationId;
  282. var filteredDestinations = this.destinationsbak.filter((item) => {
  283. return item.value == response.data.data.destinationId;
  284. });
  285. this.bindedDestination = filteredDestinations[0];
  286. this.shortDescription = response.data.data.shortDescription;
  287. } else {
  288. this.showNotifyMessageFail(response.data.message);
  289. }
  290. })
  291. .catch((e) => {
  292. console.log(e);
  293. storeThis.showNotifyMessageFail(e.response);
  294. });
  295. },
  296. },
  297. data() {
  298. return {
  299. focusedGuideId: "",
  300. mode: "",
  301. shortDescription: "",
  302. downloadUrl: "",
  303. destinations: [],
  304. destinationsbak: [],
  305. bindedDestination: "",
  306. coverImageUrl: "",
  307. maximizedToggle: true,
  308. dialogOpen: false,
  309. };
  310. },
  311. };
  312. </script>