create.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <template>
  2. <div class="create">
  3. <div class="breadcrumb">
  4. <ul>
  5. <li v-for="({ name, path }, i) in breadcrumbList" :key="name">
  6. <span v-if="i !== 0" class="separator">></span>
  7. <span :class="['breadcrumb-name', { pointer: path }]" @click="path ? $router.push(path) : ''">
  8. {{ name }}
  9. </span>
  10. </li>
  11. </ul>
  12. </div>
  13. <div class="basic-info">
  14. <div class="basic-info-title">基本信息</div>
  15. <el-form ref="form" :model="form" :rules="formRules" label-width="80px">
  16. <el-form-item label="封面" prop="picture_url">
  17. <el-upload
  18. class="cover-uploader"
  19. action="none"
  20. :show-file-list="false"
  21. :http-request="uploadCover"
  22. :before-upload="beforeCoverUpload"
  23. >
  24. <img v-if="form.picture_url" :src="form.picture_url" class="cover" />
  25. <div v-else class="cover-uploader-icon">
  26. <i class="el-icon-plus"></i>
  27. <span>点击上传封面</span>
  28. </div>
  29. </el-upload>
  30. <div class="tips">支持jpg、png格式图片,大小不超过5mb。</div>
  31. </el-form-item>
  32. <el-form-item label="书籍名称" prop="name">
  33. <el-input v-model="form.name" placeholder="请输入内容" :maxlength="100" />
  34. </el-form-item>
  35. <el-form-item label="作者" prop="author">
  36. <el-input v-model="form.author" placeholder="请输入内容" :maxlength="20" />
  37. </el-form-item>
  38. <el-form-item label="现价" prop="price">
  39. <el-input v-model="form.price" placeholder="请输入内容" @input="handlePrice($event, 'price')">
  40. <template slot="append">元</template>
  41. </el-input>
  42. </el-form-item>
  43. <el-form-item label="原价" prop="price_old">
  44. <el-input v-model="form.price_old" placeholder="请输入内容" @input="handlePrice($event, 'price_old')">
  45. <template slot="append">元</template>
  46. </el-input>
  47. </el-form-item>
  48. <el-form-item label="标签" prop="label_name_list">
  49. <el-select
  50. v-model="form.label_name_list"
  51. class="label-select"
  52. multiple
  53. filterable
  54. allow-create
  55. default-first-option
  56. placeholder="请输入标签,回车确认"
  57. />
  58. </el-form-item>
  59. <el-form-item label="分类" prop="type_id">
  60. <el-select v-model="form.type_id" placeholder="选择分类">
  61. <el-option v-for="{ id: typeId, name } in type_list" :key="typeId" :label="name" :value="typeId" />
  62. </el-select>
  63. </el-form-item>
  64. <el-form-item label="简介" prop="description">
  65. <el-input
  66. v-model="form.description"
  67. type="textarea"
  68. :autosize="{ minRows: 12 }"
  69. :maxlength="500"
  70. show-word-limit
  71. placeholder="请输入更多内容"
  72. />
  73. </el-form-item>
  74. <el-form-item>
  75. <el-button type="primary" @click="addBook">确定</el-button>
  76. <el-button @click="$router.push('/')">取消</el-button>
  77. </el-form-item>
  78. </el-form>
  79. </div>
  80. </div>
  81. </template>
  82. <script>
  83. import { fileUpload } from '@/api/app';
  84. import { GetBook, UpdateBook, AddBook, GetBookTypeList } from '@/api/book';
  85. import { twoDecimal } from '@/utils/validate';
  86. export default {
  87. name: 'CreateBookPage',
  88. data() {
  89. return {
  90. book_id: this.$route.query.book_id,
  91. form: {
  92. picture_url: '',
  93. picture_id: '',
  94. name: '',
  95. author: '',
  96. price: '',
  97. price_old: '',
  98. label_name_list: '',
  99. type_id: '',
  100. description: '',
  101. },
  102. formRules: {
  103. picture_url: [{ required: true, message: '请上传封面', trigger: 'blur' }],
  104. name: [{ required: true, message: '请输入书籍名称', trigger: 'blur' }],
  105. author: [{ required: true, message: '请输入作者', trigger: 'blur' }],
  106. price: [{ required: true, message: '请输入现价', trigger: 'blur' }],
  107. type_id: [{ required: true, message: '请选择分类', trigger: 'blur' }],
  108. description: [{ required: true, message: '请输入简介', trigger: 'blur' }],
  109. },
  110. type_list: [],
  111. breadcrumbList: [
  112. { name: '教材管理', path: '/home' },
  113. { name: '新建教材', path: '' },
  114. { name: '基本信息', path: '' },
  115. ],
  116. };
  117. },
  118. created() {
  119. if (this.book_id) {
  120. this.getBookDetail();
  121. }
  122. GetBookTypeList().then(({ type_list }) => {
  123. this.type_list = type_list;
  124. });
  125. },
  126. methods: {
  127. uploadCover(file) {
  128. fileUpload('Mid', file, { isGlobalprogress: true }).then(({ file_info_list }) => {
  129. if (file_info_list.length > 0) {
  130. const { file_url, file_id } = file_info_list[0];
  131. this.form.picture_url = file_url;
  132. this.form.picture_id = file_id;
  133. }
  134. });
  135. },
  136. beforeCoverUpload(file) {
  137. const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
  138. if (!isJPG) {
  139. this.$message.error('上传封面图片只能是 JPG 或 PNG 格式!');
  140. return false;
  141. }
  142. const isLt5M = file.size / 1024 / 1024 < 5;
  143. if (!isLt5M) {
  144. this.$message.error('上传封面图片大小不能超过 5MB!');
  145. return false;
  146. }
  147. },
  148. /**
  149. * @description 处理价格输入
  150. * @param {string | number} val 输入的值
  151. * @param {price | price_old} type 输入的类型
  152. */
  153. handlePrice(val, type) {
  154. this.form[type] = twoDecimal(val);
  155. },
  156. addBook() {
  157. this.$refs.form.validate((valid) => {
  158. if (valid) {
  159. if (this.book_id) {
  160. this.updateBook();
  161. } else {
  162. AddBook({ ...this.form, sys_version_type: 1 }).then(({ id }) => {
  163. this.$router.push(`/book/setting/${id}`);
  164. });
  165. }
  166. } else {
  167. return false;
  168. }
  169. });
  170. },
  171. getBookDetail() {
  172. GetBook({ id: this.book_id }).then(
  173. ({ name, picture_id, picture_url, author, type_id, price, price_old, label_name_list, description }) => {
  174. this.form = {
  175. name,
  176. picture_id,
  177. picture_url,
  178. author,
  179. type_id,
  180. price,
  181. price_old,
  182. label_name_list,
  183. description,
  184. };
  185. },
  186. );
  187. },
  188. updateBook() {
  189. UpdateBook({ id: this.book_id, ...this.form })
  190. .then(() => {
  191. this.$router.push(`/book/setting/${this.book_id}`);
  192. })
  193. .catch(() => {});
  194. },
  195. },
  196. };
  197. </script>
  198. <style lang="scss" scoped>
  199. .create {
  200. padding: 8px 24px;
  201. .breadcrumb {
  202. display: flex;
  203. align-items: center;
  204. > ul {
  205. display: flex;
  206. li {
  207. font-size: 14px;
  208. font-weight: 400;
  209. color: $font-light-color;
  210. .separator {
  211. margin: 0 8px;
  212. color: #c9cdd4;
  213. }
  214. &:nth-last-child(1) {
  215. font-weight: bold;
  216. color: $font-color;
  217. }
  218. }
  219. }
  220. }
  221. .basic-info {
  222. width: 1200px;
  223. padding: 24px;
  224. margin: 24px auto 16px;
  225. background-color: #fff;
  226. border-radius: 4px;
  227. &-title {
  228. margin-bottom: 24px;
  229. font-size: 18px;
  230. font-weight: bold;
  231. }
  232. .el-form {
  233. .el-input,
  234. .el-textarea,
  235. .el-select {
  236. width: 400px;
  237. :deep .el-input__inner,
  238. :deep .el-textarea__inner {
  239. background-color: #fff;
  240. border-color: #dcdcdc;
  241. }
  242. }
  243. .cover-uploader {
  244. :deep img {
  245. max-width: 228px;
  246. max-height: 320px;
  247. }
  248. :deep .el-upload {
  249. position: relative;
  250. overflow: hidden;
  251. cursor: pointer;
  252. border: 1px dashed #d9d9d9;
  253. border-radius: 6px;
  254. &:hover {
  255. border-color: #409eff;
  256. }
  257. }
  258. &-icon {
  259. display: flex;
  260. flex-direction: column;
  261. row-gap: 4px;
  262. align-items: center;
  263. justify-content: center;
  264. width: 228px;
  265. height: 320px;
  266. font-size: 12px;
  267. color: #8c939d;
  268. background-color: #eee;
  269. .el-icon-plus {
  270. font-size: 16px;
  271. font-weight: bold;
  272. color: #000;
  273. }
  274. }
  275. .avatar {
  276. display: block;
  277. width: 178px;
  278. height: 178px;
  279. }
  280. }
  281. .label-select {
  282. :deep .el-input__suffix {
  283. display: none;
  284. }
  285. }
  286. .tips {
  287. margin-top: -4px;
  288. font-size: 12px;
  289. color: #8c8c8c;
  290. }
  291. &-item {
  292. margin-bottom: 24px;
  293. }
  294. }
  295. }
  296. }
  297. </style>
  298. <style lang="scss">
  299. .el-select-dropdown.el-popper.is-multiple {
  300. display: none;
  301. .el-select-dropdown__empty {
  302. display: none;
  303. }
  304. }
  305. </style>