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

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