小说小程序前端代码仓库(小程序)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
7.2 KiB

  1. <template>
  2. <!-- 新建作品页面 -->
  3. <view class="create-novel">
  4. <navbar title="新建作品" leftClick @leftClick="$utils.navigateBack" />
  5. <view class="form-container">
  6. <!-- 封面信息 -->
  7. <view class="section">
  8. <view class="section-title">封面信息</view>
  9. <view class="upload-cover">
  10. <view class="sub-title">上传封面</view>
  11. <view class="cover-box" @click="chooseCover">
  12. <image v-if="formData.Image" :src="formData.Image" mode="aspectFill" class="cover-image">
  13. </image>
  14. <view v-else class="upload-placeholder">
  15. <text class="plus">+</text>
  16. </view>
  17. </view>
  18. </view>
  19. </view>
  20. <!-- 作品信息 -->
  21. <view class="section">
  22. <view class="section-title">作品信息</view>
  23. <view class="form-item">
  24. <view style="display: flex;">
  25. <text class="required">*</text>
  26. <text class="label">作品名称</text>
  27. </view>
  28. <input type="text" v-model="formData.name" placeholder="请输入"
  29. placeholder-class="input-placeholder" />
  30. </view>
  31. <view class="form-item">
  32. <view style="display: flex;">
  33. <text class="required">*</text>
  34. <text class="label">作品类型</text>
  35. </view>
  36. <input type="text"
  37. disabled
  38. v-model="formData.type" placeholder="请输入"
  39. placeholder-class="input-placeholder" />
  40. </view>
  41. <view class="form-item">
  42. <view style="display: flex;">
  43. <text class="required">*</text>
  44. <text class="label">作品简介</text>
  45. </view>
  46. <textarea v-model="formData.details" placeholder="请输入" placeholder-class="input-placeholder"
  47. :maxlength="500"></textarea>
  48. </view>
  49. <view class="form-item">
  50. <view style="display: flex;">
  51. <text class="required">*</text>
  52. <text class="label">作品状态</text>
  53. </view>
  54. <view class="status-options">
  55. <view class="status-item" :class="{ active: formData.status == '0' }"
  56. @click="formData.status = '0'">
  57. <view class="radio-dot" :class="{ checked: formData.status == '0' }"></view>
  58. <text>连载</text>
  59. </view>
  60. <view class="status-item" :class="{ active: formData.status == '1' }"
  61. @click="formData.status = '1'">
  62. <view class="radio-dot" :class="{ checked: formData.status == '1' }"></view>
  63. <text>完结</text>
  64. </view>
  65. </view>
  66. </view>
  67. </view>
  68. <!-- 书籍信息 -->
  69. <view class="section" v-if="formData.id">
  70. <view class="section-title">书籍信息</view>
  71. <view class="form-item">
  72. <text class="label">书号</text>
  73. <text class="value">9999993339393</text>
  74. </view>
  75. <view class="form-item">
  76. <text class="label">总字数</text>
  77. <text class="value">99999999</text>
  78. </view>
  79. </view>
  80. <!-- 提交按钮 -->
  81. <view class="submit-btn" @click="submitForm">提交申请</view>
  82. </view>
  83. </view>
  84. </template>
  85. <script>
  86. export default {
  87. data() {
  88. return {
  89. formData: {
  90. Image: '',
  91. title: '',
  92. type: '1',
  93. details: '',
  94. status: '0' // 默认连载
  95. },
  96. id: 0
  97. }
  98. },
  99. onLoad(options) {
  100. if (options.id) {
  101. this.id = options.id
  102. this.getBookInfo()
  103. }
  104. },
  105. methods: {
  106. getBookInfo() {
  107. this.$fetch('getBookDetail', {
  108. id : this.id
  109. }).then(res => {
  110. this.formData = res
  111. })
  112. },
  113. // 选择封面
  114. chooseCover() {
  115. uni.chooseImage({
  116. count: 1,
  117. success: (res) => {
  118. this.$Oss.ossUpload(res.tempFilePaths[0])
  119. .then(url => {
  120. this.formData.Image = url
  121. })
  122. }
  123. })
  124. },
  125. // 提交表单
  126. async submitForm() {
  127. if (!this.formData.name) {
  128. uni.showToast({
  129. title: '请输入作品名称',
  130. icon: 'none'
  131. })
  132. return
  133. }
  134. if (!this.formData.type) {
  135. uni.showToast({
  136. title: '请输入作品类型',
  137. icon: 'none'
  138. })
  139. return
  140. }
  141. if (!this.formData.details) {
  142. uni.showToast({
  143. title: '请输入作品简介',
  144. icon: 'none'
  145. })
  146. return
  147. }
  148. // 构建作品数据
  149. const workData = {
  150. name: this.formData.name,
  151. Image: this.formData.Image,
  152. type: this.formData.type,
  153. details: this.formData.details,
  154. status: this.formData.status || 0,
  155. }
  156. await this.$fetch('saveOrUpdateBook', workData)
  157. // 延迟返回上一页
  158. setTimeout(() => {
  159. // 先保存当前要显示的标签
  160. uni.setStorageSync('activeBookshelfTab', 'work')
  161. // 返回上一页
  162. uni.navigateBack({
  163. delta: 1
  164. })
  165. }, 500)
  166. }
  167. }
  168. }
  169. </script>
  170. <style lang="scss">
  171. .create-novel {
  172. min-height: 100vh;
  173. background-color: #F8F8F8;
  174. .form-container {
  175. padding: 20rpx;
  176. .section {
  177. background-color: #FFFFFF;
  178. border-radius: 12rpx;
  179. padding: 30rpx;
  180. margin-bottom: 20rpx;
  181. .section-title {
  182. font-size: 32rpx;
  183. font-weight: bold;
  184. color: #333;
  185. margin-bottom: 30rpx;
  186. }
  187. .upload-cover {
  188. .sub-title {
  189. font-size: 28rpx;
  190. color: #666;
  191. margin-bottom: 20rpx;
  192. }
  193. .cover-box {
  194. width: 200rpx;
  195. height: 266rpx;
  196. background-color: #F5F5F5;
  197. border-radius: 8rpx;
  198. display: flex;
  199. align-items: center;
  200. justify-content: center;
  201. overflow: hidden;
  202. .cover-image {
  203. width: 100%;
  204. height: 100%;
  205. }
  206. .upload-placeholder {
  207. .plus {
  208. font-size: 60rpx;
  209. color: #999;
  210. }
  211. }
  212. }
  213. }
  214. .form-item {
  215. margin-bottom: 30rpx;
  216. position: relative;
  217. &:last-child {
  218. margin-bottom: 0;
  219. }
  220. .required {
  221. color: #FF0000;
  222. margin-right: 4rpx;
  223. }
  224. .label {
  225. font-size: 28rpx;
  226. color: #333;
  227. margin-bottom: 16rpx;
  228. display: block;
  229. }
  230. input,
  231. textarea {
  232. width: 100%;
  233. height: 80rpx;
  234. background-color: #F5F5F5;
  235. border-radius: 8rpx;
  236. padding: 20rpx;
  237. font-size: 28rpx;
  238. color: #333;
  239. box-sizing: border-box;
  240. position: relative;
  241. z-index: 1;
  242. }
  243. textarea {
  244. height: 200rpx;
  245. }
  246. .input-placeholder {
  247. color: #999;
  248. }
  249. .status-options {
  250. display: flex;
  251. gap: 40rpx;
  252. .status-item {
  253. display: flex;
  254. align-items: center;
  255. gap: 10rpx;
  256. .radio-dot {
  257. width: 32rpx;
  258. height: 32rpx;
  259. border: 2rpx solid #999;
  260. border-radius: 50%;
  261. position: relative;
  262. &.checked {
  263. border-color: #001351;
  264. &::after {
  265. content: '';
  266. position: absolute;
  267. width: 20rpx;
  268. height: 20rpx;
  269. background-color: #001351;
  270. border-radius: 50%;
  271. left: 50%;
  272. top: 50%;
  273. transform: translate(-50%, -50%);
  274. }
  275. }
  276. }
  277. text {
  278. font-size: 28rpx;
  279. color: #333;
  280. }
  281. }
  282. }
  283. .value {
  284. font-size: 28rpx;
  285. color: #999;
  286. }
  287. }
  288. }
  289. .submit-btn {
  290. background-color: #001351;
  291. color: #FFFFFF;
  292. font-size: 32rpx;
  293. text-align: center;
  294. padding: 24rpx 0;
  295. border-radius: 12rpx;
  296. margin-top: 40rpx;
  297. &:active {
  298. opacity: 0.9;
  299. }
  300. }
  301. }
  302. }
  303. </style>