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

362 lines
9.1 KiB

  1. <template>
  2. <!-- 新建作品页面 -->
  3. <view class="create-novel">
  4. <uv-navbar
  5. title="新建作品"
  6. :autoBack="true"
  7. fixed
  8. placeholder
  9. titleStyle="color: #333; font-weight: 500;"
  10. :border="false"
  11. ></uv-navbar>
  12. <view class="form-container">
  13. <!-- 封面信息 -->
  14. <view class="section">
  15. <view class="section-title">封面信息</view>
  16. <view class="upload-cover">
  17. <view class="sub-title">上传封面</view>
  18. <view class="cover-box" @click="chooseCover">
  19. <image v-if="formData.cover" :src="formData.cover" mode="aspectFill" class="cover-image"></image>
  20. <view v-else class="upload-placeholder">
  21. <text class="plus">+</text>
  22. </view>
  23. </view>
  24. </view>
  25. </view>
  26. <!-- 作品信息 -->
  27. <view class="section">
  28. <view class="section-title">作品信息</view>
  29. <view class="form-item">
  30. <text class="required">*</text>
  31. <text class="label">作品名称</text>
  32. <input
  33. type="text"
  34. v-model="formData.title"
  35. placeholder="请输入"
  36. placeholder-class="input-placeholder"
  37. />
  38. </view>
  39. <view class="form-item">
  40. <text class="required">*</text>
  41. <text class="label">作品类型</text>
  42. <input
  43. type="text"
  44. v-model="formData.type"
  45. placeholder="请输入"
  46. placeholder-class="input-placeholder"
  47. />
  48. </view>
  49. <view class="form-item">
  50. <text class="required">*</text>
  51. <text class="label">作品简介</text>
  52. <textarea
  53. v-model="formData.description"
  54. placeholder="请输入"
  55. placeholder-class="input-placeholder"
  56. :maxlength="500"
  57. ></textarea>
  58. </view>
  59. <view class="form-item">
  60. <text class="required">*</text>
  61. <text class="label">作品状态</text>
  62. <view class="status-options">
  63. <view
  64. class="status-item"
  65. :class="{ active: formData.status === 'serial' }"
  66. @click="formData.status = 'serial'"
  67. >
  68. <view class="radio-dot" :class="{ checked: formData.status === 'serial' }"></view>
  69. <text>连载</text>
  70. </view>
  71. <view
  72. class="status-item"
  73. :class="{ active: formData.status === 'completed' }"
  74. @click="formData.status = 'completed'"
  75. >
  76. <view class="radio-dot" :class="{ checked: formData.status === 'completed' }"></view>
  77. <text>完结</text>
  78. </view>
  79. </view>
  80. </view>
  81. </view>
  82. <!-- 书籍信息 -->
  83. <view class="section">
  84. <view class="section-title">书籍信息</view>
  85. <view class="form-item">
  86. <text class="label">书号</text>
  87. <text class="value">9999993339393</text>
  88. </view>
  89. <view class="form-item">
  90. <text class="label">总字数</text>
  91. <text class="value">99999999</text>
  92. </view>
  93. </view>
  94. <!-- 提交按钮 -->
  95. <view class="submit-btn" @click="submitForm">提交申请</view>
  96. </view>
  97. </view>
  98. </template>
  99. <script>
  100. export default {
  101. components: {
  102. 'uv-navbar': () => import('@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue')
  103. },
  104. data() {
  105. return {
  106. formData: {
  107. cover: '',
  108. title: '',
  109. type: '',
  110. description: '',
  111. status: 'serial' // 默认连载
  112. }
  113. }
  114. },
  115. methods: {
  116. // 选择封面
  117. chooseCover() {
  118. uni.chooseImage({
  119. count: 1,
  120. success: (res) => {
  121. this.formData.cover = res.tempFilePaths[0]
  122. }
  123. })
  124. },
  125. // 提交表单
  126. submitForm() {
  127. if (!this.formData.title) {
  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.description) {
  142. uni.showToast({
  143. title: '请输入作品简介',
  144. icon: 'none'
  145. })
  146. return
  147. }
  148. // 构建作品数据
  149. const workData = {
  150. id: Date.now().toString(),
  151. title: this.formData.title,
  152. cover: this.formData.cover || 'https://bookcover.yuewen.com/qdbimg/349573/1033014772/150.webp',
  153. type: this.formData.type,
  154. description: this.formData.description,
  155. status: this.formData.status,
  156. readers: '0',
  157. publishStatus: '发布审核中',
  158. isOriginal: true,
  159. chapters: [],
  160. author: '当前用户', // 添加作者信息
  161. tags: [this.formData.type], // 添加标签
  162. updateTime: new Date().getTime() // 添加更新时间
  163. }
  164. // 获取现有的作品列表
  165. let worksList = uni.getStorageSync('worksList') || []
  166. // 添加新作品
  167. worksList.unshift(workData) // 使用unshift确保新作品显示在最前面
  168. // 保存到本地存储
  169. uni.setStorageSync('worksList', worksList)
  170. // 保存到全局状态
  171. getApp().globalData.submittedWork = workData
  172. // 设置需要显示提交成功提示的标记
  173. getApp().globalData.showSubmitSuccess = true
  174. // 显示成功提示
  175. uni.showToast({
  176. title: '创建成功',
  177. icon: 'success'
  178. })
  179. // 延迟返回上一页
  180. setTimeout(() => {
  181. // 先保存当前要显示的标签
  182. uni.setStorageSync('activeBookshelfTab', 'work')
  183. // 返回上一页
  184. uni.navigateBack({
  185. delta: 1
  186. })
  187. }, 500)
  188. }
  189. }
  190. }
  191. </script>
  192. <style lang="scss">
  193. .create-novel {
  194. min-height: 100vh;
  195. background-color: #F8F8F8;
  196. .form-container {
  197. padding: 20rpx;
  198. .section {
  199. background-color: #FFFFFF;
  200. border-radius: 12rpx;
  201. padding: 30rpx;
  202. margin-bottom: 20rpx;
  203. .section-title {
  204. font-size: 32rpx;
  205. font-weight: bold;
  206. color: #333;
  207. margin-bottom: 30rpx;
  208. }
  209. .upload-cover {
  210. .sub-title {
  211. font-size: 28rpx;
  212. color: #666;
  213. margin-bottom: 20rpx;
  214. }
  215. .cover-box {
  216. width: 200rpx;
  217. height: 266rpx;
  218. background-color: #F5F5F5;
  219. border-radius: 8rpx;
  220. display: flex;
  221. align-items: center;
  222. justify-content: center;
  223. overflow: hidden;
  224. .cover-image {
  225. width: 100%;
  226. height: 100%;
  227. }
  228. .upload-placeholder {
  229. .plus {
  230. font-size: 60rpx;
  231. color: #999;
  232. }
  233. }
  234. }
  235. }
  236. .form-item {
  237. margin-bottom: 30rpx;
  238. position: relative;
  239. &:last-child {
  240. margin-bottom: 0;
  241. }
  242. .required {
  243. color: #FF0000;
  244. margin-right: 4rpx;
  245. }
  246. .label {
  247. font-size: 28rpx;
  248. color: #333;
  249. margin-bottom: 16rpx;
  250. display: block;
  251. }
  252. input, textarea {
  253. width: 100%;
  254. height: 80rpx;
  255. background-color: #F5F5F5;
  256. border-radius: 8rpx;
  257. padding: 20rpx;
  258. font-size: 28rpx;
  259. color: #333;
  260. box-sizing: border-box;
  261. position: relative;
  262. z-index: 1;
  263. }
  264. textarea {
  265. height: 200rpx;
  266. }
  267. .input-placeholder {
  268. color: #999;
  269. }
  270. .status-options {
  271. display: flex;
  272. gap: 40rpx;
  273. .status-item {
  274. display: flex;
  275. align-items: center;
  276. gap: 10rpx;
  277. .radio-dot {
  278. width: 32rpx;
  279. height: 32rpx;
  280. border: 2rpx solid #999;
  281. border-radius: 50%;
  282. position: relative;
  283. &.checked {
  284. border-color: #001351;
  285. &::after {
  286. content: '';
  287. position: absolute;
  288. width: 20rpx;
  289. height: 20rpx;
  290. background-color: #001351;
  291. border-radius: 50%;
  292. left: 50%;
  293. top: 50%;
  294. transform: translate(-50%, -50%);
  295. }
  296. }
  297. }
  298. text {
  299. font-size: 28rpx;
  300. color: #333;
  301. }
  302. }
  303. }
  304. .value {
  305. font-size: 28rpx;
  306. color: #999;
  307. }
  308. }
  309. }
  310. .submit-btn {
  311. background-color: #001351;
  312. color: #FFFFFF;
  313. font-size: 32rpx;
  314. text-align: center;
  315. padding: 24rpx 0;
  316. border-radius: 12rpx;
  317. margin-top: 40rpx;
  318. &:active {
  319. opacity: 0.9;
  320. }
  321. }
  322. }
  323. }
  324. </style>