小说小程序前端代码仓库(小程序)
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.

327 lines
6.8 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. }
  97. },
  98. methods: {
  99. // 选择封面
  100. chooseCover() {
  101. uni.chooseImage({
  102. count: 1,
  103. success: (res) => {
  104. this.$Oss.ossUpload(res.tempFilePaths[0])
  105. .then(url => {
  106. this.formData.Image = url
  107. })
  108. }
  109. })
  110. },
  111. // 提交表单
  112. async submitForm() {
  113. if (!this.formData.name) {
  114. uni.showToast({
  115. title: '请输入作品名称',
  116. icon: 'none'
  117. })
  118. return
  119. }
  120. if (!this.formData.type) {
  121. uni.showToast({
  122. title: '请输入作品类型',
  123. icon: 'none'
  124. })
  125. return
  126. }
  127. if (!this.formData.details) {
  128. uni.showToast({
  129. title: '请输入作品简介',
  130. icon: 'none'
  131. })
  132. return
  133. }
  134. // 构建作品数据
  135. const workData = {
  136. name: this.formData.name,
  137. Image: this.formData.Image,
  138. type: this.formData.type,
  139. details: this.formData.details,
  140. status: this.formData.status,
  141. }
  142. await this.$fetch('saveOrUpdateBook', workData)
  143. // 延迟返回上一页
  144. setTimeout(() => {
  145. // 先保存当前要显示的标签
  146. uni.setStorageSync('activeBookshelfTab', 'work')
  147. // 返回上一页
  148. uni.navigateBack({
  149. delta: 1
  150. })
  151. }, 500)
  152. }
  153. }
  154. }
  155. </script>
  156. <style lang="scss">
  157. .create-novel {
  158. min-height: 100vh;
  159. background-color: #F8F8F8;
  160. .form-container {
  161. padding: 20rpx;
  162. .section {
  163. background-color: #FFFFFF;
  164. border-radius: 12rpx;
  165. padding: 30rpx;
  166. margin-bottom: 20rpx;
  167. .section-title {
  168. font-size: 32rpx;
  169. font-weight: bold;
  170. color: #333;
  171. margin-bottom: 30rpx;
  172. }
  173. .upload-cover {
  174. .sub-title {
  175. font-size: 28rpx;
  176. color: #666;
  177. margin-bottom: 20rpx;
  178. }
  179. .cover-box {
  180. width: 200rpx;
  181. height: 266rpx;
  182. background-color: #F5F5F5;
  183. border-radius: 8rpx;
  184. display: flex;
  185. align-items: center;
  186. justify-content: center;
  187. overflow: hidden;
  188. .cover-image {
  189. width: 100%;
  190. height: 100%;
  191. }
  192. .upload-placeholder {
  193. .plus {
  194. font-size: 60rpx;
  195. color: #999;
  196. }
  197. }
  198. }
  199. }
  200. .form-item {
  201. margin-bottom: 30rpx;
  202. position: relative;
  203. &:last-child {
  204. margin-bottom: 0;
  205. }
  206. .required {
  207. color: #FF0000;
  208. margin-right: 4rpx;
  209. }
  210. .label {
  211. font-size: 28rpx;
  212. color: #333;
  213. margin-bottom: 16rpx;
  214. display: block;
  215. }
  216. input,
  217. textarea {
  218. width: 100%;
  219. height: 80rpx;
  220. background-color: #F5F5F5;
  221. border-radius: 8rpx;
  222. padding: 20rpx;
  223. font-size: 28rpx;
  224. color: #333;
  225. box-sizing: border-box;
  226. position: relative;
  227. z-index: 1;
  228. }
  229. textarea {
  230. height: 200rpx;
  231. }
  232. .input-placeholder {
  233. color: #999;
  234. }
  235. .status-options {
  236. display: flex;
  237. gap: 40rpx;
  238. .status-item {
  239. display: flex;
  240. align-items: center;
  241. gap: 10rpx;
  242. .radio-dot {
  243. width: 32rpx;
  244. height: 32rpx;
  245. border: 2rpx solid #999;
  246. border-radius: 50%;
  247. position: relative;
  248. &.checked {
  249. border-color: #001351;
  250. &::after {
  251. content: '';
  252. position: absolute;
  253. width: 20rpx;
  254. height: 20rpx;
  255. background-color: #001351;
  256. border-radius: 50%;
  257. left: 50%;
  258. top: 50%;
  259. transform: translate(-50%, -50%);
  260. }
  261. }
  262. }
  263. text {
  264. font-size: 28rpx;
  265. color: #333;
  266. }
  267. }
  268. }
  269. .value {
  270. font-size: 28rpx;
  271. color: #999;
  272. }
  273. }
  274. }
  275. .submit-btn {
  276. background-color: #001351;
  277. color: #FFFFFF;
  278. font-size: 32rpx;
  279. text-align: center;
  280. padding: 24rpx 0;
  281. border-radius: 12rpx;
  282. margin-top: 40rpx;
  283. &:active {
  284. opacity: 0.9;
  285. }
  286. }
  287. }
  288. }
  289. </style>