master
yujialong 2 months ago
commit 43091ad9d3
  1. 12
      .editorconfig
  2. 7
      .eslintrc
  3. 8
      .gitignore
  4. 10
      babel.config.js
  5. 11
      config/dev.ts
  6. 75
      config/index.ts
  7. 37
      config/prod.ts
  8. 83
      package.json
  9. 14175
      pnpm-lock.yaml
  10. 40
      project.config.json
  11. 13
      project.tt.json
  12. 67
      src/app.config.ts
  13. 0
      src/app.less
  14. 67
      src/app.ts
  15. BIN
      src/assets/images.rar
  16. BIN
      src/assets/images/home.png
  17. BIN
      src/assets/images/home_active.png
  18. BIN
      src/assets/images/listen.png
  19. BIN
      src/assets/images/listen_active.png
  20. 34
      src/assets/images/service.svg
  21. BIN
      src/assets/images/store.png
  22. BIN
      src/assets/images/subscribe.png
  23. BIN
      src/assets/images/subscribe_active.png
  24. BIN
      src/assets/images/user.png
  25. BIN
      src/assets/images/user_active.png
  26. BIN
      src/assets/listen/music.png
  27. BIN
      src/assets/listen/musicListNext.png
  28. BIN
      src/assets/listen/next.png
  29. 127
      src/components/Popup/index.less
  30. 167
      src/components/Popup/index.tsx
  31. 82
      src/components/UserExchangeModal/index.less
  32. 198
      src/components/UserExchangeModal/index.tsx
  33. 34
      src/components/defaultPage1/index.less
  34. 30
      src/components/defaultPage1/index.tsx
  35. 35
      src/components/defaultPage2/index.less
  36. 31
      src/components/defaultPage2/index.tsx
  37. 36
      src/components/defaultPage3/index.less
  38. 14
      src/components/defaultPage3/index.tsx
  39. 88
      src/components/getPhoneModal/index.less
  40. 137
      src/components/getPhoneModal/index.tsx
  41. 61
      src/components/goToStoreModal/index.less
  42. 76
      src/components/goToStoreModal/index.tsx
  43. 17
      src/index.html
  44. 5
      src/pages/AudioInterface/index.config.ts
  45. 130
      src/pages/AudioInterface/index.less
  46. 257
      src/pages/AudioInterface/index.tsx
  47. 5
      src/pages/CollectionDetail/index.config.ts
  48. 169
      src/pages/CollectionDetail/index.less
  49. 200
      src/pages/CollectionDetail/index.tsx
  50. 8
      src/pages/DisplayVideo/index.config.tsx
  51. 101
      src/pages/DisplayVideo/index.less
  52. 402
      src/pages/DisplayVideo/index.tsx
  53. 5
      src/pages/Home/index.config.tsx
  54. 266
      src/pages/Home/index.less
  55. 432
      src/pages/Home/index.tsx
  56. 5
      src/pages/Listen/index.config.ts
  57. 197
      src/pages/Listen/index.less
  58. 314
      src/pages/Listen/index.tsx
  59. 19
      src/pages/ListenBookDisplay/index.tsx
  60. 5
      src/pages/ListenDetail/index.config.ts
  61. 189
      src/pages/ListenDetail/index.less
  62. 246
      src/pages/ListenDetail/index.tsx
  63. 5
      src/pages/ListenDisplay/index.config.ts
  64. 22
      src/pages/ListenDisplay/index.tsx
  65. 5
      src/pages/ListenRegion/index.config.ts
  66. 90
      src/pages/ListenRegion/index.less
  67. 169
      src/pages/ListenRegion/index.tsx
  68. 5
      src/pages/ListenSearch/index.config.ts
  69. 230
      src/pages/ListenSearch/index.less
  70. 201
      src/pages/ListenSearch/index.tsx
  71. 5
      src/pages/ListenType/MainType/index.config.ts
  72. 123
      src/pages/ListenType/MainType/index.less
  73. 275
      src/pages/ListenType/MainType/index.tsx
  74. 5
      src/pages/ListenType/SingleType/index.config.ts
  75. 108
      src/pages/ListenType/SingleType/index.less
  76. 235
      src/pages/ListenType/SingleType/index.tsx
  77. 5
      src/pages/SearchDetail/index.config.ts
  78. 230
      src/pages/SearchDetail/index.less
  79. 301
      src/pages/SearchDetail/index.tsx
  80. 5
      src/pages/SingleDetail/index.config.ts
  81. 195
      src/pages/SingleDetail/index.less
  82. 281
      src/pages/SingleDetail/index.tsx
  83. 5
      src/pages/Store/index.config.ts
  84. 35
      src/pages/Store/index.less
  85. 56
      src/pages/Store/index.tsx
  86. 5
      src/pages/Subscribe/index.config.ts
  87. 273
      src/pages/Subscribe/index.less
  88. 669
      src/pages/Subscribe/index.tsx
  89. 7
      src/pages/UserHome/UserPersonalInfo/index.config.ts
  90. 75
      src/pages/UserHome/UserPersonalInfo/index.less
  91. 157
      src/pages/UserHome/UserPersonalInfo/index.tsx
  92. 5
      src/pages/UserHome/UserSubscribe/index.config.ts
  93. 180
      src/pages/UserHome/UserSubscribe/index.less
  94. 139
      src/pages/UserHome/UserSubscribe/index.tsx
  95. 5
      src/pages/UserHome/index.config.ts
  96. 99
      src/pages/UserHome/index.less
  97. 210
      src/pages/UserHome/index.tsx
  98. 27
      tsconfig.json
  99. 20
      types/global.d.ts

@ -0,0 +1,12 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

@ -0,0 +1,7 @@
{
"extends": ["taro/react"],
"rules": {
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}

8
.gitignore vendored

@ -0,0 +1,8 @@
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store
.swc
project.private.config.json

@ -0,0 +1,10 @@
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro', {
framework: 'react',
ts: true
}]
]
}

@ -0,0 +1,11 @@
module.exports = {
env: {
NODE_ENV: '"development"'
},
defineConstants: {
},
mini: {},
h5: {
esnextModules: ['taro-ui']
}
}

@ -0,0 +1,75 @@
const config = {
projectName: 'FCF',
date: '2024-7-18',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [],
defineConstants: {
},
copy: {
patterns: [
],
options: {
}
},
framework: 'react',
compiler: 'webpack5',
cache: {
enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
},
mini: {
postcss: {
pxtransform: {
enable: true,
config: {
}
},
url: {
enable: true,
config: {
limit: 1024 // 设定转换尺寸上限
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
esnextModules: ['taro-ui'],
postcss: {
autoprefixer: {
enable: true,
config: {
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
}
}
module.exports = function (merge) {
if (process.env.NODE_ENV === 'development') {
return merge({}, config, require('./dev'))
}
return merge({}, config, require('./prod'))
}

@ -0,0 +1,37 @@
module.exports = {
env: {
NODE_ENV: '"production"'
},
defineConstants: {
},
mini: {},
h5: {
/**
* WebpackChain
* @docs https://github.com/neutrinojs/webpack-chain
*/
// webpackChain (chain) {
// /**
// * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
// * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
// */
// chain.plugin('analyzer')
// .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
// /**
// * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
// * @docs https://github.com/chrisvfritz/prerender-spa-plugin
// */
// const path = require('path')
// const Prerender = require('prerender-spa-plugin')
// const staticDir = path.join(__dirname, '..', 'dist')
// chain
// .plugin('prerender')
// .use(new Prerender({
// staticDir,
// routes: [ '/pages/index/index' ],
// postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
// }))
// }
}
}

@ -0,0 +1,83 @@
{
"name": "FCF",
"version": "1.0.0",
"private": true,
"description": "FCF",
"templateInfo": {
"name": "taro-ui",
"typescript": true,
"css": "Less",
"framework": "React"
},
"scripts": {
"build:weapp": "taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:jd": "taro build --type jd",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:jd": "npm run build:jd -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch"
},
"browserslist": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
],
"author": "",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@tarojs/components": "3.6.32",
"@tarojs/helper": "3.6.32",
"@tarojs/plugin-framework-react": "3.6.32",
"@tarojs/plugin-platform-alipay": "3.6.32",
"@tarojs/plugin-platform-h5": "3.6.32",
"@tarojs/plugin-platform-jd": "3.6.32",
"@tarojs/plugin-platform-qq": "3.6.32",
"@tarojs/plugin-platform-swan": "3.6.32",
"@tarojs/plugin-platform-tt": "3.6.32",
"@tarojs/plugin-platform-weapp": "3.6.32",
"@tarojs/react": "3.6.32",
"@tarojs/runtime": "3.6.32",
"@tarojs/shared": "3.6.32",
"@tarojs/taro": "3.6.32",
"lodash": "4.17.15",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"taro-ui": "^3.3.0"
},
"devDependencies": {
"@babel/core": "^7.8.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
"@tarojs/cli": "3.6.32",
"@tarojs/taro-loader": "3.6.32",
"@tarojs/webpack5-runner": "3.6.32",
"@types/node": "^18.15.11",
"@types/react": "^18.0.0",
"@types/webpack-env": "^1.13.6",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"babel-preset-taro": "3.6.32",
"eslint": "^8.12.0",
"eslint-config-taro": "3.6.32",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-react": "^7.8.2",
"eslint-plugin-react-hooks": "^4.2.0",
"postcss": "^8.4.18",
"react-refresh": "^0.11.0",
"stylelint": "9.3.0",
"ts-node": "^10.9.1",
"typescript": "^4.1.0",
"webpack": "^5.78.0"
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,40 @@
{
"miniprogramRoot": "dist/",
"projectname": "FCF",
"description": "FCF",
"appid": "wxc5c21dae2f45470e",
"setting": {
"urlCheck": true,
"es6": false,
"enhance": false,
"compileHotReLoad": false,
"postcss": false,
"preloadBackgroundData": false,
"minified": false,
"newFeature": true,
"autoAudits": false,
"coverView": true,
"showShadowRootInWxmlPanel": false,
"scopeDataCheck": false,
"useCompilerModule": false,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"compileType": "miniprogram",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {},
"libVersion": "3.5.0",
"srcMiniprogramRoot": "dist/",
"packOptions": {
"ignore": [],
"include": []
},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

@ -0,0 +1,13 @@
{
"miniprogramRoot": "./",
"projectname": "FCF",
"description": "FCF",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

@ -0,0 +1,67 @@
export default defineAppConfig({
pages: [
'pages/Home/index',
'pages/Subscribe/index',
'pages/Store/index',
'pages/UserHome/index',
'pages/UserHome/UserPersonalInfo/index',
'pages/UserHome/UserSubscribe/index',
'pages/CollectionDetail/index',
'pages/SingleDetail/index',
'pages/AudioInterface/index',
'pages/DisplayVideo/index',
'pages/SearchDetail/index',
'pages/Listen/index',
'pages/ListenType/MainType/index',
'pages/ListenType/SingleType/index',
'pages/ListenRegion/index',
'pages/ListenDetail/index',
'pages/ListenDisplay/index',
'pages/ListenSearch/index',
'pages/ListenBookDisplay/index',
],
tabBar: {
color: '#999',
selectedColor: '#333',
backgroundColor: '#fff',
borderStyle: 'black',
list: [
{
pagePath: 'pages/Home/index',
text: '首页',
iconPath: 'assets/images/home.png',
selectedIconPath: 'assets/images/home_active.png'
},
{
pagePath: 'pages/Subscribe/index',
text: '绘本',
iconPath: 'assets/images/subscribe.png',
selectedIconPath: 'assets/images/subscribe_active.png'
},
{
pagePath: 'pages/Listen/index',
text: '熏听',
iconPath: 'assets/images/listen.png',
selectedIconPath: 'assets/images/listen_active.png'
},
{
pagePath: 'pages/UserHome/index',
text: '我的',
iconPath: 'assets/images/user.png',
selectedIconPath: 'assets/images/user_active.png'
},
]
},
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
},
plugins: {
"player": {
"version": "2.5.2",
"provider": "wxa75efa648b60994b"
}
}
})

@ -0,0 +1,67 @@
import Taro, { setGlobalDataPlugin, useDidShow, useLaunch, useLoad, usePullDownRefresh } from '@tarojs/taro'
import { Component, PropsWithChildren, useEffect, useState } from 'react'
// import 'taro-ui/dist/style/index.scss'
import "taro-ui/dist/style/components/accordion.scss";
import "taro-ui/dist/style/components/icon.scss";
import './app.less'
export default function App(props: any) {
useDidShow(()=>{
console.log('进入小程序并登录')
Taro.login({
success:function(res) {
console.log('微信登录成功', res.code)
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/login',
data: {
CODE: res.code,
channel: 'wusehua_mini',
},
success: function(sres) {
console.log('静默授权登录成功', sres.data)
if(sres.data.state === 200){
Taro.setStorageSync('UserAvatar', sres.data.data.user.Avatar)
Taro.setStorageSync('UserNickName', sres.data.data.user.NickName)
Taro.setStorageSync('UserPhoneNumber', sres.data.data.user.Mobile)
Taro.setStorageSync('UserToken', sres.data.token)
}else{
//注册key
Taro.setStorageSync('LoginKey', sres.data.open_id)
}
}
})
}
})
})
useLaunch(()=>{
const updateManager = Taro.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
// console.log(res.hasUpdate)
})
updateManager.onUpdateReady(function () {
Taro.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新的版本下载失败
})
})
return (
props.children
)
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -0,0 +1,34 @@
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse opacity="0.1" cx="27" cy="28.5" rx="23" ry="18.5" fill="url(#paint0_linear_1339_10715)"/>
<ellipse cx="22" cy="22.5" rx="22" ry="18.5" fill="url(#paint1_linear_1339_10715)"/>
<circle cx="10.5" cy="30.5" r="1.5" fill="#3BA366"/>
<circle cx="5" cy="6" r="2.5" stroke="#FCCA1E" stroke-opacity="0.6"/>
<circle cx="46" cy="12" r="2" stroke="#3BA366" stroke-width="2"/>
<g clip-path="url(#clip0_1339_10715)">
<path d="M25 24C23.1435 24 21.363 23.2625 20.0503 21.9497C18.7375 20.637 18 18.8565 18 17C18 15.1435 18.7375 13.363 20.0503 12.0503C21.363 10.7375 23.1435 10 25 10C26.8565 10 28.637 10.7375 29.9497 12.0503C31.2625 13.363 32 15.1435 32 17C32 18.8565 31.2625 20.637 29.9497 21.9497C28.637 23.2625 26.8565 24 25 24ZM25 21C27.21 21 29 19.328 29 18.5C29 17.672 27.21 19 25 19C22.79 19 21 17.672 21 18.5C21 19.328 22.79 21 25 21Z" fill="#3BA366"/>
<path d="M25 24C23.1435 24 21.363 23.2625 20.0503 21.9497C18.7375 20.637 18 18.8565 18 17C18 15.1435 18.7375 13.363 20.0503 12.0503C21.363 10.7375 23.1435 10 25 10C26.8565 10 28.637 10.7375 29.9497 12.0503C31.2625 13.363 32 15.1435 32 17C32 18.8565 31.2625 20.637 29.9497 21.9497C28.637 23.2625 26.8565 24 25 24ZM25 21C27.21 21 29 19.328 29 18.5C29 17.672 27.21 19 25 19C22.79 19 21 17.672 21 18.5C21 19.328 22.79 21 25 21Z" fill="url(#paint2_linear_1339_10715)"/>
<path d="M29.8879 26.069C29.757 26.3881 29.5201 26.6523 29.2172 26.8172C28.9143 26.982 28.5638 27.0375 28.2248 26.9742C27.8858 26.9109 27.5789 26.7327 27.3559 26.4696C27.1329 26.2065 27.0074 25.8746 27.0004 25.5298C26.9935 25.185 27.1056 24.8483 27.3179 24.5765C27.5301 24.3047 27.8296 24.1143 28.1658 24.0374C28.502 23.9605 28.8544 24.0018 29.1637 24.1544C29.473 24.307 29.7203 24.5614 29.8639 24.875C32.1039 23.219 33.4999 20.491 33.4999 17.495C33.4999 12.523 29.6879 8.5 24.9999 8.5C20.3119 8.5 16.4999 12.522 16.4999 17.496C16.4997 18.5261 16.6665 19.5494 16.9939 20.526C17.0171 20.5887 17.0274 20.6554 17.0244 20.7222C17.0213 20.789 17.0049 20.8544 16.9761 20.9148C16.9473 20.9751 16.9067 21.029 16.8567 21.0734C16.8067 21.1177 16.7483 21.1516 16.685 21.173C16.6216 21.1944 16.5547 21.2029 16.488 21.198C16.4213 21.193 16.3563 21.1748 16.2968 21.1443C16.2374 21.1138 16.1846 21.0717 16.1417 21.0205C16.0987 20.9692 16.0665 20.9099 16.0469 20.846C15.9516 20.5644 15.8685 20.2788 15.7979 19.99C15.3217 19.9422 14.8785 19.7252 14.5487 19.3784C14.2188 19.0316 14.0243 18.5781 14.0003 18.1001C13.9764 17.6222 14.1246 17.1515 14.4181 16.7735C14.7116 16.3954 15.1309 16.1352 15.5999 16.04C16.2699 11.214 20.2179 7.5 24.9999 7.5C29.7819 7.5 33.7299 11.214 34.3999 16.04C34.8689 16.1354 35.2882 16.3958 35.5816 16.774C35.8749 17.1522 36.023 17.623 35.9988 18.101C35.9746 18.579 35.7797 19.0325 35.4497 19.3791C35.1196 19.7257 34.6762 19.9425 34.1999 19.99C33.5819 22.524 32.0349 24.712 29.8879 26.069Z" fill="#3BA366"/>
<path d="M29.8879 26.069C29.757 26.3881 29.5201 26.6523 29.2172 26.8172C28.9143 26.982 28.5638 27.0375 28.2248 26.9742C27.8858 26.9109 27.5789 26.7327 27.3559 26.4696C27.1329 26.2065 27.0074 25.8746 27.0004 25.5298C26.9935 25.185 27.1056 24.8483 27.3179 24.5765C27.5301 24.3047 27.8296 24.1143 28.1658 24.0374C28.502 23.9605 28.8544 24.0018 29.1637 24.1544C29.473 24.307 29.7203 24.5614 29.8639 24.875C32.1039 23.219 33.4999 20.491 33.4999 17.495C33.4999 12.523 29.6879 8.5 24.9999 8.5C20.3119 8.5 16.4999 12.522 16.4999 17.496C16.4997 18.5261 16.6665 19.5494 16.9939 20.526C17.0171 20.5887 17.0274 20.6554 17.0244 20.7222C17.0213 20.789 17.0049 20.8544 16.9761 20.9148C16.9473 20.9751 16.9067 21.029 16.8567 21.0734C16.8067 21.1177 16.7483 21.1516 16.685 21.173C16.6216 21.1944 16.5547 21.2029 16.488 21.198C16.4213 21.193 16.3563 21.1748 16.2968 21.1443C16.2374 21.1138 16.1846 21.0717 16.1417 21.0205C16.0987 20.9692 16.0665 20.9099 16.0469 20.846C15.9516 20.5644 15.8685 20.2788 15.7979 19.99C15.3217 19.9422 14.8785 19.7252 14.5487 19.3784C14.2188 19.0316 14.0243 18.5781 14.0003 18.1001C13.9764 17.6222 14.1246 17.1515 14.4181 16.7735C14.7116 16.3954 15.1309 16.1352 15.5999 16.04C16.2699 11.214 20.2179 7.5 24.9999 7.5C29.7819 7.5 33.7299 11.214 34.3999 16.04C34.8689 16.1354 35.2882 16.3958 35.5816 16.774C35.8749 17.1522 36.023 17.623 35.9988 18.101C35.9746 18.579 35.7797 19.0325 35.4497 19.3791C35.1196 19.7257 34.6762 19.9425 34.1999 19.99C33.5819 22.524 32.0349 24.712 29.8879 26.069Z" fill="url(#paint3_linear_1339_10715)"/>
</g>
<defs>
<linearGradient id="paint0_linear_1339_10715" x1="11.5" y1="14" x2="42" y2="42.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#FCCA1E" stop-opacity="0"/>
<stop offset="1" stop-color="#FCCA1E"/>
</linearGradient>
<linearGradient id="paint1_linear_1339_10715" x1="13.5" y1="8" x2="33" y2="37" gradientUnits="userSpaceOnUse">
<stop stop-color="#329C5E" stop-opacity="0"/>
<stop offset="1" stop-color="#3BA366" stop-opacity="0.3"/>
</linearGradient>
<linearGradient id="paint2_linear_1339_10715" x1="25.0003" y1="16.8206" x2="32.4406" y2="10.541" gradientUnits="userSpaceOnUse">
<stop stop-color="#FCCA1E" stop-opacity="0"/>
<stop offset="1" stop-color="#FCCA1E"/>
</linearGradient>
<linearGradient id="paint3_linear_1339_10715" x1="25" y1="17" x2="35.5" y2="7" gradientUnits="userSpaceOnUse">
<stop stop-color="#FCCA1E" stop-opacity="0"/>
<stop offset="1" stop-color="#FCCA1E"/>
</linearGradient>
<clipPath id="clip0_1339_10715">
<rect width="24" height="24" fill="white" transform="translate(13 5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

@ -0,0 +1,127 @@
@keyframes slideInFromBottom {
from {
bottom: -100%;
opacity: 0;
}
to {
bottom: 0;
opacity: 1;
}
}
.popup_overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
.popup_half_screen {
position: fixed;
bottom: 0; // 移动到屏幕底部
left: 0;
width: 100%;
height: 50%; // 占据屏幕高度的一半
background-color: white;
z-index: 1000;
overflow-y: auto;
// background-color: black;
border-radius: 1rem 1rem 0 0;
animation: slideInFromBottom .5s ease;
.popup_content {
padding: 1rem;
display: flex;
flex-direction: column;
gap: 1rem;
.popop_content_header {
width: 100%;
height: 2.75rem;
display: flex;
flex-direction: row;
.popup_content_header_icon {
width: 1.25rem;
height: .75rem;
margin: auto auto auto 0;
}
.popup_content_header_title {
margin: auto calc(50% - 1.125rem) auto 0;
font-weight: 600;
font-size: 1.125rem;
text-align: center;
width: auto;
}
}
.popup_content_body {
width: 100%;
height: calc(50vh - 2.75rem - 2.5rem - 4rem);
display: flex;
flex-direction: column;
.popup_content_body_item {
width: 100%;
height: auto;
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1rem;
.popup_content_body_item_title {
font-size: 1rem;
font-weight: 600;
}
.popup_content_body_item_group {
width: 100%;
height: auto;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
.popup_content_body_item_group_bar {
width: 100%;
height: 1.75rem;
border-radius: .5rem;
background: #f5f5f5;
display: flex;
.popup_content_body_item_group_bar_title {
text-align: center;
margin: auto;
}
}
}
}
}
.popup_content_footer {
width: 100%;
height: 2.5rem;
display: flex;
flex-direction: row;
gap: 10%;
.popup_content_footer_btn {
width: 45%;
height: 100%;
border-radius: 1.5rem;
display: flex;
.popup_content_footer_btn_text {
font-weight: 600;
font-size: 1.125rem;
text-align: center;
margin: auto;
}
}
}
}
}

@ -0,0 +1,167 @@
import { View, Text, Image, ScrollView } from '@tarojs/components';
import { useEffect, useState } from 'react';
import Taro from '@tarojs/taro';
import './index.less'
export default function PopupHalfScreen({ visible, onClose, isfilter, onFilter }) {
//弹窗内容数据
const [popUpContextList, setpopUpContextList] = useState<any[]>([])
//管理关闭动画状态
const [isAnimationOpen, setisAnimationOpen] = useState(false)
//本地记录筛选内容
const [userFilter, setuserFilter] = useState(0)
useEffect(() => {
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/filter',
method: 'POST',
header: {
authorization: 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
timestamp: Date.now(),
},
success: (res) => {
console.log('订阅筛选分类请求成功=>', res.data)
setpopUpContextList(res.data.data)
},
fail: (err) => {
console.log('订阅筛选分类请求失败=>', err)
}
})
}, [])
if (!visible) {
return null;
}
const handleOverlayClick = (event: any) => {
// 点击蒙层时关闭弹窗
setisAnimationOpen(true)
setTimeout(() =>{
setisAnimationOpen(false)
onClose();
}, 500)
};
const handleFilterSelect = (target: number) => {
if(isfilter === target){
// onFilter('')
setuserFilter(0)
}else{
// onFilter(target)
setuserFilter(target)
}
}
const handleReset = () => {
setuserFilter(0)
onFilter('reset')
handleOverlayClick(null)
}
const handleCommit = () => {
onFilter(userFilter)
handleOverlayClick(null)
}
return (
<>
<View
className='popup_overlay'
onClick={handleOverlayClick}
/>
<View
className='popup_half_screen'
onClick={onClose}
style={
!isAnimationOpen ? {} : {
bottom: '-100%',
transition: 'bottom 0.5s ease',
}
}
>
<View className='popup_content' onClick={(e) => e.stopPropagation()}>
{/* 弹窗内容 */}
<View className='popop_content_header'>
<Image
className='popup_content_header_icon'
src='https://oss.jm-kid.com/wx_5colorflower/foldUp.svg'
onClick={handleOverlayClick}
/>
<View className='popup_content_header_title'></View>
</View>
<ScrollView
className='popup_content_body'
scrollY
scrollWithAnimation
>
{
popUpContextList.map((item: any, index: number) => (
<View
className='popup_content_body_item'
key={index}
>
<Text className='popup_content_body_item_title'>{item.title}</Text>
<View className='popup_content_body_item_group'>
{
item.category.map((subItem: any, subIndex: number) => (
<View
className='popup_content_body_item_group_bar'
key={subIndex}
onClick={()=>handleFilterSelect(subItem.id)}
style={
userFilter === subItem.id ? {
backgroundColor: '#3BA366'
} : {}
}
>
<Text
className='popup_content_body_item_group_bar_title'
style={
userFilter === subItem.id ? {
color: '#ffffff'
} : {}
}
>{subItem.title}</Text>
</View>
))
}
</View>
</View>
))
}
</ScrollView>
<View className='popup_content_footer'>
<View
className='popup_content_footer_btn'
style={{background: '#3BA366'}}
onClick={handleReset}
>
<Text
className='popup_content_footer_btn_text'
style={{color: '#fff'}}
></Text>
</View>
<View
className='popup_content_footer_btn'
style={{background: '#FCCA1E'}}
onClick={handleCommit}
>
<Text
className='popup_content_footer_btn_text'
style={{color: '#000'}}
></Text>
</View>
</View>
</View>
</View>
</>
);
}

@ -0,0 +1,82 @@
.exchange_mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
.exchange_modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: calc(18rem - 2rem);
height: calc(15rem - 1.875rem);
background: #fff;
border-radius: 1rem;
display: flex;
flex-direction: column;
padding: .9375rem 1rem;
z-index: 1000;
gap: .5rem;
.exchange_header {
width: 100%;
height: 1.625rem;
display: flex;
.exchange_title {
font-weight: 600;
font-size: 1.125rem;
color: #000;
margin: auto auto auto 0;
}
.exchange_close {
width: 1.5rem;
height: 1.5rem;
margin: auto 0 auto auto;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/close.png);
background-size: cover;
background-repeat: no-repeat;
}
}
.exchange_scan {
width: 6rem;
height: 6rem;
border-radius: 3rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/exchangeScan.png);
background-size: cover;
background-repeat: no-repeat;
margin: 0 auto;
}
.exchange_input {
width: 100%;
height: 2rem;
margin: 0 auto;
background-color: #f8f8f8;
}
.exchange_exchange {
width: 10rem;
height: 2rem;
border-radius: 1rem;
background: linear-gradient(to right, #FCB11E, #FCCA1E);
margin: 0 auto;
display: flex;
.exchange_exchange_text {
width: auto;
font-size: 1rem;
font-weight: 600;
color: #000;
text-align: center;
margin: auto;
}
}
}

@ -0,0 +1,198 @@
import { useState } from 'react'
import Taro from '@tarojs/taro'
import { Input, View, Text } from '@tarojs/components'
import './index.less'
import GetPhoneNumber from '../getPhoneModal'
interface Props{
isOpen: boolean,
setIsOpen: (isOpen: boolean) => void
}
export default function UserExchangeModal({ isOpen, setIsOpen }: Props) {
const [inputValue, setinputValue] = useState('')
const [userScene, setuserScene] = useState<any>(null)
//管理登录弹窗
const [isGetUsePhone, setisGetUsePhone] = useState(false) //false
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
//唤起扫码
const handleScanCode = () => {
console.log('唤起扫码')
Taro.scanCode({
success: (res: any) => {
console.log(res.path.slice(-8))
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
setuserScene(res.path.slice(-8))
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/exchange',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
change_code: res.path.slice(-8)
},
success: (s_res: any) => {
console.log('兑换成功=>', s_res.data)
if(s_res.data.state === '200'){
let modalContent = '兑换成功:'
s_res.data.data.Subscribed.forEach(element => {
modalContent += `${element.PrdtTitle};`
})
Taro.showModal({
title: '兑换成功',
content: modalContent,
showCancel: true,
success: (modal_res) => {
setIsOpen(false)
if (modal_res.confirm) {
console.log('用户点击确定')
if(s_res.data.data.Subscribed[0].PrdtType === '03'){
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + s_res.data.data.Subscribed[0].PrdtId
})
}else if(s_res.data.data.Subscribed[0].PrdtType === '05'){
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + s_res.data.data.Subscribed[0].PrdtId
})
}
} else if (modal_res.cancel) {
console.log('用户点击取消')
}
}
})
}else if(s_res.data.state === '207'){
Taro.showToast({
title: '兑换码已使用',
icon: 'error'
})
}
},
fail: (err: any) => {
console.log('兑换失败=>', err)
}
})
}
}
})
}
const handleExchange = () => {
if(inputValue.length === 8){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/exchange',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
change_code: inputValue
},
success: (res: any) => {
console.log('兑换成功=>', res.data)
if(res.data.state === '200'){
let modalContent = '兑换成功:'
res.data.data.Subscribed.forEach(element => {
modalContent += `${element.PrdtTitle};`
})
console.log(modalContent)
Taro.showModal({
title: '兑换成功',
content: modalContent,
showCancel: true,
success: (modal_res) => {
setIsOpen(false)
if (modal_res.confirm) {
console.log('用户点击确定')
if(res.data.data.Subscribed[0].PrdtType === '03'){
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + res.data.data.Subscribed[0].PrdtId
})
}else if(res.data.data.Subscribed[0].PrdtType === '05'){
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + res.data.data.Subscribed[0].PrdtId
})
}
} else if (modal_res.cancel) {
console.log('用户点击取消')
}
}
})
}else if(res.data.state === '207'){
Taro.showToast({
title: '兑换码已使用',
icon: 'error'
})
}
},
fail: (err: any) => {
console.log('兑换失败=>', err)
}
})
}else{
Taro.showToast({
title: '兑换码格式错误',
icon: 'none'
})
}
}
if(!isOpen){
return null
}
return (
<>
<View
className='exchange_mask'
onClick={() => setIsOpen(false)}
></View>
<View className='exchange_modal'>
<View className='exchange_header'>
<View className='exchange_title'></View>
<View
className='exchange_close'
onClick={() => setIsOpen(false)}
></View>
</View>
<View
className='exchange_scan'
onClick={handleScanCode}
></View>
<Input
className='exchange_input'
placeholder='请输入兑换码兑换商品'
value={inputValue}
onInput={(e) => setinputValue(e.detail.value)}
></Input>
<View
className='exchange_exchange'
onClick={handleExchange}
>
<Text className='exchange_exchange_text'></Text>
</View>
</View>
<GetPhoneNumber
onClose={setisGetUsePhone}
scene={userScene}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
</>
)
}

@ -0,0 +1,34 @@
.default1_bg {
display: flex;
flex-direction: column;
margin: auto;
gap: 1.25rem;
.default1_img {
width: 15.625rem;
height: 15.625rem;
margin: auto;
}
.default1_context {
margin: 0 auto;
color: black;
font-size: .875rem;
font-weight: 600;
}
.default1_btn {
margin: 0 auto;
width: 6.25rem;
height: 1.75rem;
background: linear-gradient(#329C5E, #3BA366);
border-radius: 2.0625rem;
display: flex;
.default1_btn_text {
margin: auto;
color: white;
font-size: .875rem;
}
}
}

@ -0,0 +1,30 @@
import { View, Text, Image } from '@tarojs/components'
import { useState } from 'react'
import './index.less'
import GetPhoneNumber from '../getPhoneModal'
export default function DefaultPage1({setisGetUsePhone}) {
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
return (
<View className='default1_bg'>
<Image src='https://oss.jm-kid.com/wx_5colorflower/defaultBg1.png'></Image>
<Text className='default1_context'></Text>
<View
className='default1_btn'
onClick={()=>{setisLoginOpen(true)}}
>
<Text
className='default1_btn_text'
></Text>
</View>
<GetPhoneNumber
onClose={setisGetUsePhone}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
</View>
)
}

@ -0,0 +1,35 @@
.default1_bg {
display: flex;
height: 100vh;
flex-direction: column;
margin: auto;
gap: 1.25rem;
.default1_img {
width: 15.625rem;
height: 15.625rem;
margin: auto auto 1rem auto;
}
.default1_context {
margin: 0 auto;
color: black;
font-size: .875rem;
font-weight: 600;
}
.default1_btn {
margin: 0 auto auto auto;
width: 6.25rem;
height: 1.75rem;
background: linear-gradient(#329C5E, #3BA366);
border-radius: 2.0625rem;
display: flex;
.default1_btn_text {
margin: auto;
color: white;
font-size: .875rem;
}
}
}

@ -0,0 +1,31 @@
import { View, Text, Image } from '@tarojs/components'
import { useState } from 'react'
import './index.less'
import GoToStoreModal from '../goToStoreModal'
export default function DefaultPage2() {
const [isToStoreOpen, setisToStoreOpen] = useState(false)
return (
<View className='default1_bg'>
<Image src='https://oss.jm-kid.com/wx_5colorflower/defaultBg2.png' className='default1_img'></Image>
<Text className='default1_context'>~</Text>
<View
className='default1_btn'
onClick={()=>{
setisToStoreOpen(true)
}}
>
<Text className='default1_btn_text'>~</Text>
</View>
<GoToStoreModal
visible={isToStoreOpen}
onClose={() => setisToStoreOpen(false)}
type={0}
setmallLink={()=>{}}
></GoToStoreModal>
</View>
)
}

@ -0,0 +1,36 @@
.default3_bg {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
margin: auto;
gap: 1.25rem;
.default1_img {
width: 15.625rem;
height: 15.625rem;
margin: auto auto 1rem auto;
}
.default1_context {
margin: 0 auto auto auto;
color: black;
font-size: .875rem;
font-weight: 600;
}
// .default1_btn {
// margin: 0 auto auto auto;
// width: 6.25rem;
// height: 1.75rem;
// background: linear-gradient(#329C5E, #3BA366);
// border-radius: 2.0625rem;
// display: flex;
// .default1_btn_text {
// margin: auto;
// color: white;
// font-size: .875rem;
// }
// }
}

@ -0,0 +1,14 @@
import { View, Text, Image } from '@tarojs/components'
import './index.less'
export default function DefaultPage3() {
return (
<View className='default3_bg'>
<Image src='https://oss.jm-kid.com/wx_5colorflower/empty_subscribe.png' className='default1_img'></Image>
<Text className='default1_context'></Text>
{/* <View className='default1_btn'>
<Text className='default1_btn_text'>~</Text>
</View> */}
</View>
)
}

@ -0,0 +1,88 @@
.light_border {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 18rem;
height: 16.625rem;
background: rgba(0, 0, 0, 0.1);
border-radius: 1rem;
display: flex;
padding: .125rem;
z-index: 1000;
box-shadow: 0px 0px 13.8px 0px #FFFFFFCC inset;
.phone_modal {
width: 16.375rem;
height: 15rem ;
background: linear-gradient(180deg, #FDF5DE 0%, #FFFFFF 100%);
border-radius: 1rem;
display: flex;
padding: .125rem;
z-index: 1000;
margin: auto;
flex-direction: column;
.phone_modal_container {
width: 10rem;
height: 2rem;
display: flex;
flex-direction: row;
background: #07c160;
border-radius: 1rem;
margin: auto auto 0 auto;
gap: 1rem;
border: 1.5px solid #FFFFFF;
box-shadow: 0px 4px 12px 0px #05BD4D4D;
// .phone_modal_icon {
// width: 2.5rem;
// height: 2.5rem;
// background-image: url(https://oss.jm-kid.com/wx_5colorflower/wechatFill.svg);
// background-repeat: no-repeat;
// background-size: cover;
// // margin: auto 0 auto auto;
// }
.phone_modal_title {
font-size: 1rem;
font-weight: 600;
line-height: 1.4375rem;
color: #fff;
text-align: center;
margin: auto;
}
}
.phone_modal_desc {
color: rgba(0, 0, 0, 0.4);
font-size: .75rem;
margin: .5rem auto auto auto;
}
.phone_modal_logo {
width: 11.25rem;
height: 5rem;
margin: 2.625rem auto auto auto;
background-image: url('https://oss.jm-kid.com/wx_5colorflower/FCFlogo.png');
background-repeat: no-repeat;
background-size: cover;
}
}
}
.login_overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
background-image: url('https://oss.jm-kid.com/wx_5colorflower/light.png');
background-repeat: no-repeat;
background-size: cover;
z-index: 999;
}

@ -0,0 +1,137 @@
import { Button, View, Text } from '@tarojs/components'
import { useState } from 'react'
import Taro from '@tarojs/taro'
import './index.less'
export default function GetPhoneNumber({ onClose, scene = null, modalVisible, onModalClose}) {
//管理关闭动画状态
const [isAnimationOpen, setisAnimationOpen] = useState(false)
if(!modalVisible){
return null
}
const handleOverlayClick = (event: any) => {
// 点击蒙层时关闭弹窗
setisAnimationOpen(true)
setTimeout(() =>{
setisAnimationOpen(false)
// onClose()
onModalClose()
}, 0)
};
const handleGetUserPhone = (e: any) => {
console.log(e.detail)
Taro.request({
url: 'https://interapi.jm-kid.com/api/register',
method: 'POST',
data: {
MCODE: e.detail.code,
channel: 'wusehua_mini',
open_id: Taro.getStorageSync('LoginKey'),
},
success: (res: any) => {
console.log('用户注册信息=>',res)
Taro.setStorageSync('UserAvatar', res.data.user.Avatar)
Taro.setStorageSync('UserNickName', res.data.user.NickName)
Taro.setStorageSync('UserPhoneNumber', res.data.user.Mobile)
Taro.setStorageSync('UserToken', res.data.token)
if(scene){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/exchange',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
change_code: scene
},
success: (s_res: any) => {
console.log('兑换成功=>', s_res.data)
if(s_res.data.state === '200'){
let modalContent = ''
s_res.data.data.Subscribed.forEach(element => {
modalContent += `兑换成功: ${element.PrdtTitle}\n`
})
Taro.showModal({
title: '兑换成功',
content: modalContent,
showCancel: true,
success: (modal_res) => {
if (modal_res.confirm) {
console.log('用户点击确定')
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + s_res.data.data.Subscribed[0].PrdtId
})
} else if (modal_res.cancel) {
console.log('用户点击取消')
}
}
})
}else if(s_res.data.state === '207'){
Taro.showToast({
title: '兑换码已使用',
icon: 'error'
})
}
},
fail: (err: any) => {
console.log('兑换失败=>', err)
}
})
}
//注册成功
onClose(true)
//关闭弹窗
onModalClose()
},
fail: (err: any) => {
console.log('用户注册失败=>',err)
}
})
}
return (
<>
<View
className='login_overlay'
onClick={handleOverlayClick}
style={
!isAnimationOpen ? { opacity: 1, transition: 'opacity 1s ease-in-out' }
: { opacity: 0 }
}
/>
<View className='light_border'>
<View className='phone_modal'>
<View className='phone_modal_logo'></View>
<Button
className='phone_modal_container'
openType='getPhoneNumber'
onGetPhoneNumber={handleGetUserPhone}
>
{/* <View className='phone_modal_icon'></View> */}
<View
className='phone_modal_title'
>
</View>
</Button>
<Text
className='phone_modal_desc'
onClick={handleOverlayClick}
></Text>
</View>
</View>
</>
)
}

@ -0,0 +1,61 @@
.store_modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 18rem;
height: 9rem;
background: #fff;
border-radius: 1rem;
display: flex;
flex-direction: column;
padding: .125rem;
z-index: 1000;
.store_modal_close {
width: 1.5rem;
height: 1.5rem;
margin: 1rem 1rem auto auto;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/close.png);
background-repeat: no-repeat;
background-size: cover;
}
.store_modal_context {
font-size: .875rem;
font-weight: 600;
text-align: center;
margin: auto;
}
.store_modal_container {
width: 10rem;
height: 2rem;
display: flex;
flex-direction: row;
background: #07c160;
border-radius: 1rem;
margin: auto;
gap: 1rem;
.store_modal_title {
font-size: 1rem;
font-weight: 600;
height: 1.125rem;
color: #fff;
text-align: center;
margin: auto;
}
}
}
.store_overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}

@ -0,0 +1,76 @@
import { View, Text } from '@tarojs/components'
import { useState } from 'react';
import Taro from '@tarojs/taro';
import './index.less'
export default function GoToStoreModal({ visible, onClose, type, mallLink = 'pages/home/dashboard/index', setmallLink}) {
//管理关闭动画状态
const [isAnimationOpen, setisAnimationOpen] = useState(false)
if(!visible){
return null
}
const handleOverlayClick = (event: any) => {
// 点击蒙层时关闭弹窗
setisAnimationOpen(true)
setTimeout(() =>{
setisAnimationOpen(false)
onClose();
}, 0)
};
const handleNavigateToMiniProgram = () => {
Taro.navigateToMiniProgram({
appId: 'wxbd3d383851fea776',
path: mallLink,
success: (res) => {
console.log('打开成功=>',res)
},
fail: (res) => {
console.log('打开失败=>',res)
}
})
setmallLink('')
handleOverlayClick(null)
}
return (
<>
<View
className='store_overlay'
onClick={handleOverlayClick}
style={
!isAnimationOpen ? { opacity: 1, transition: 'opacity 1s ease-in-out' }
: { opacity: 0 }
}
/>
<View
className='store_modal'
style={
!isAnimationOpen ? { opacity: 1, transition: 'opacity 1s ease-in-out' }
: { opacity: 0 }
}
>
<View className='store_modal_close' onClick={handleOverlayClick}></View>
<Text className='store_modal_context'>
{type === 0 ? '您还没有订阅,请前往商城购买' : '更多绘本请前往商城选购'}
</Text>
<View
className='store_modal_container'
onClick={handleNavigateToMiniProgram}
>
<View
className='store_modal_title'
>
</View>
</View>
</View>
</>
)
}

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no,address=no">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
<title>FCF</title>
<script><%= htmlWebpackPlugin.options.script %></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '听绘本',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,130 @@
.audioItfc_bg {
width: calc(100vw - 2rem);
height: 100vh;
display: flex;
flex-direction: column;
padding: 0 1rem;
.audio_disc {
width: 15rem;
height: 15rem;
border-radius: 7.5rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/《屁》.png);
background-repeat: no-repeat;
background-size: cover;
margin: 5rem auto 0 auto;
border: .3125rem solid #fff;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);
.audio_disc_bearing {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 4rem;
height: 4rem;
border-radius: 2rem;
background: #ffffff;
}
}
.audio_progress_bar {
width: 100%;
height: auto;
margin: auto auto calc(1rem + env(safe-area-inset-bottom)) auto;
display: flex;
flex-direction: column;
gap: .5rem;
.audio_title {
font-size: 1.125rem;
font-weight: 600;
color: #000;
text-align: center;
margin: 2rem auto 0 0;
}
.audio_discription {
font-size: .875rem;
color: rgba(0, 0, 0, 0.4);
margin: .5rem auto 0 0;
}
.audio_tips {
width: auto;
height: 1rem;
margin: .5rem auto auto 0;
display: flex;
flex-direction: row;
gap: .5rem;
.audio_tip {
width: auto;
height: 1rem;
border-radius: .375rem;
background: #3BA366;
display: flex;
padding: .0625rem .5625rem;
.audio_tip_text {
width: auto;
font-size: .625rem;
color: #ffffff;
text-align: center;
margin: auto;
}
}
}
.audio_progress_time_bar {
width: 100%;
height: 1rem;
display: flex;
flex-direction: row;
.audio_progress_time {
font-size: .75rem;
color: #3BA366;
width: 1.875rem;
height: 100%;
}
}
.audio_progress {
margin: .5rem 0;
width: calc(100% - 2rem);
}
.audio_operate {
height: 4.125rem;
width: 100%;
display: flex;
flex-direction: row;
gap: 2rem;
.audio_operate_btn0 {
width: 3rem;
height: 3rem;
background-repeat: no-repeat;
background-size: cover;
margin: auto;
}
.audio_operate_btn1 {
width: 4rem;
height: 4rem;
background-repeat: no-repeat;
background-size: cover;
}
}
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg); /* 顺时针旋转360度 */
}
}

@ -0,0 +1,257 @@
import { View, Text, Progress, Image } from '@tarojs/components'
import Taro, { useDidShow, useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import React, { useEffect, useState } from 'react'
import './index.less'
export default function AudioInterface() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [testMusic, settestMusic] = useState('http://music.163.com/song/media/outer/url?id=447925558.mp3')
const [MusicDesc, setMusicDesc] = useState<any>({})
const [currentTime, setcurrentTime] = useState(0)
const [durantionTime, setdurantionTime] = useState(230)
const [isPlay, setisPlay] = useState(false)
const formatSecondsToTime = (seconds: number) => {
// 将秒数转换为整数秒和毫秒
const totalSeconds = Math.floor(seconds);
// 分钟数
const minutes = Math.floor(totalSeconds / 60);
// 剩余秒数
const remainingSeconds = totalSeconds % 60;
// 补零操作
const formattedMinutes = minutes.toString().padStart(2, '0');
const formattedSeconds = remainingSeconds.toString().padStart(2, '0');
return `${formattedMinutes}:${formattedSeconds}`;
}
useLoad((query) => {
console.log('query=>', query.id)
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
prdt_id: query.id,
res_type: '03',
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
setMusicDesc(res.data.data.Product)
setdurantionTime(res.data.data.StoryResource[0].ResDuration)
settestMusic(res.data.data.StoryResource[0].ResVpath)
// Taro.request({
// method: 'POST',
// url: 'https://api.jimeikid.com/jiyoumei/system/admin/employee/login',
// data: {
// "password": "WxBmGKupbl30+v4hfQC8aQ==",
// "userName": "VqwgIY4g7s9DanyyqsKP4g==",
// },
// success: (token_res) => {
// if(res.data.data.StoryResource.length){
// Taro.request({
// method: 'GET',
// url: 'https://api.jimeikid.com/jiyoumei/product/app/message/send/history/getPlayInfo',
// header: {
// authorization: token_res.data.data.token
// },
// data: {
// token: res.data.data.StoryResource[0].ResPwd,
// videoId: res.data.data.StoryResource[0].ResVcode,
// },
// success: function (rres) {
// console.log('视频资源请求成功=>', rres)
// setdurantionTime(rres.data.data.body.playInfoList.playInfo[0].duration)
// settestMusic(rres.data.data.body.playInfoList.playInfo[0].playURL)
// }
// })
// }
// },
// })
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
data: {
timestamp: Date.now(),
prdt_id: query.id,
res_type: '03',
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
setMusicDesc(res.data.data.Product)
setdurantionTime(res.data.data.StoryResource[0].ResDuration)
settestMusic(res.data.data.StoryResource[0].ResVpath)
// Taro.request({
// method: 'POST',
// url: 'https://api.jimeikid.com/jiyoumei/system/admin/employee/login',
// data: {
// "password": "WxBmGKupbl30+v4hfQC8aQ==",
// "userName": "VqwgIY4g7s9DanyyqsKP4g==",
// },
// success: (token_res) => {
// if(res.data.data.StoryResource.length){
// Taro.request({
// method: 'GET',
// url: 'https://api.jimeikid.com/jiyoumei/product/app/message/send/history/getPlayInfo',
// header: {
// authorization: token_res.data.data.token
// },
// data: {
// token: res.data.data.StoryResource[0].ResPwd,
// videoId: res.data.data.StoryResource[0].ResVcode,
// },
// success: function (rres) {
// console.log('视频资源请求成功=>', rres)
// setdurantionTime(rres.data.data.body.playInfoList.playInfo[0].duration)
// settestMusic(rres.data.data.body.playInfoList.playInfo[0].playURL)
// }
// })
// }
// },
// })
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}
})
useEffect(()=>{
if(currentTime === durantionTime - 1){
setcurrentTime(0)
}
const audioContext = Taro.createInnerAudioContext()
audioContext.src = testMusic
if(isPlay){
if(currentTime !== 0){
audioContext.seek(currentTime)
}
audioContext.play()
}else{
audioContext.pause()
}
audioContext.onPlay(() => {
setisPlay(true)
})
audioContext.onPause(() => {
setcurrentTime(audioContext.currentTime)
setisPlay(false)
})
audioContext.onTimeUpdate(() => {
setcurrentTime(audioContext.currentTime)
})
audioContext.onError((res) => {
console.log('error', res)
})
return () => {
audioContext.destroy()
}
}, [isPlay])
return (
<View className='audioItfc_bg'>
<View
className='audio_disc'
style={isPlay ? {animation: 'spin 10s linear infinite', backgroundImage: `url(${MusicDesc.PrdtCover})`} : {backgroundImage: `url(${MusicDesc.PrdtCover})`}}
>
<View className='audio_disc_bearing'></View>
</View>
<View className='audio_progress_bar'>
<Text className='audio_title'>{MusicDesc.PrdtTitle}</Text>
{/* <Text className='audio_discription'>{MusicDesc.PrdtDescription}</Text>
<View className='audio_tips'>
{
MusicDesc && MusicDesc.PrdtKeys && MusicDesc.PrdtKeys.map((item: any, index: number) => (
<View
className='audio_tip'
key={index}
>
<Text className='audio_tip_text'>{item}</Text>
</View>
))
}
</View> */}
<Progress
className='audio_progress'
percent={currentTime/durantionTime*100}
activeColor='#3BA366'
strokeWidth={2}
></Progress>
<View className='audio_progress_time_bar'>
<View
className='audio_progress_time'
style={{marginRight: 'auto'}}
>
{formatSecondsToTime(currentTime)}
</View>
<View
className='audio_progress_time'
style={{marginLeft: 'auto'}}
>
{formatSecondsToTime(durantionTime)}
</View>
</View>
<View className='audio_operate'>
<Image
className='audio_operate_btn0'
style={{marginLeft: 'auto', marginRight: '0'}}
src='https://oss.jm-kid.com/wx_5colorflower/prevMusic.png'
></Image>
<Image
className='audio_operate_btn1'
src={isPlay ? 'https://oss.jm-kid.com/wx_5colorflower/pauseMusic.png' : 'https://oss.jm-kid.com/wx_5colorflower/playMusic.png'}
onClick={() => setisPlay(!isPlay)}
></Image>
<Image
className='audio_operate_btn0'
style={{marginRight: 'auto', marginLeft: '0'}}
src='https://oss.jm-kid.com/wx_5colorflower/nextMusic.png'
></Image>
</View>
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationStyle: 'custom',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,169 @@
.collection_bg {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
.collection_cover {
width: 100vw;
height: calc(100vw * .5625);
background-repeat: no-repeat;
background-size: cover;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/《屁》.png);
}
.collection_info_container {
position: relative;
width: 100%;
height: 0;
.collection_container {
position: absolute;
width: calc(100% - 2rem);
height: auto;
top: -1rem;
left: 1rem;
.collection_info {
width: calc(100% - 2rem);
height: auto;
border-radius: 1rem;
box-shadow: 0 .125rem .5rem rgba(0,0,0,.1);
padding: 1rem;
display: flex;
flex-direction: column;
background: #fff;
gap: .5rem;
.collection_header {
width: 100%;
height: 1.4375rem;
display: flex;
flex-direction: row;
.collection_title {
width: auto;
font-size: 1rem;
font-weight: 600;
margin: auto auto auto 0;
}
.collection_count {
width: auto;
font-size: .75rem;
line-height: 1.0625rem;
height: .75rem;
color: rgba( 0, 0, 0, .4);
margin: auto 0 0 auto;
}
.collection_count::before {
content: '';
background-image: url(https://oss.jm-kid.com/wx_5colorflower/detailCount.png);
background-size: cover;
background-repeat: no-repeat;
display: inline-block;
width: .75rem;
height: .75rem;
margin-right: .25rem;
}
}
.collection_desc {
width: 100%;
height: auto;
font-size: .875rem;
color: rgba( 0, 0, 0, .4);
line-height: 1.25rem;
letter-spacing: .125rem;
}
}
.collection_List {
width: 100%;
height: auto;
display: flex;
margin-top: 1rem;
flex-direction: column;
.collection_item {
width: 100%;
height: 8rem;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
.collection_item_cover {
width: 7rem;
height: 7rem;
border-radius: .75rem;
background-repeat: no-repeat;
background-size: cover;
margin: auto .5rem;
}
.collection_item_info {
width: calc(100% - 7rem);
height: 100%;
display: flex;
flex-direction: column;
gap: .25rem;
.collection_item_title {
font-size: 1rem;
font-weight: 600;
margin: auto auto 0 0;
}
.collection_item_subtitle {
font-size: .875rem;
color: rgba( 0, 0, 0, .4);
line-height: 1.25rem;
margin: 0 auto 0 0;
}
.collection_item_label_container {
width: auto;
height: auto;
display: flex;
flex-direction: row;
margin: 0 auto auto 0;
.collection_item_label {
width: auto;
height: 1rem;
background-color: #3ba366;
border-radius: .375rem;
display: flex;
margin: auto .24rem auto 0;
.collection_item_label_text {
font-size: .625rem;
margin: .0625rem .5625rem;
color: #fff;
}
}
}
}
}
}
}
}
.collection_back {
position: fixed;
top: .625rem;
left: .625rem;
width: .7181rem;
height: 1.25rem; //20px
background-image: url(https://oss.jm-kid.com/wx_5colorflower/turnBack.png);
background-repeat: no-repeat;
background-size: cover;
z-index: 9999;
}
}

@ -0,0 +1,200 @@
import { View, Text, ScrollView, Image } from '@tarojs/components'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import React, { useEffect, useRef, useState } from 'react'
import './index.less'
import GoToStoreModal from '../../components/goToStoreModal'
interface DetailProps {
Child: {
PrdtCover: string,
PrdtDescription: string,
PrdtId: number,
PrdtImages: string[],
PrdtKeys: string[],
PrdtRead: number,
PrdtSubtitle: string,
PrdtTitle: string,
}[],
IsSubscribed: number,
MallLink: string,
Product: {
PrdtCover: string,
PrdtDescription: string,
PrdtId: number,
PrdtImages: string[],
PrdtKeys: string[],
PrdtRead: number,
PrdtSubtitle: string,
PrdtTitle: string,
}
}
export default function CollectionDetail() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [navigationBarHeight, setnavigationBarHeight] = useState(0)
//产品详情
const [productDetail, setproductDetail] = useState<DetailProps>()
const [isToStoreOpen, setisToStoreOpen] = useState(false)
//管理跳转页面路径
const [prdtMallLink, setprdtMallLink] = useState('')
useLoad((query) => {
console.log('query=>', query.id)
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/detail',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
prdt_id: query.id
},
success: (res) => {
console.log('产品详情获取成功=>', res.data)
setproductDetail(res.data.data)
},
fail: (err) => {
console.log('产品详情获取失败=>', err)
}
})
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/detail',
method: 'POST',
data: {
timestamp: Date.now(),
prdt_id: query.id
},
success: (res) => {
console.log('产品详情获取成功=>', res.data)
setproductDetail(res.data.data)
},
fail: (err) => {
console.log('产品详情获取失败=>', err)
}
})
}
})
useEffect(() => {
const sysInfo = Taro.getSystemInfoSync()
const statusBarHeight = sysInfo.statusBarHeight
if(statusBarHeight)
setnavigationBarHeight(statusBarHeight + 12)
}, [])
const handleToSingleDetail = (id: string) => {
if(productDetail?.IsSubscribed === -1 || productDetail?.IsSubscribed === 2){
//未订阅,跳转商城
setprdtMallLink(productDetail.MallLink)
setisToStoreOpen(true)
}
else if(productDetail?.IsSubscribed === 1){
//已订阅,跳转详情页
Taro.navigateTo({
url: '/pages/SingleDetail/index?id=' + id
})
}
// Taro.navigateTo({
// url: '/pages/SingleDetail/index?id=' + id
// })
}
return (
<View className='collection_bg'>
<View
className='collection_back'
style={{top: navigationBarHeight}}
onClick={()=>Taro.navigateBack()}
></View>
{
productDetail && <View
className='collection_cover'
style={{backgroundImage: `url(${productDetail.Product.PrdtCover})`}}
></View>
}
<View
className='collection_info_container'
>
<View className='collection_container'>
<View className='collection_info'>
<View className='collection_header'>
<Text className='collection_title'>{productDetail?.Product.PrdtTitle}</Text>
<Text className='collection_count'>{`${productDetail?.Child.length}`}</Text>
</View>
<View className='collection_desc'>{productDetail?.Product.PrdtDescription}</View>
</View>
<View
className='collection_List'
>
{
productDetail?.Child.map((item: any, index: number) => (
<View
className='collection_item'
key={index}
onClick={() => handleToSingleDetail(item.PrdtId)}
>
<Image
className='collection_item_cover'
src={item.PrdtCover}
lazyLoad
></Image>
<View className='collection_item_info'>
<View className='collection_item_title'>{item.PrdtTitle}</View>
<View className='collection_item_subtitle'>{item.PrdtSubtitle}</View>
<View className='collection_item_label_container'>
{
item.PrdtKeys.map((keys_item: any, keys_index: number) => (
keys_index < 3 && <View
className='collection_item_label'
key={keys_index}
>
<View className='collection_item_label_text'>{keys_item}</View>
</View>
))
}
</View>
</View>
</View>
))
}
</View>
</View>
</View>
<GoToStoreModal
visible={isToStoreOpen}
onClose={() => setisToStoreOpen(false)}
type={0}
mallLink={prdtMallLink}
setmallLink={setprdtMallLink}
></GoToStoreModal>
</View>
)
}

@ -0,0 +1,8 @@
export default {
navigationBarTitleText: '视频播放',
enableShareAppMessage: true,
enableShareTimeline: true,
usingComponents: {
"player-component": "plugin://player/video"
}
}

@ -0,0 +1,101 @@
.sixteen-to-nine-container {
position: relative;
width: 100%; /* 或者任意宽度 */
padding-top: calc((9 / 16) * 100%); /* 计算高度以保持16:9比例 */
.content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0; /* 使内容填充整个容器 */
.jimeiVideo {
width: 100%;
height: 100%
}
}
}
.displayList {
// width: 100vw;
// height: 100vh;
// display: flex;
// align-items: center;
// margin-top: 12.5rem;
height: calc(100vh - 100vw * .5625);
overflow: hidden;
//排列方向为竖直方向水平居中
// flex-direction: column;
.card {
width: 100vw;
height: 6rem;
display: flex;
.card-image {
// object-fit: cover; wechatapp中object-fit属性不生效
width: 8rem;
height: 4.5rem;
border-radius: 1rem;
margin-top: .75rem;
margin-bottom: .75rem;
margin-left: 1.5rem;
margin-right: .75rem;
}
.card-textarea {
margin-top: 1.7813rem;
width: 9.375rem;
height: 3.125rem;
// float: left;
display: flex;
flex-direction: column;
// justify-content: center;
.card-textarea-title {
font-size: .875rem;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.card-textarea-content {
padding-top: .625rem;
height: 1.25rem;
width: 9.375rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: flex;
.content-icon {
width: .9375rem;
height: .9375rem;
padding-right: .375rem;
}
.content-text {
width: 11.5625rem;
// height: 1.0625rem;
font-size: .75rem;
color: dimgray;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.card-button {
// margin-top: 2.3125rem;
// margin-left: auto;
margin: 2.0625rem 0 0;
width: 1.875rem;
height: 1.875rem;
}
}
}

@ -0,0 +1,402 @@
import { useEffect, useState } from 'react'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import { View, Text, Video, Image, ScrollView } from '@tarojs/components'
import './index.less'
// const freeList = [
// [
// {
// ResCover: "https://alihls.jm-kid.com/4e4442cc8bb04ee9945f7fc62f5d83c2/snapshots/a4835dffb64d4d62be067e7d73b1f9ed-00001.jpg",
// ResDuration: 9,
// ResId: 10001,
// ResTitle: "森林的诞生_封面",
// Tvpid: 'z3562su60q2',
// },
// {
// ResCover: "https://alihls.jm-kid.com/c0a62307b01c47f5bd9f96a105f23df1/snapshots/78fdf09eaf6446519f96afe8c1630480-00003.jpg",
// ResDuration: 43,
// ResId: 10001,
// ResTitle: "森林的诞生P1",
// Tvpid: 'e3562q26qqy',
// },
// {
// ResCover: "https://alihls.jm-kid.com/bd03e6684ee24f8b9ac91acb6c32c63d/snapshots/87a9f893f97e44529a7a90ed4522b593-00002.jpg",
// ResDuration: 23,
// ResId: 10001,
// ResTitle: "森林的诞生P2",
// Tvpid: 'p35627v9cm2',
// },
// ],
// [
// {
// ResCover: "https://alihls.jm-kid.com/af78118009bb71ee80616732b78e0102/snapshots/a9ba85d7bbdb49c28001bd5fec1aa611-00002.jpg",
// ResDuration: 17,
// ResId: 10001,
// ResTitle: "当我长大时_男孩_封面",
// Tvpid: 'h3563rbx1uo',
// },
// {
// ResCover: "https://alihls.jm-kid.com/a4c5e0f009bb71ee8b936733a78e0102/snapshots/7b8886fbc9864850b36462e7752cebfd-00005.jpg",
// ResDuration: 80,
// ResId: 10001,
// ResTitle: "当我长大时_男孩P1",
// Tvpid: 't3563fjh7wg',
// },
// {
// ResCover: "https://alihls.jm-kid.com/ab68f1e009bb71eea28d6633b79f0102/snapshots/e803c8d22da14531be0dc53c118ce336-00004.jpg",
// ResDuration: 50,
// ResId: 10001,
// ResTitle: "当我长大时_男孩P2",
// Tvpid: 'q3563s8krn2',
// },
// ],
// [
// {
// ResCover: "https://alihls.jm-kid.com/af78118009bb71ee80616732b78e0102/snapshots/a9ba85d7bbdb49c28001bd5fec1aa611-00002.jpg",
// ResDuration: 42,
// ResId: 10001,
// ResTitle: "当我长大时_女孩_封面",
// Tvpid: 'd3563zelkc4',
// },
// {
// ResCover: "https://alihls.jm-kid.com/a4c5e0f009bb71ee8b936733a78e0102/snapshots/7b8886fbc9864850b36462e7752cebfd-00005.jpg",
// ResDuration: 28,
// ResId: 10001,
// ResTitle: "当我长大时_女孩P1",
// Tvpid: 'm35631g0anx',
// },
// {
// ResCover: "https://alihls.jm-kid.com/ab68f1e009bb71eea28d6633b79f0102/snapshots/e803c8d22da14531be0dc53c118ce336-00004.jpg",
// ResDuration: 85,
// ResId: 10001,
// ResTitle: "当我长大时_女孩P2",
// Tvpid: 'd3563bvtw1r',
// },
// ],
// ]
export default function Index() {
// const [poemdata, setpoemdata] = useState({})
// const [readnum, setreadnum] = useState('')
// const [showVideo, setshowVideo] = useState(false)
// const [showModal, setshowModal] = useState(false) //看一看和读一读图片点击弹窗
// const [showvModal, setshowvModal] = useState(false) //视频播放结束弹窗
// const [showftModal, setshowftModal] = useState(false)
// const [yanDisplay, setyanDisplay] = useState({
// src:'',
// })
// const [changDisplay, setchangDisplay] = useState({
// src:'',
// })
// const [defaultvideo, setdefaultvideo] = useState('')
const [ifchoose, setifchoose] = useState(1)
const [desc, setdesc] = useState('')
const [alldata, setalldata] = useState<any>([])
const [displayindex, setdisplayindex] = useState({
index: -1,
src: '',
poster: '',
})
const [isplay, setisplay] = useState(false)
const [isFree, setisFree] = useState(false)
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useLoad((query) => {
console.log('id=>', query.id)
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
prdt_id: query.id,
},
success: (res: any) => {
console.log('播放资源请求成功=>', res.data)
setalldata(res.data.data.Resource)
setisFree(res.data.data.IsFree)
if(res.data.data.IsFree){
setdisplayindex({
index: 0,
src: res.data.data.Resource[0].Tvpid,
poster: res.data.data.Resource[0].ResCover,
})
}else{
Taro.request({
method: 'POST',
url: 'https://api.jimeikid.com/jiyoumei/system/admin/employee/login',
data: {
"password": "WxBmGKupbl30+v4hfQC8aQ==",
"userName": "VqwgIY4g7s9DanyyqsKP4g==",
},
success: (token_res) => {
if(res.data.data.Resource.length){
Taro.request({
method: 'GET',
url: 'https://api.jimeikid.com/jiyoumei/product/app/message/send/history/getPlayInfo',
header: {
authorization: token_res.data.data.token
},
data: {
token: res.data.data.Resource[0].ResPwd,
videoId: res.data.data.Resource[0].ResVcode,
},
success: function (rres) {
console.log('视频资源请求成功=>', rres)
//设置初始播放状态
setdisplayindex({
index: 0,
src: rres.data.data.body.playInfoList.playInfo[0].playURL,
poster: rres.data.data.body.videoBase.coverURL,
})
}
})
}
},
})
}
},
fail: (err) => {
console.log('播放资源请求失败=>', err)
}
})
}else{
//常规请求数据
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
data: {
timestamp: Date.now(),
prdt_id: query.id,
},
success: (res: any) => {
console.log('播放资源请求成功=>', res.data)
setalldata(res.data.data.Resource)
setisFree(res.data.data.IsFree)
setdisplayindex({
index: 0,
src: res.data.data.Resource[0].Tvpid,
poster: res.data.data.Resource[0].ResCover,
})
},
fail: (err) => {
console.log('播放资源请求失败=>', err)
}
})
}
})
const changedisplay = (item: any, index: any) => {
if(!isFree){
//根据点击行为设置播放状态
console.log(index)
console.log(alldata)
//点击切换时更新视频
Taro.request({
method: 'POST',
url: 'https://api.jimeikid.com/jiyoumei/system/admin/employee/login',
data: {
"password": "WxBmGKupbl30+v4hfQC8aQ==",
"userName": "VqwgIY4g7s9DanyyqsKP4g==",
},
success: (token_res) => {
Taro.request({
method: 'GET',
url: 'https://api.jimeikid.com/jiyoumei/product/app/message/send/history/getPlayInfo',
header: {
authorization: token_res.data.data.token
},
data: {
token: alldata[index]['ResPwd'],
videoId: alldata[index]['ResVcode']
},
success: function (rres) {
console.log('4请求成功', rres)
//设置初始播放状态
setdisplayindex({
index: index,
src: rres.data.data.body.playInfoList.playInfo[0].playURL,
poster: rres.data.data.body.videoBase.coverURL,
})
},
fail: (err) => {
console.log(err)
}
})
},
})
}else{
//腾讯视频固定数据
setdisplayindex({
index: index,
src: item.Tvpid,
poster: item.ResCover,
})
}
}
const continuePlay = () => {
//连播
let nowindex = displayindex['index']
console.log('nowindex:', nowindex, 'alldata.length:', alldata.length)
//当播放至最后一项时,停在当前视频
if (nowindex === alldata.length - 1) {
console.log('播放结束')
} else {
if(!isFree){
//连播时更新视频
Taro.request({
method: 'POST',
url: 'https://api.jimeikid.com/jiyoumei/system/admin/employee/login',
data: {
"password": "WxBmGKupbl30+v4hfQC8aQ==",
"userName": "VqwgIY4g7s9DanyyqsKP4g==",
},
success: (token_res) => {
Taro.request({
method: 'GET',
url: 'https://api.jimeikid.com/jiyoumei/product/app/message/send/history/getPlayInfo',
header: {
authorization: token_res.data.data.token
},
data: {
token: alldata[nowindex + 1]['ResPwd'],
videoId: alldata[nowindex + 1]['ResVcode']
},
success: function (rres) {
console.log('视频内容请求成功', rres)
//设置初始播放状态
setdisplayindex({
index: nowindex + 1,
src: rres.data.data.body.playInfoList.playInfo[0].playURL,
poster: rres.data.data.body.videoBase.coverURL,
})
}
})
},
})
}else{
//腾讯视频固定数据
setdisplayindex({
index: nowindex + 1,
src: alldata[nowindex + 1].Tvpid,
poster: alldata[nowindex + 1].ResCover,
})
}
}
}
const provingCdKey = () => {
//记录验证成功后退出函数,避免反复执行
setisplay(true)
return
}
const getDuration = (num: number) => {
let minutes = Math.floor(num / 60);
let seconds = Math.floor(num % 60);
// let result = minutes + ':' + seconds;
let result = minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
return result;
}
return (
<View className='bgview' style={{ width: '100%', overflow: 'hidden' }}>
{/* pad小程序 */}
<View className='sixteen-to-nine-container'>
<View className='content'>
{
!isFree &&
<Video
className='jimeiVideo'
src={displayindex['src']}
poster={displayindex['poster']}
initialTime={0}
controls
autoplay
loop={false}
muted={false}
onEnded={() => continuePlay()}
onPlay={() => provingCdKey()}
direction={90}
id='topvideo'
objectFit='contain'
></Video>
}
{
isFree &&
//@ts-ignore
<player-component
className='jimeiVideo'
id='tvp-id'
playerid='tvp'
vid={displayindex.src}
onEnded={() => continuePlay()}
onPlay={() => provingCdKey()}
autoplay
/>
}
</View>
</View>
<ScrollView
className='displayList'
scrollY
scrollWithAnimation
>
{
alldata.map((item : any, index: number) =>
<View className='card' key={item['ResId']} style={index == displayindex['index'] ? { backgroundColor: '#efefef' } : {}} onClick={() => changedisplay(item, index)} >
<Image className='card-image' src={item['ResCover']} mode='aspectFill'></Image>
<View className='card-textarea'>
<Text className='card-textarea-title'>{item['ResTitle']}</Text>
<View className='card-textarea-content'>
<Image src='https://oss.jm-kid.com/wx_5colorflower/testIcon.svg' className='content-icon'></Image>
<Text className='content-text'>{getDuration(item['ResDuration'])}</Text>
</View>
</View>
<Image className='card-button' src={isplay && displayindex['index'] == index ? 'https://oss.jm-kid.com/wx_5colorflower/newplay.gif' : 'https://oss.jm-kid.com/wx_5colorflower/button_01.svg'}></Image>
</View>
)
}
</ScrollView>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationStyle: 'custom',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,266 @@
.home_bg {
width: 100vw;
height: auto;
display: flex;
flex-direction: column;
background: #fafafa;
.home_swiper {
width: 100vw;
height: calc(100vw * .5625);
background: #000;
// background-image: url(https://oss.jm-kid.com/wx_5colorflower/banner1.png);
// background-repeat: no-repeat;
// background-size: contain;
margin-bottom: 1rem;
.swiper_container {
width: 100%;
height: 100%;
.swiper_item {
width: 100%;
height: 100%;
.swiper_item_img {
width: 100%;
height: 100%;
}
}
}
}
.home_capsule {
width: 100%;
height: 3.125rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/capsule.png);
background-repeat: no-repeat;
background-size: cover;
margin-bottom: .5rem;
}
.home_single_container {
width: calc(100% - 2rem);
display: grid;
grid-template-columns: repeat(3, 1fr);
height: auto;
gap: .625rem;
padding: 0 1rem;
background: #fff;
.free_item {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3 + .5rem + 2.5rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.free_item_label {
position: absolute;
left: calc(100% - 3rem);
top: calc((100vw - 2rem - 1.25rem) / 3 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.free_item_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.free_item_cover {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3);
border-radius: .75rem;
margin-bottom: .5rem;
}
.free_item_title {
width: calc(((100vw - 2rem - 1.25rem) / 3));
height: 2.5rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
white-space: wrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
margin-bottom: 0;
line-clamp: 2;
}
}
}
.home_single_checkMore_container {
width: 100%;
height: auto;
display: flex;
background: #fff;
margin-bottom: 1rem;
.home_single_checkMore {
width: 10rem;
height: 1.5rem;
border-radius: .5rem;
background: linear-gradient(to right, #329C5E, #3BA366);
display: flex;
margin: .5rem auto .5rem auto;
.home_single_checkMore_text {
color: #fff;
font-size: .75rem;
line-height: 1.125rem;
font-weight: 600;
margin: auto;
}
}
}
.home_hot_container {
width: calc(100% - 2rem);
height: auto;
padding: 0 1rem;
display: flex;
flex-direction: column;
background: #fff;
gap: 1rem;
.home_hot_title {
width: 6rem;
height: 1.5rem;
display: flex;
margin-bottom: 1rem;
.home_hot_title_text {
line-height: 1.5rem;
font-size: 1rem;
font-weight: 600;
margin: auto;
}
}
.home_hot_title::before {
content: '';
display: inline-block;
width: 1.5rem;
height: 1.5rem;
margin-right: .5rem;
background-image: url('https://oss.jm-kid.com/wx_5colorflower/homeFire.png');
background-repeat: no-repeat;
background-size: cover;
}
.home_hot_item {
width: 100%;
height: auto;
display: flex;
flex-direction: column;
.hot_info {
width: 100%;
height: auto;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
.hot_info_cover {
width: 10.75rem;
height: 6.0469rem;
border-radius: .75rem;
background: #000;
}
.hot_info_context {
width: calc(100% - 10.75rem);
height: 6.0469rem;
display: flex;
flex-direction: column;
margin: auto auto auto 1rem;
.hot_info_title {
width: auto;
height: 1.5rem;
font-size: 1rem;
font-weight: 600;
margin: 0 auto auto 0;
}
.hot_info_intro {
width: 100%;
height: auto;
font-size: .75rem;
line-height: 1.125rem;
color: rgba(0, 0, 0, .4);
margin: auto auto auto 0;
}
.hot_info_btn {
width: 5rem;
height: 1.5rem;
border-radius: 2.0625rem;
background: linear-gradient(to right, #329C5E, #3BA366);
margin: auto auto 0 0;
display: flex;
.hot_info_btn_text {
width: auto;
height: 1.5rem;
line-height: 1.5rem;
font-size: .75rem;
text-align: center;
color: #fff;
margin: auto;
}
}
}
}
.hot_details {
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
height: auto;
gap: .625rem;
background: #fff;
.hot_details_item {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3 + .5rem + 2.5rem);
display: flex;
flex-direction: column;
.hot_details_item_cover {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3);
border-radius: .75rem;
margin-bottom: .5rem;
}
.hot_details_item_title {
width: calc(((100vw - 2rem - 1.25rem) / 3));
height: 2.5rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
white-space: wrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
margin-bottom: 0;
line-clamp: 2;
}
}
}
}
}
}

@ -0,0 +1,432 @@
import { View, Image, Text, ScrollView, Swiper, SwiperItem } from '@tarojs/components'
import Taro, { useDidShow, useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import { useEffect, useState } from 'react'
import './index.less'
import GetPhoneNumber from '../../components/getPhoneModal'
import GoToStoreModal from '../../components/goToStoreModal'
interface FreeItemProps {
Child: any[],
ChildNum: number,
MallLink: string,
PrdtCover: string,
PrdtId: string,
PrdtOrder: number,
PrdtSubtitle: string,
PrdtTitle: string,
}
export default function Home() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [isToStoreOpen, setisToStoreOpen] = useState(false)
useLoad((query) => {
console.log(query.scene)
if (query.scene) {
console.log('不知道在判断什么玩意儿')
const userCode = decodeURIComponent(query.scene).slice(-8)
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
setuserScene(userCode)
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/exchange',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
change_code: userCode
},
success: (s_res: any) => {
console.log('兑换成功=>', s_res.data)
if(s_res.data.state === '200'){
let modalContent = '兑换成功:'
s_res.data.data.Subscribed.forEach(element => {
modalContent += `${element.PrdtTitle};`
})
Taro.showModal({
title: '兑换成功',
content: modalContent,
showCancel: true,
success: (modal_res) => {
if (modal_res.confirm) {
console.log('用户点击确定')
if(s_res.data.data.Subscribed[0].PrdtType === '03'){
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + s_res.data.data.Subscribed[0].PrdtId
})
}else if(s_res.data.data.Subscribed[0].PrdtType === '05'){
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + s_res.data.data.Subscribed[0].PrdtId
})
}
} else if (modal_res.cancel) {
console.log('用户点击取消')
}
}
})
}else if(s_res.data.state === '207'){
Taro.showToast({
title: '兑换码已使用',
icon: 'error'
})
}
},
fail: (err: any) => {
console.log('兑换失败=>', err)
}
})
}
}
})
//判断是否登录
const [isGetUsePhone, setisGetUsePhone] = useState(false) //false
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
const [userScene, setuserScene] = useState<any>(null)
//首页banner图集
const [bannerList, setbannerList] = useState([])
//免费绘本集
const [freeBook, setfreeBook] = useState<FreeItemProps[]>()
//爆品集
const [hotBook, sethotBook] = useState([])
//管理跳转页面路径
const [prdtMallLink, setprdtMallLink] = useState('')
//点击免费试读跳转
const handleNavigateToFreeRead = (id: number) => {
console.log('点击免费试读跳转', id)
Taro.navigateTo({
url: '/pages/SingleDetail/index?id=' + id
})
}
useDidShow(() => {
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/operation',
method: 'POST',
data: {
timestamp: Date.now(),
type: 'free_books'
},
success: (res:any) => {
console.log('免费绘本获取成功=>',res)
setfreeBook(res.data.data)
}
})
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/operation',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
type: 'hot_books'
},
success: (res:any) => {
console.log('爆品绘本获取成功=>',res)
sethotBook(res.data.data)
}
})
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/index',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res:any) => {
console.log('banner获取成功=>',res)
setbannerList(res.data.data.banner)
}
})
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/operation',
method: 'POST',
data: {
timestamp: Date.now(),
type: 'hot_books'
},
success: (res:any) => {
console.log('爆品绘本获取成功=>',res)
sethotBook(res.data.data)
}
})
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/index',
method: 'POST',
data: {
timestamp: Date.now(),
},
success: (res:any) => {
console.log('banner获取成功=>',res)
setbannerList(res.data.data.banner)
}
})
}
})
//用户登录后重新请求爆品
useEffect(() => {
if(isGetUsePhone){
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/operation',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
type: 'hot_books'
},
success: (res:any) => {
console.log('爆品绘本获取成功=>',res)
sethotBook(res.data.data)
}
})
Taro.request({
url: 'https://interapi.jm-kid.com/api/app/index',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res:any) => {
console.log('banner获取成功=>',res)
setbannerList(res.data.data.banner)
}
})
}
}, [isGetUsePhone])
const toDetail = (isSubscribed: number, id: number, isDetail: number) => {
if(isSubscribed === 0){
//提醒用户登录
setisLoginOpen(true)
}
else if (isSubscribed === -1 || isSubscribed === 2) {
//未订阅,跳转商城
setisToStoreOpen(true)
}else if(isSubscribed === 1){
//已订阅,跳转详情页
Taro.navigateTo({
url: `/pages/${isDetail ? 'SingleDetail' : 'CollectionDetail'}/index?id=${id}`
})
}
// else if(isSubscribed === 1 || isSubscribed === -1 || isSubscribed === 2){
// //已订阅,跳转详情页
// Taro.navigateTo({
// url: '/pages/CollectionDetail/index?id=' + id
// })
// }
}
const handleBannerClick = (item: any) => {
if(item.is_subscribed === 0){
//提醒用户登录
setisLoginOpen(true)
}
// else if(item.is_subscribed === -1 || item.is_subscribed === 2){
// //未订阅,跳转商城
// setprdtMallLink(item.mall_link)
// setisToStoreOpen(true)
// }else if(item.is_subscribed === 1){
// //已订阅,跳转详情页
// Taro.navigateTo({
// url: '/pages/CollectionDetail/index?id=' + item.prdt_id
// })
// }
else{
//已订阅,跳转详情页
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + item.prdt_id
})
}
}
return (
<ScrollView
className='home_bg'
scrollY
scrollWithAnimation
>
<View className='home_swiper'>
<Swiper
className='swiper_container'
circular
indicatorDots
indicatorColor='#999'
indicatorActiveColor='#333'
autoplay
>
{
bannerList.map((item: any, index: number) => (
<SwiperItem
className='swiper_item'
key={index}
onClick={()=>handleBannerClick(item)}
>
<Image className='swiper_item_img' src={item.url}></Image>
</SwiperItem>
))
}
</Swiper>
</View>
<View className='home_capsule'></View>
<View className='home_single_container'>
{
//@ts-ignore
freeBook && freeBook[0].Child.map((item: any, index: number) => (
<View
className='free_item'
key={index}
>
<View className='relative_container'>
<View className='free_item_label'>
<Text className='free_item_label_text'></Text>
</View>
</View>
<Image
src={item.PrdtCover}
className='free_item_cover'
onClick={()=>handleNavigateToFreeRead(item.PrdtId)}
lazyLoad
/>
<Text
className='free_item_title'
>
{item.PrdtTitle}
</Text>
</View>
))
}
</View>
<View
className='home_single_checkMore_container'
onClick={()=> {
if(freeBook)
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + freeBook[0].PrdtId
})
}}
>
<View className='home_single_checkMore'>
<Text
className='home_single_checkMore_text'
>
</Text>
</View>
</View>
<View className='home_hot_container'>
<View className='home_hot_title'>
<Text className='home_hot_title_text'></Text>
</View>
{
hotBook.map((item: any, index: number) => (
<View
className='home_hot_item'
key={index}
>
<View className='hot_info'
onClick={()=>toDetail(item.IsSubscribed, item.PrdtId, 0)}
>
<Image
className='hot_info_cover'
src={item.PrdtCover}
mode='scaleToFill'
></Image>
<View className='hot_info_context'>
<View className='hot_info_title'>{item.PrdtTitle}</View>
<View className='hot_info_intro'>{item.PrdtSubtitle}</View>
<View className='hot_info_btn'>
<View className='hot_info_btn_text'></View>
</View>
</View>
</View>
<View className='hot_details'
onClick={()=>toDetail(item.IsSubscribed, item.PrdtId, 1)}
>
{
item.Child.map((childItem: any, Childindex: number) => (
<View
className='hot_details_item'
key={Childindex}
>
<Image
className='hot_details_item_cover'
src={childItem.PrdtCover}
lazyLoad
></Image>
<View className='hot_details_item_title'>{childItem.PrdtTitle}</View>
</View>
))
}
</View>
</View>
))
}
</View>
<GetPhoneNumber
onClose={setisGetUsePhone}
scene={userScene}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
<GoToStoreModal
visible={isToStoreOpen}
onClose={() => setisToStoreOpen(false)}
type={0}
mallLink={prdtMallLink}
setmallLink={setprdtMallLink}
></GoToStoreModal>
</ScrollView>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '熏听',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,197 @@
.listen_bg {
width: 100vw;
height: auto;
display: flex;
flex-direction: column;
.listen_search {
width: calc(100% - 2rem);
height: 2.75rem;
background-color: #f8f8f8;
margin: 0 1rem;
border-radius: 2.25rem;
display: flex;
flex-direction: row;
.listen_search_icon {
width: 1.5rem;
height: 1.5rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/searchIcon.png);
background-repeat: no-repeat;
background-size: contain;
margin: auto .75rem;
}
.listen_search_input {
width: auto;
height: 1.25rem;
line-height: 1.25rem;
font-size: .875rem;
color: #c5c5c5;
margin: auto auto auto 0;
}
}
.listen_banner {
width: calc(100% - 2rem);
height: calc((100vw - 2rem) / 1920 * 800);
background-color: #000;
margin: 1rem 1rem 0 1rem;
border-radius: .5rem;
.swiper_container {
width: 100%;
height: 100%;
border-radius: .5rem;
.swiper_item {
width: 100%;
height: 100%;
border-radius: .5rem;
.swiper_item_img {
width: 100%;
height: 100%;
border-radius: .5rem;
}
}
}
}
.listen_type {
width: calc(100% - 2rem);
height: 4.3125rem;
margin: 1rem 1.25rem 0 1.25rem;
display: flex;
gap: calc((100vw - 2.5rem - 15rem) / 4);
.item {
width: 3rem;
height: 100%;
// margin: auto;
display: flex;
flex-direction: column;
.icon {
width: 3rem;
height: 3rem;
}
.name {
width: 100%;
height: 1.0625rem;
line-height: 1.0625rem;
font-weight: 600;
font-size: .75rem;
text-align: center;
margin: auto auto auto 0;
}
}
}
.listen_area {
width: calc(100% - 2rem);
margin: 1rem 1rem 0 1rem;
height: auto;
display: flex;
flex-direction: column;
gap: 1rem;
.item {
width: 100%;
height: 12.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
.header {
width: 100%;
height: 1.5rem;
display: flex;
.title {
width: auto;
height: 1.5rem;
line-height: 1.4375rem;
font-weight: 600;
font-size: 1rem;
margin: auto auto auto 0;
}
.more {
width: auto;
height: 1.0625rem;
line-height: 1.0625rem;
font-size: .75rem;
margin: auto 0 auto auto;
}
.more_icon {
width: 1.5rem;
height: 1.5rem;
background-image: url(../../assets/listen/next.png);
background-repeat: no-repeat;
background-size: contain;
margin: auto 0 auto 0;
}
}
.selection {
width: 100%;
height: auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: .6875rem;
.item {
width: 100%;
height: calc(((100vw - 2rem - 1.375rem) / 3) + 3rem);
display: flex;
flex-direction: column;
gap: 0;
.icon {
width: 100%;
height: calc((100vw - 2rem - 1.375rem) / 3);
border-radius: .75rem;
margin: 0 auto auto auto;
}
.title {
line-height: 1.25rem;
width: 100%;
height: 2.5rem;
font-size: .875rem;
font-weight: 600;
margin: auto auto 0 auto;
}
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.free_item_label {
position: absolute;
left: calc(100% - 3rem);
top: calc((100vw - 2rem - 1.375rem) / 3 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.free_item_label_text {
font-size: .5rem;
margin: auto;
}
}
}
}
}
}
}
}

@ -0,0 +1,314 @@
import { Swiper, SwiperItem, View, Image, Text } from '@tarojs/components'
import React, { useEffect, useState } from 'react'
import Taro, { useDidShow } from '@tarojs/taro'
import './index.less'
import GetPhoneNumber from '../../components/getPhoneModal'
// const areaList = [
// {
// index: 0,
// name: '免费专区',
// child: [
// {
// index: 0,
// icon: '',
// title: 'daaswcaw',
// },
// {
// index: 1,
// icon: '',
// title: 'dawawd',
// },
// {
// index: 2,
// icon: '',
// title: 'dawdawd',
// },
// ]
// },
// {
// index: 1,
// name: '哄睡故事',
// child: [
// {
// index: 0,
// icon: '',
// title: 'tgdwcaw',
// },
// {
// index: 1,
// icon: '',
// title: 'dfdd',
// },
// {
// index: 2,
// icon: '',
// title: 'vsawd',
// },
// ]
// },
// {
// index: 2,
// name: '牛魔王',
// child: [
// {
// index: 0,
// icon: '',
// title: 'dewqeqwcaw',
// },
// {
// index: 1,
// icon: '',
// title: 'eqweqwwd',
// },
// {
// index: 2,
// icon: '',
// title: 'fcwwdawd',
// },
// ]
// },
// ]
export default function Listen() {
//首页banner图集
const [bannerList, setbannerList] = useState([])
const [typeList, settypeList] = useState([])
const [areaList, setareaList] = useState([])
//判断是否登录
const [isGetUsePhone, setisGetUsePhone] = useState(false) //false
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
useDidShow(() => {
if(Taro.getStorageSync('UserToken')){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/index',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页banner及金刚区接口请求成功' ,res.data)
setbannerList(res.data.data.banner)
settypeList(res.data.data.head)
}
})
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/operation',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页运营数据接口请求成功' ,res.data)
setareaList(res.data.data.show)
}
})
}else{
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/index',
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页banner及金刚区接口请求成功' ,res.data)
setbannerList(res.data.data.banner)
settypeList(res.data.data.head)
}
})
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/operation',
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页运营数据接口请求成功' ,res.data)
setareaList(res.data.data.show)
}
})
}
})
useEffect(() => {
if(isGetUsePhone){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/index',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页banner及金刚区接口请求成功' ,res.data)
setbannerList(res.data.data.banner)
settypeList(res.data.data.head)
}
})
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/operation',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
},
success: (res)=> {
console.log('熏听首页运营数据接口请求成功' ,res.data)
setareaList(res.data.data.show)
}
})
}
}, [isGetUsePhone])
const handleTypeClick = (index: string) => {
if(index === "03"){
Taro.navigateTo({
url: '/pages/ListenType/MainType/index'
})
}else{
Taro.navigateTo({
url: '/pages/ListenType/SingleType/index?index=' + index
})
}
}
const handleAreaClick = (index: number) => {
Taro.navigateTo({
url: '/pages/ListenRegion/index?index=' + index
})
}
const handleDetail = (prdtId: number) => {
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + prdtId
})
}
return (
<View className='listen_bg'>
<View
className='listen_search'
onClick={()=>{
Taro.navigateTo({
url: '/pages/ListenSearch/index'
})
}}
>
<View className='listen_search_icon'></View>
<View className='listen_search_input'></View>
</View>
<View className='listen_banner'>
<Swiper
className='swiper_container'
circular
indicatorDots
indicatorColor='#999'
indicatorActiveColor='#333'
autoplay
>
{
bannerList.map((item: any, index: number) => (
<SwiperItem
className='swiper_item'
key={index}
onClick={()=>{}}
>
<Image className='swiper_item_img' src={item.url} mode='scaleToFill'></Image>
</SwiperItem>
))
}
</Swiper>
</View>
<View className='listen_type'>
{
typeList.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={() => {handleTypeClick(item.site_class)}}
>
<Image
className='icon'
src={item.url}
></Image>
<View className='name'>{item.title}</View>
</View>
))
}
</View>
<View className='listen_area'>
{
areaList.map((item: any, index: number) => (
<View
key={index}
className='item'
>
<View className='header'
onClick={()=>handleAreaClick(item.site_id)}
>
<View className='title'>{item.title}</View>
<View className='more'></View>
<View className='more_icon' ></View>
</View>
<View className='selection'>
{
item.products.map((child: any, c_index: number) => (
<View
key={c_index}
className='item'
onClick={()=>handleDetail(child.PrdtId)}
>
{
item.is_free === 1 &&
<View className='relative_container'>
<View className='free_item_label'>
<Text className='free_item_label_text'></Text>
</View>
</View>
}
<Image
className='icon'
src={child.PrdtCover}
lazyLoad
></Image>
<View className='title'>{child.PrdtTitle}</View>
</View>
))
}
</View>
</View>
))
}
</View>
<GetPhoneNumber
onClose={setisGetUsePhone}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
</View>
)
}

@ -0,0 +1,19 @@
import { View, WebView } from '@tarojs/components'
import { useLoad } from '@tarojs/taro'
import React, { useState } from 'react'
export default function ListenBookDisplay() {
const [prdtId, setprdtId] = useState(-1)
useLoad((query)=> {
console.log(query.prdtId)
setprdtId(query.prdtId)
})
return (
<WebView
src={`https://audioplay.jm-kid.com/listen?prdtId=${prdtId}`}
></WebView>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,189 @@
.listendetail_bg {
width: 100vw;
min-height: 100vh;
height: auto;
display: flex;
flex-direction: column;
.header {
width: calc(100%- 2rem);
height: calc(8.875rem - 2rem);
padding: 1rem;
display: flex;
.icon {
width: 7.5rem;
height: 7.5rem;
border-radius: .75rem;
}
.content {
width: calc(100% - 7.5rem - 2rem);
height: auto;
padding: 0 1rem;
display: flex;
flex-direction: column;
.title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
font-size: 1.125rem;
font-weight: 600;
line-height: 1.625rem;
margin: auto auto 0 0;
overflow: hidden;
}
.subtitle {
width: 100%;
font-size: .875rem;
height: 1.25rem;
line-height: 1.25rem;
color: rgba(0, 0, 0, .6);
margin: .5rem auto 0 0;
white-space: nowrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
line-clamp: 1;
}
.tags {
width: 100%;
height: 1rem;
display: flex;
gap: .25rem;
margin: .5rem auto auto 0;
.tag {
width: auto;
padding: .0625rem .5625rem;
background-color: #3ba366;
color: #fff;
font-size: .625rem;
border-radius: .375rem;
}
}
}
}
.chooseBar {
width: calc(100% - 12.5rem);
padding: 0 6.25rem;
display: flex;
.item {
width: 4.5rem;
height: 2.5rem;
display: flex;
flex-direction: column;
margin: 0 calc((100vw - 12.5rem - 9rem) / 4);
.title {
font-size: .75rem;
line-height: 1.0625rem;
height: 1.0625rem;
color: rgba(0, 0, 0, .6);
margin: auto;
}
.line {
width: 1rem;
height: .25rem;
background-color: #3ba366;
border-radius: .9375rem;
margin: auto;
}
}
}
.MusicList {
width: 100%;
height: auto;
display: flex;
flex-direction: column;
.item {
width: 100%;
border-top: .0625rem solid #d9d9d9;
display: flex;
.content {
width: 100vw;
height: 4.75rem;
margin: auto 0 auto 2rem;
display: flex;
flex-direction: column;
.title {
width: auto;
height: 1.5rem;
font-weight: 600;
font-size: 1rem;
line-height: 1.4375rem;
margin: auto auto .25rem 0;
}
.subtitle {
width: calc(100vw - 1rem - 1.875rem - 4rem);
height: 1.25rem;
font-size: .875rem;
line-height: 1.25rem;
color: rgba(0, 0, 0, .6);
margin: 0 auto .25rem 0;
white-space: nowrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
line-clamp: 1;
}
.duration {
width: 3.75rem;
height: .875rem;
font-size: .875rem;
line-height: .875rem;
color: rgba(0, 0, 0, .3);
margin: .25rem auto auto .375rem;
}
.duration::before {
content: '';
display: inline-block;
margin-right: 6px;
width: .75rem;
height: .75rem;
background-image: url(../../assets/listen/music.png);
background-repeat: no-repeat;
background-size: contain;
}
}
.next {
width: 1.875rem;
height: 1.875rem;
background-image: url(../../assets/listen/musicListNext.png);
background-repeat: no-repeat;
background-size: contain;
margin: auto 2rem auto auto;
}
}
}
.introduction {
width: 100%;
height: auto;
border-top: .0625rem solid #d9d9d9;
display: flex;
.text {
margin: 1rem 2rem 0 2rem;
width: calc(100% - 4rem);
height: calc(100vh - 9.5rem - 2.5rem - .0625rem);
line-height: 1.4375rem;
font-size: .875rem;
white-space: normal;
word-wrap: break-word;
}
}
}

@ -0,0 +1,246 @@
import { View, Image, Text } from '@tarojs/components'
import React, { useEffect, useState } from 'react'
import Taro, { useLoad } from '@tarojs/taro'
import './index.less'
import GetPhoneNumber from '../../components/getPhoneModal'
import GoToStoreModal from '../../components/goToStoreModal'
interface DetailProps {
IsFree: boolean
IsSubscribed: number
MallLink: string
Product: {
PrdtCover: string
PrdtId: number
PrdtKeys: string[]
PrdtSubtitle: string
PrdtTitle: string
PrdtDescription: string
}
Resources: {
ResDuration: number
ResId: number
ResSeries: string
ResSubtitle: string
ResTitle: string
}[]
}
export default function ListenDetail() {
const [chooseIndex, setchooseIndex] = useState(0)
const [detailData, setdetailData] = useState<DetailProps>({
IsFree: false,
IsSubscribed: 0,
MallLink: '',
Product: {
PrdtCover: '',
PrdtId: 0,
PrdtKeys: [''],
PrdtSubtitle: '',
PrdtTitle: '',
PrdtDescription: ''
},
Resources: [
{
ResDuration: 0,
ResId: 0,
ResSeries: '',
ResSubtitle: '',
ResTitle: '',
}
],
})
//判断是否登录
const [isGetUsePhone, setisGetUsePhone] = useState(Taro.getStorageSync('UserToken') ? true : false) //false
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
const [isToStoreOpen, setisToStoreOpen] = useState(false)
//管理跳转页面路径
const [prdtMallLink, setprdtMallLink] = useState('')
//记录prdtId
const [queryId, setqueryId] = useState('')
useLoad((query) => {
setqueryId(query.prdtId)
if(!isGetUsePhone){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/product/detail',
data: {
timestamp: Date.now(),
prdt_id: query.prdtId
},
success: (res) => {
console.log('获取熏听产品详情数据请求成功' ,res.data)
setdetailData(res.data.data)
}
})
}
})
const formatSecondsToTime = (seconds: number) => {
// 将秒数转换为整数秒和毫秒
const totalSeconds = Math.floor(seconds);
// 分钟数
const minutes = Math.floor(totalSeconds / 60);
// 剩余秒数
const remainingSeconds = totalSeconds % 60;
// 补零操作
const formattedMinutes = minutes.toString().padStart(2, '0');
const formattedSeconds = remainingSeconds.toString().padStart(2, '0');
return `${formattedMinutes}:${formattedSeconds}`;
}
const handleDisplay = (prdtId: number, resId: number, IsSubscribed: number) => {
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
}else{
console.log('IsSubscribed=>', IsSubscribed)
if(IsSubscribed === -1){
//未订阅,跳转商城
setprdtMallLink(detailData.MallLink)
setisToStoreOpen(true)
}else{
Taro.navigateTo({
url: '/pages/ListenDisplay/index?prdtId=' + prdtId + '&resId=' + resId
})
}
}
}
useEffect(()=> {
console.log('isGetUsePhone=>', isGetUsePhone)
if(isGetUsePhone && queryId){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/product/detail',
header: {
'authorization': 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
timestamp: Date.now(),
prdt_id: queryId
},
success: (res) => {
console.log('获取熏听产品详情数据请求成功' ,res.data)
setdetailData(res.data.data)
}
})
}
}, [isGetUsePhone, queryId])
return (
<View className='listendetail_bg'>
<View className='header'>
<Image
src={detailData.Product.PrdtCover}
className='icon'
></Image>
<View className='content'>
<View className='title'>{detailData.Product.PrdtTitle}</View>
<View className='subtitle'>{detailData.Product.PrdtDescription}</View>
<View className='tags'>
{
detailData.Product.PrdtKeys.map((item, index) => (
index < 2 &&<View
className='tag'
key={index}
>
{item}
</View>
))
}
</View>
</View>
</View>
<View className='chooseBar'>
<View
className='item'
onClick={() => {setchooseIndex(0)}}
>
<View
className='title'
style={chooseIndex === 0 ? {color: '#3ba366', fontWeight: '600', fontSize: '1rem'} : {}}
>
</View>
{
chooseIndex === 0 && <View className='line'></View>
}
</View>
<View
className='item'
onClick={() => {setchooseIndex(1)}}
>
<View
className='title'
style={chooseIndex === 1 ? {color: '#3ba366', fontWeight: '600', fontSize: '1rem'} : {}}
>
</View>
{
chooseIndex === 1 && <View className='line'></View>
}
</View>
</View>
{
chooseIndex === 0 &&
<View className='MusicList'>
{
detailData.Resources.map((item, index) => (
<View
key={index}
className='item'
onClick={() => {handleDisplay( detailData.Product.PrdtId ,item.ResId, detailData.IsSubscribed)}}
>
<View className='content'>
<View className='title'>{item.ResTitle}</View>
{/* <View className='subtitle'>{item.ResSubtitle}</View> */}
<View className='duration'>{formatSecondsToTime(item.ResDuration)}</View>
</View>
<View className='next'></View>
</View>
))
}
</View>
}
{
chooseIndex === 1 &&
<View className='introduction'>
<Text className='text'>
{detailData.Product.PrdtDescription}
</Text>
</View>
}
<GetPhoneNumber
onClose={setisGetUsePhone}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
<GoToStoreModal
visible={isToStoreOpen}
onClose={() => setisToStoreOpen(false)}
type={0}
mallLink={prdtMallLink}
setmallLink={setprdtMallLink}
></GoToStoreModal>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '播放',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,22 @@
import { View, WebView } from '@tarojs/components'
import { useLoad } from '@tarojs/taro'
import React, { useState } from 'react'
export default function ListenDisplay() {
const [prdtId, setprdtId] = useState(-1)
const [resId, setresId] = useState(-1)
useLoad((query)=> {
console.log(query.prdtId, query.resId)
setprdtId(query.prdtId)
setresId(query.resId)
})
return (
<WebView
src={`https://audioplay.jm-kid.com?prdtId=${prdtId}&resId=${resId}`}
></WebView>
)
}

@ -0,0 +1,5 @@
export default {
navigationStyle: 'custom',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,90 @@
.listenRegion_bg {
width: 100vw;
height: 100vh;
.header {
width: 100vw;
height: 3.75rem;
margin-top: 2.75rem;
display: flex;
.back {
width: 1.25rem;
height: 1.25rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/turnBack.png);
background-repeat: no-repeat;
background-size: contain;
margin: auto 0 auto 1rem;
}
.title {
width: 6.25rem;
height: 1.625rem;
font-weight: 600;
font-size: 1.125rem;
text-align: center;
margin: auto auto auto calc(50vw - 3.125rem - 1.25rem - 1rem);
}
}
.container {
width: calc(100vw - 2rem);
// height: calc(100vh - 6.5rem - 1rem);
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: .5625rem;
padding: 0 1rem;
.item {
width: 100%;
height: calc((100vw - 2rem - 1.125rem) / 3 + 3rem);
.icon {
width: 100%;
height: calc((100vw - 2rem - 1.125rem) / 3);
border-radius: .75rem;
background-color: #000;
margin-bottom: .5rem;
}
.title {
width: 100%;
height: 2.5rem;
font-size: .875rem;
font-weight: 600;
}
}
}
.acContainer {
.acItem {
width: calc(100vw - 2rem);
// height: calc(100vh - 6.5rem - 1rem);
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: .5625rem;
padding: 1rem;
.item {
width: calc((100vw - 2rem - 1.125rem) / 3);
height: calc((100vw - 2rem - 1.125rem) / 3 + 3rem);
.icon {
width: 100%;
height: calc((100vw - 2rem - 1.125rem) / 3);
border-radius: .75rem;
background-color: #000;
margin-bottom: .5rem;
}
.title {
width: 100%;
height: 2.5rem;
font-size: .875rem;
font-weight: 600;
}
}
}
}
}

@ -0,0 +1,169 @@
import { ScrollView, View, Image } from '@tarojs/components'
import React, { useState } from 'react'
import Taro, { useLoad } from '@tarojs/taro'
import { AtAccordion } from 'taro-ui'
import './index.less'
export default function ListenRegion() {
const [regionList, setregionList] = useState<any>([])
const [ifMB, setifMB] = useState(false)
const [isAcOpen, setisAcOpen] = useState(
regionList.reduce((acc, option) => ({ ...acc, [option.title]: true }), {})
)
const [isAcItem, setisAcItem] = useState<any[]>(
regionList.map(option => option.id)
)
useLoad((query)=>{
console.log('query=>', query.index)
if(Taro.getStorageSync('UserToken')){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/show/product',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
site_id: query.index
},
success: (res)=> {
console.log('region接口请求成功' ,res.data)
if(res.data.data.show.site_id === 334){
setifMB(true)
setregionList(res.data.data.show.grouped_products)
}else{
setregionList(res.data.data.show.products)
}
setpageTitle(res.data.data.show.title)
const initialStates = res.data.data.show.grouped_products.reduce((acc, option) => ({ ...acc, [option.title]: true }), {});
console.log('initialStates', initialStates)
setisAcOpen(initialStates)
setisAcItem(res.data.data.show.grouped_products.map(option => option.id))
console.log('isAcOpen', isAcOpen)
console.log('isAcItem', isAcItem)
}
})
}else{
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/show/product',
data: {
timestamp: Date.now(),
site_id: query.index
},
success: (res)=> {
console.log('region接口请求成功' ,res.data)
if(res.data.data.show.site_id === 334){
setifMB(true)
setregionList(res.data.data.show.grouped_products)
}else{
setregionList(res.data.data.show.products)
}
setpageTitle(res.data.data.show.title)
}
})
}
})
const [pageTitle, setpageTitle] = useState('')
const handleBack = () => {
Taro.navigateBack()
}
const handleDetail = (prdtId: number) => {
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + prdtId
})
}
return (
<View className='listenRegion_bg'>
<View className='header'>
<View
className='back'
onClick={handleBack}
></View>
<View className='title'>{pageTitle}</View>
</View>
<View className='container'>
{
!ifMB && regionList.map((item, index) => (
<View
key={index}
className='item'
onClick={()=>handleDetail(item.PrdtId)}
>
<Image
className='icon'
src={item.PrdtCover}
></Image>
<View className='title'>{item.PrdtTitle}</View>
</View>
))
}
</View>
<View
className='acContainer'
>
{
ifMB && regionList.map((item: any, index: number) => (
<AtAccordion
key={index}
open={isAcOpen[item.title]}
title={item.title}
onClick={() => {
// 更新选项状态
setisAcOpen(prevStates => ({
...prevStates,
[item.title]: !prevStates[item.title],
}));
// 更新已选选项
if (isAcItem.includes(index)) {
setisAcItem(isAcItem.filter(i => i !== index));
} else {
setisAcItem([...isAcItem, index]);
}
console.log('isAcOpen', isAcOpen)
console.log('isAcItem', isAcItem)
}}
style={{
display: 'flex',
flexDirection: 'row',
}}
>
<View className='acItem'>
{
item.list.map((acitem, acindex) => (
<View
key={acindex}
className='item'
onClick={()=>handleDetail(acitem.prdt_id)}
>
<Image
className='icon'
src={acitem.prdt_cover}
></Image>
<View className='title'>{acitem.prdt_title}</View>
</View>
))
}
</View>
</AtAccordion>
))
}
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '搜索',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,230 @@
.search_bg {
width: calc(100vw - 2rem);
height: calc(100vh - 1rem);
display: flex;
flex-direction: column;
padding: 1rem 1rem 0 1rem;
.subscribe_header {
width: 100%;
height: 2.75rem;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
.subscribe_header_input {
width: calc(100% - 2.5rem - 4rem);
height: 2.5rem;
background: #f8f8f8;
border-radius: 2.25rem;
padding-left: 3rem;
border: .0625rem solid green;
}
.subscribe_header_dressing {
width: 2.5rem;
height: 1.5rem;
font-weight: 600;
font-size: 1rem;
margin: auto 0 auto auto;
}
.subscribe_header_scanCodeBtn {
position: absolute;
top: 1.5625rem;
left: 2rem;
width: 1.5rem;
height: 1.5rem;
}
.subscribe_header_errorIcon {
position: absolute;
top: 1.5625rem;
right: calc(2rem + 3.375rem);
width: 1.5rem;
height: 1.5rem;
z-index: 999;
}
.subscribe_header_searchContainer {
position: relative;
width: 0;
height: 2.5rem;
top: calc(2.5rem + .125rem);
left: 0;
.subscribe_searchContainer {
position: absolute;
left: 1.125rem;
width: calc(100vw - 2rem - 3.375rem - 2.25rem);
height: auto;
background: #fafafa;
display: flex;
flex-direction: column;
z-index: 999;
opacity: .9;
.subscribe_searchItem {
// width: 100%;
width: auto;
height: 2.5rem;
background: #fff;
border: .0625rem solid #f8f8f8;
display: flex;
flex-direction: row;
.subscribe_searchItem_cover {
width: 2.5rem;
height: 2.5rem;
}
.subscribe_searchItem_title {
width: auto;
font-size: 1.125rem;
font-weight: 600;
margin: auto .25rem;
}
}
}
}
}
.subscribe_selection {
width: 100%;
height: 1.5rem;
display: flex;
flex-direction: row;
gap: 1rem;
margin-bottom: 1rem;
.subscribe_selection_item {
width: 2.5rem;
height: 1.5rem;
margin: auto 0;
display: flex;
.subscribe_selection_item_text {
margin: auto;
}
}
}
.subscribe_content {
width: 100%;
height: calc(100% - 3.75rem - 2.5rem);
display: flex;
flex-direction: column;
.subscribe_container {
display: grid;
grid-template-columns: repeat(3, 1fr);
// height: auto;
gap: .625rem;
.subscribe_content_singleItem {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3 + .5rem + 2.5rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc((100vw - 2rem - 1.25rem) / 3 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3);
border-radius: .75rem;
margin-bottom: auto;
}
.subscribe_content_singleItem_title {
width: 100%;
height: 2.5rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
}
}
.subscribe_content_collectionItem {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625 + .5rem + 2rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc(((100vw - 2rem - .625rem) / 2) * .5625 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625);
border-radius: .75rem;
margin-bottom: .625rem;
}
.subscribe_content_singleItem_title {
width: calc(((100vw - 2rem - .625rem) / 2));
height: 1.25rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
white-space: nowrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
margin-bottom: 0;
}
.subscribe_content_collectionItem_count {
height: .625rem;
line-height: .625rem;
font-size: .625rem;
color: rgba(0, 0, 0, .3);
}
}
}
}
}

@ -0,0 +1,201 @@
import { Input, View, Image, Text, ScrollView } from '@tarojs/components'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import React, { useState } from 'react'
import searchIcon from '../../assets/images/searchIcon.png'
import errorIcon from '../../assets/images/error.png'
import './index.less'
// 自定义防抖 Hook
function useDebounce<T>(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void {
let timeoutId: ReturnType<typeof setTimeout> | null = null;
return (...args: any[]): void => {
//@ts-ignore
clearTimeout(timeoutId);
timeoutId = setTimeout(() => callback(...args), delay);
};
}
// 自定义节流 Hook
function useThrottle<T>(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void {
let lastCallTime: number | null = null;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
return (...args: any[]): void => {
const now = Date.now();
if (lastCallTime === null || now - lastCallTime >= delay) {
lastCallTime = now;
callback(...args);
} else if (!timeoutId) {
timeoutId = setTimeout(() => {
lastCallTime = now;
callback(...args);
timeoutId = null;
}, delay - (now - (lastCallTime as number)));
}
};
}
export default function SearchDetail() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
//单本订阅列表
const [userSubscribeSingleList, setuserSubscribeSingleList] = useState([])
//套装订阅列表
const [userSubscribeCollectionList, setuserSubscribeCollectionList] = useState([])
//管理登录弹窗
const [isGetUsePhone, setisGetUsePhone] = useState(false)
const [searchText, setSearchText] = useState<string>('');
const [searchSingleResults, setSearchSingleResults] = useState<any[]>()
const [searchCollectionResults, setsearchCollectionResults] = useState<any[]>()
const [userSelect, setuserSelect] = useState(0)
// 搜索逻辑
const handleSearch = (value: string) => {
if(value){
//搜索单本结果
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/search/product',
data: {
timestamp: Date.now(),
title: value,
},
success: (res: any) => {
console.log('依据专辑标题搜索熏听专辑列表', res.data)
setSearchSingleResults(res.data.data.products)
}
})
}
// console.log('searchSingle=>', searchSingle)
// setSearchSingleResults(searchSingle)
};
// 使用防抖和节流 Hooks
const debouncedHandleSearch = useDebounce(handleSearch, 300);
const throttledHandleSearch = useThrottle(handleSearch, 500);
// 监听输入框的变化
const handleInputChange = (event: any) => {
setSearchText(event.detail.value);
debouncedHandleSearch(event.detail.value);
throttledHandleSearch(event.detail.value);
};
//跳转详情页
const handleToCollectionDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + id
})
}
const handleToSingleDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + id
})
}
//点击取消按钮清楚搜索栏
const handleClearResearch = () => {
console.log('点击取消按钮清楚搜索栏')
setSearchText('')
}
useLoad(() => {
if(!Taro.getStorageSync('UserToken')){
setisGetUsePhone(true)
}
})
return (
<View className='search_bg'>
<View className='subscribe_header'>
<View
className='subscribe_header_searchContainer'
>
</View>
<Input
className='subscribe_header_input'
placeholder='请输入搜索内容'
value={searchText}
onInput={handleInputChange}
></Input>
<View
className='subscribe_header_dressing'
// onClick={() => setisPopupOpen(!isPopupOpen)}
></View>
<Image
className='subscribe_header_scanCodeBtn'
src='https://oss.jm-kid.com/wx_5colorflower/searchIcon.png'
// onClick={handleScanCode}
></Image>
<Image
src='https://oss.jm-kid.com/wx_5colorflower/error.png'
className='subscribe_header_errorIcon'
onClick={()=>handleClearResearch()}
></Image>
</View>
{/* 列表渲染 */}
<ScrollView
scrollY
scrollWithAnimation
className='subscribe_content'
enableFlex
>
<View
className='subscribe_container'
style={userSelect === 0 ? {gridTemplateColumns: 'repeat(3, 1fr)'} : {gridTemplateColumns: 'repeat(2, 1fr)'}}
>
{
searchSingleResults && searchSingleResults.length > 0 &&searchSingleResults.map((item: any, index: number) => (
<View
className='subscribe_content_singleItem'
key={index}
onClick={() => handleToSingleDetail(item.PrdtId)}
>
{
item.isFree === 1 && (
<View className='relative_container'>
<View className='subscribe_content_singleItem_label'>
<Text className='subscribe_content_singleItem_label_text'></Text>
</View>
</View>
)
}
<Image
className='subscribe_content_singleItem_cover'
src={item.PrdtCover}
mode='aspectFill'
lazyLoad
></Image>
<View className='subscribe_content_singleItem_title'>{item.PrdtTitle}</View>
</View>
))
}
</View>
</ScrollView>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '全部分类',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,123 @@
.main_bg {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
.main_top {
width: 100vw;
height: 2.5rem;
.top_container {
width: 100%;
height: 2.5rem;
display: flex;
overflow-y: hidden;
overflow-x: scroll;
.item {
flex: 0 0 auto;
width: 5rem;
height: 100%;
display: flex;
flex-direction: column;
margin: 0 .5rem 0 0;
.title {
width: 100%;
height: 1.0625rem;
line-height: 1.0625rem;
font-size: .75rem;
color: rgba(0, 0, 0, .6);
text-align: center;
margin: auto;
}
.line {
width: 1rem;
height: .25rem;
border-radius: .9375rem;
background-color: #3ba366;
margin: auto;
}
}
}
}
.main_context {
width: 100vw;
height: calc(100vh - 2.5rem);
display: flex;
// background: #000;
.type_container {
width: 4.3rem;
height: 100%;
padding-left: .2rem;
.typelist {
width: 4.5rem;
height: calc(100vh - 2.5rem);
.item {
width: 100%;
height: 2.5rem;
display: flex;
.line {
width: .1875rem;
height: .625rem;
border-radius: 1.0625rem;
background-color: #3ba366;
margin: auto .3125rem auto 0;
}
.title {
height: 1.0625rem;
line-height: 1.0862rem;
font-size: .75rem;
margin: auto auto auto 0;
}
}
}
}
.product_container {
width: calc(100vw - 4.5rem);
height: 100%;
.product {
width: 100%;
height: calc(100vh - 2.5rem);
.container {
width: calc(100% - 1rem);
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: .8125rem;
padding: 0 .5rem;
.item {
width: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
height: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3 + 3rem);
.icon {
width: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
height: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
border-radius: .5rem;
margin-bottom: .25rem;
}
.title {
font-weight: 600;
line-height: 1.25rem;
font-size: .875rem;
}
}
}
}
}
}
}

@ -0,0 +1,275 @@
import { ScrollView, View, Image } from '@tarojs/components'
import React, { useEffect, useState } from 'react'
import Taro, { useLoad } from '@tarojs/taro'
import './index.less'
// const typeList = [
// {
// index: 0,
// name: '全部',
// },
// {
// index: 1,
// name: '听儿歌',
// },
// {
// index: 2,
// name: '听故事',
// },
// {
// index: 3,
// name: '听英语',
// },
// {
// index: 4,
// name: '听国学',
// },
// ]
// const typetypeList = [
// {
// index: 0,
// name: 'dqwsq'
// },
// {
// index: 1,
// name: 'dqwsq'
// },
// {
// index: 2,
// name: 'dqwsq'
// },
// {
// index: 3,
// name: 'dqwsq'
// },
// {
// index: 4,
// name: 'dqwsq'
// },
// {
// index: 5,
// name: 'dqwsq'
// },
// {
// index: 6,
// name: 'dqwsq'
// },
// {
// index: 7,
// name: 'dqwsq'
// },
// {
// index: 8,
// name: 'dqwsq'
// },
// {
// index: 9,
// name: 'dqwsq'
// },
// {
// index: 10,
// name: 'dqwsq'
// },
// {
// index: 11,
// name: 'dqwsq'
// },
// {
// index: 12,
// name: 'dqwsq'
// },
// {
// index: 13,
// name: 'dqwsq'
// },
// {
// index: 14,
// name: 'dqwsq'
// },
// {
// index: 15,
// name: 'dqwsq'
// },
// {
// index: 16,
// name: 'dqwsq'
// },
// {
// index: 17,
// name: 'dqwsq'
// },
// {
// index: 18,
// name: 'dqwsq'
// },
// {
// index: 19,
// name: 'dqwsq'
// },
// {
// index: 20,
// name: 'dqwsq'
// },
// {
// index: 21,
// name: 'dqwsq'
// },
// ]
export default function MainType() {
const [chooseType, setchooseType] = useState(0)
const [choooseTypeType, setchoooseTypeType] = useState<number | string>('')
const [typeList, settypeList] = useState<any>([])
const [typeCode, settypeCode] = useState('')
const [typetypeList, settypetypeList] = useState<any>([])
useLoad(()=>{
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/category',
data: {
timestamp: Date.now(),
},
success: (res) => {
console.log('熏听区两级分类数据请求成功' ,res.data)
let data = res.data.data.category
// res.data.data.category[0].children = [
// {
// class_code: "03",
// class_name: "全部",
// }
// ]
console.log('熏听区两级分类数据处理后的数据', data)
settypeList(data)
}
})
})
useEffect(()=> {
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/class/product',
data: {
timestamp: Date.now(),
class_code: typeCode
},
success: (res) => {
console.log('获取金刚区内容列表数据请求成功' ,res.data)
settypetypeList(res.data.data.products)
}
})
}, [typeCode])
const handleChooseType = (index: number) => {
console.log('选择的分类', index)
setchooseType(index)
setchoooseTypeType('')
settypeCode(typeList[index].class_code)
}
const handleChooseTypeType = (index: number) => {
setchoooseTypeType(index)
settypeCode(typeList[chooseType].children[index].class_code)
}
const handleDetail = (prdtId: number) => {
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + prdtId
})
}
return (
<View className='main_bg'>
<ScrollView
scrollX
scrollWithAnimation
className='main_top'
>
<View className='top_container'>
{
typeList.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={() => handleChooseType(index)}
>
<View
className='title'
style={chooseType === index? {color: '#3ba366', fontSize: '1rem', fontWeight: '600'} : {}}
>
{item.class_name}
</View>
{
chooseType === index && <View className='line'></View>
}
</View>
))
}
</View>
</ScrollView>
<View className='main_context'>
<View className='type_container'>
<ScrollView
className='typelist'
scrollY
scrollWithAnimation
>
{
typeList && chooseType !== -1 && typeList[chooseType] && typeList[chooseType].children.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={()=>handleChooseTypeType(index)}
>
{
choooseTypeType === index && <View className='line'></View>
}
<View
className='title'
style={choooseTypeType === index? {color: '#3ba366'} : {}}
>{item.class_name}</View>
</View>
))
}
</ScrollView>
</View>
<View className='product_container'>
<ScrollView
className='product'
scrollY
scrollWithAnimation
>
<View className='container'>
{
typetypeList.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={()=>handleDetail(item.PrdtId)}
>
<Image
className='icon'
src={item.PrdtCover}
lazyLoad
></Image>
<View className='title'>{item.PrdtTitle}</View>
</View>
))
}
</View>
</ScrollView>
</View>
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationStyle: 'custom',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,108 @@
.singleType_bg {
width: 100vw;
height: 100vh;
overflow: hidden;
.header {
width: 100vw;
height: 3.75rem;
margin-top: 2.75rem;
display: flex;
.back {
width: 1.25rem;
height: 1.25rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/turnBack.png);
background-repeat: no-repeat;
background-size: contain;
margin: auto 0 auto 1rem;
}
.title {
width: 6.25rem;
height: 1.625rem;
font-weight: 600;
font-size: 1.125rem;
text-align: center;
margin: auto auto auto calc(50vw - 3.125rem - 1.25rem - 1rem);
}
}
.main_context {
width: 100vw;
height: calc(100% - 6.5rem - 1rem);
display: flex;
margin-top: 1rem;
// background: #000;
.type_container {
width: 4.5rem;
height: 100%;
.typelist {
width: 4.5rem;
height: calc(100vh - 6.5rem - 1rem);
.item {
width: 100%;
height: 2.5rem;
display: flex;
.line {
width: .1875rem;
height: .625rem;
border-radius: 1.0625rem;
background-color: #3ba366;
margin: auto .3125rem auto 0;
}
.title {
height: 1.0625rem;
line-height: 1.0862rem;
font-size: .75rem;
margin: auto auto auto 0;
}
}
}
}
.product_container {
width: calc(100vw - 4.5rem);
height: 100%;
.product {
width: 100%;
height: calc(100vh - 6.5rem - 1rem);
.container {
width: calc(100% - 1rem);
height: auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: .8125rem;
padding: 0 .5rem;
.item {
width: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
height: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3 + 3rem);
.icon {
width: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
height: calc((100vw - 4.5rem - 1rem - 1.625rem) / 3);
border-radius: .5rem;
margin-bottom: .25rem;
}
.title {
font-weight: 600;
line-height: 1.25rem;
font-size: .875rem;
}
}
}
}
}
}
}

@ -0,0 +1,235 @@
import { ScrollView, View , Image} from '@tarojs/components'
import React, { useEffect, useState } from 'react'
import Taro, { useDidShow, useLoad } from '@tarojs/taro'
import './index.less'
// const typetypeList = [
// {
// index: 0,
// name: 'dqwsq'
// },
// {
// index: 1,
// name: 'dqwsq'
// },
// {
// index: 2,
// name: 'dqwsq'
// },
// {
// index: 3,
// name: 'dqwsq'
// },
// {
// index: 4,
// name: 'dqwsq'
// },
// {
// index: 5,
// name: 'dqwsq'
// },
// {
// index: 6,
// name: 'dqwsq'
// },
// {
// index: 7,
// name: 'dqwsq'
// },
// {
// index: 8,
// name: 'dqwsq'
// },
// {
// index: 9,
// name: 'dqwsq'
// },
// {
// index: 10,
// name: 'dqwsq'
// },
// {
// index: 11,
// name: 'dqwsq'
// },
// {
// index: 12,
// name: 'dqwsq'
// },
// {
// index: 13,
// name: 'dqwsq'
// },
// {
// index: 14,
// name: 'dqwsq'
// },
// {
// index: 15,
// name: 'dqwsq'
// },
// {
// index: 16,
// name: 'dqwsq'
// },
// {
// index: 17,
// name: 'dqwsq'
// },
// {
// index: 18,
// name: 'dqwsq'
// },
// {
// index: 19,
// name: 'dqwsq'
// },
// {
// index: 20,
// name: 'dqwsq'
// },
// {
// index: 21,
// name: 'dqwsq'
// },
// ]
export default function SingleType() {
const [chooseType, setchooseType] = useState(0)
const [choooseTypeType, setchoooseTypeType] = useState(0)
const [typeList, settypeList] = useState<any>([])
const [typeCode, settypeCode] = useState('')
const [typetypeList, settypetypeList] = useState<any>([])
const [pageTitle, setpageTitle] = useState('')
useLoad((query)=>{
console.log('query=>', query.index)
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/category',
data: {
timestamp: Date.now(),
},
success: (res) => {
console.log('熏听区两级分类数据请求成功' ,res.data)
for(let i = 0; i < res.data.data.category.length; i++){
if(res.data.data.category[i].class_code === query.index){
settypeList(res.data.data.category[i].children)
setpageTitle(res.data.data.category[i].class_name)
settypeCode(res.data.data.category[i].children[0].class_code)
}
}
}
})
})
useEffect(()=> {
if(typeCode!== ''){
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/audio/class/product',
data: {
timestamp: Date.now(),
class_code: typeCode
},
success: (res) => {
console.log('获取金刚区内容列表数据请求成功' ,res.data)
settypetypeList(res.data.data.products)
}
})
}
}, [typeCode])
const handleChooseTypeType = (index: number) => {
setchoooseTypeType(index)
settypeCode(typeList[index].class_code)
}
const handleBack = () => {
Taro.navigateBack()
}
const handleDetail = (prdtId: number) => {
Taro.navigateTo({
url: '/pages/ListenDetail/index?prdtId=' + prdtId
})
}
return (
<View className='singleType_bg'>
<View className='header'>
<View
className='back'
onClick={handleBack}
></View>
<View className='title'>{pageTitle}</View>
</View>
<View className='main_context'>
<View className='type_container'>
<ScrollView
className='typelist'
scrollY
scrollWithAnimation
>
{
typeList.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={()=>handleChooseTypeType(index)}
>
{
choooseTypeType === index && <View className='line'></View>
}
<View
className='title'
style={choooseTypeType === index? {color: '#3ba366'} : {}}
>{item.class_name}</View>
</View>
))
}
</ScrollView>
</View>
<View className='product_container'>
<ScrollView
className='product'
scrollY
scrollWithAnimation
>
<View className='container'>
{
typetypeList.map((item: any, index: number) => (
<View
key={index}
className='item'
onClick={()=>handleDetail(item.PrdtId)}
>
<Image
className='icon'
src={item.PrdtCover}
lazyLoad
></Image>
<View className='title'>{item.PrdtTitle}</View>
</View>
))
}
</View>
</ScrollView>
</View>
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '搜索',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,230 @@
.search_bg {
width: calc(100vw - 2rem);
height: calc(100vh - 1rem);
display: flex;
flex-direction: column;
padding: 1rem 1rem 0 1rem;
.subscribe_header {
width: 100%;
height: 2.75rem;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
.subscribe_header_input {
width: calc(100% - 2.5rem - 4rem);
height: 2.5rem;
background: #f8f8f8;
border-radius: 2.25rem;
padding-left: 3rem;
border: .0625rem solid green;
}
.subscribe_header_dressing {
width: 2.5rem;
height: 1.5rem;
font-weight: 600;
font-size: 1rem;
margin: auto 0 auto auto;
}
.subscribe_header_scanCodeBtn {
position: absolute;
top: 1.5625rem;
left: 2rem;
width: 1.5rem;
height: 1.5rem;
}
.subscribe_header_errorIcon {
position: absolute;
top: 1.5625rem;
right: calc(2rem + 3.375rem);
width: 1.5rem;
height: 1.5rem;
z-index: 999;
}
.subscribe_header_searchContainer {
position: relative;
width: 0;
height: 2.5rem;
top: calc(2.5rem + .125rem);
left: 0;
.subscribe_searchContainer {
position: absolute;
left: 1.125rem;
width: calc(100vw - 2rem - 3.375rem - 2.25rem);
height: auto;
background: #fafafa;
display: flex;
flex-direction: column;
z-index: 999;
opacity: .9;
.subscribe_searchItem {
// width: 100%;
width: auto;
height: 2.5rem;
background: #fff;
border: .0625rem solid #f8f8f8;
display: flex;
flex-direction: row;
.subscribe_searchItem_cover {
width: 2.5rem;
height: 2.5rem;
}
.subscribe_searchItem_title {
width: auto;
font-size: 1.125rem;
font-weight: 600;
margin: auto .25rem;
}
}
}
}
}
.subscribe_selection {
width: 100%;
height: 1.5rem;
display: flex;
flex-direction: row;
gap: 1rem;
margin-bottom: 1rem;
.subscribe_selection_item {
width: 2.5rem;
height: 1.5rem;
margin: auto 0;
display: flex;
.subscribe_selection_item_text {
margin: auto;
}
}
}
.subscribe_content {
width: 100%;
height: calc(100% - 3.75rem - 2.5rem);
display: flex;
flex-direction: column;
.subscribe_container {
display: grid;
grid-template-columns: repeat(3, 1fr);
// height: auto;
gap: .625rem;
.subscribe_content_singleItem {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3 + .5rem + 2.5rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc((100vw - 2rem - 1.25rem) / 3 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3);
border-radius: .75rem;
margin-bottom: auto;
}
.subscribe_content_singleItem_title {
width: 100%;
height: 2.5rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
}
}
.subscribe_content_collectionItem {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625 + .5rem + 2rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc(((100vw - 2rem - .625rem) / 2) * .5625 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625);
border-radius: .75rem;
margin-bottom: .625rem;
}
.subscribe_content_singleItem_title {
width: calc(((100vw - 2rem - .625rem) / 2));
height: 1.25rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
white-space: nowrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
margin-bottom: 0;
}
.subscribe_content_collectionItem_count {
height: .625rem;
line-height: .625rem;
font-size: .625rem;
color: rgba(0, 0, 0, .3);
}
}
}
}
}

@ -0,0 +1,301 @@
import { Input, View, Image, Text, ScrollView } from '@tarojs/components'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import React, { useState } from 'react'
import searchIcon from '../../assets/images/searchIcon.png'
import errorIcon from '../../assets/images/error.png'
import './index.less'
// 自定义防抖 Hook
function useDebounce<T>(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void {
let timeoutId: ReturnType<typeof setTimeout> | null = null;
return (...args: any[]): void => {
//@ts-ignore
clearTimeout(timeoutId);
timeoutId = setTimeout(() => callback(...args), delay);
};
}
// 自定义节流 Hook
function useThrottle<T>(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void {
let lastCallTime: number | null = null;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
return (...args: any[]): void => {
const now = Date.now();
if (lastCallTime === null || now - lastCallTime >= delay) {
lastCallTime = now;
callback(...args);
} else if (!timeoutId) {
timeoutId = setTimeout(() => {
lastCallTime = now;
callback(...args);
timeoutId = null;
}, delay - (now - (lastCallTime as number)));
}
};
}
export default function SearchDetail() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
//单本订阅列表
const [userSubscribeSingleList, setuserSubscribeSingleList] = useState([])
//套装订阅列表
const [userSubscribeCollectionList, setuserSubscribeCollectionList] = useState([])
//管理登录弹窗
const [isGetUsePhone, setisGetUsePhone] = useState(false)
const [searchText, setSearchText] = useState<string>('');
const [searchSingleResults, setSearchSingleResults] = useState<any[]>()
const [searchCollectionResults, setsearchCollectionResults] = useState<any[]>()
const [userSelect, setuserSelect] = useState(0)
// 搜索逻辑
const handleSearch = (value: string) => {
//搜索单本结果
const searchSingle = userSubscribeSingleList.filter(( item:any ) => item.PrdtTitle.includes(value))
console.log('searchSingle=>', searchSingle)
setSearchSingleResults(searchSingle)
//搜索套装结果
const searchCollection = userSubscribeCollectionList.filter(( item:any ) => item.PrdtTitle.includes(value))
console.log('searchCollection=>', searchCollection)
setsearchCollectionResults(searchCollection)
};
// 使用防抖和节流 Hooks
const debouncedHandleSearch = useDebounce(handleSearch, 300);
const throttledHandleSearch = useThrottle(handleSearch, 500);
// 监听输入框的变化
const handleInputChange = (event: any) => {
setSearchText(event.detail.value);
debouncedHandleSearch(event.detail.value);
throttledHandleSearch(event.detail.value);
};
//跳转详情页
const handleToCollectionDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + id
})
}
const handleToSingleDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/SingleDetail/index?id=' + id
})
}
//点击取消按钮清楚搜索栏
const handleClearResearch = () => {
console.log('点击取消按钮清楚搜索栏')
setSearchText('')
}
useLoad(() => {
if(!Taro.getStorageSync('UserToken')){
setisGetUsePhone(true)
}else{
//查询用户订阅信息
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/subscribed',
method: 'POST',
header: {
authorization: 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
access_token: Taro.getStorageSync('UserToken'),
timestamp: Date.now(),
},
success: (res: any) => {
console.log('用户订阅信息', res)
//单本订阅列表
let singleArr: any = []
for(let item of res.data.data.FreeProducts){
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item.PrdtId === sec_item.PrdtId)){
sec_item.isFree = 1
singleArr.push(sec_item)
}
}
}
for(let item of res.data.data.SubscribedProducts){
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item.PrdtId === sec_item.PrdtId)){
sec_item.isFree = 0
singleArr.push(sec_item)
}
}
}
console.log('单本订阅列表', singleArr)
setuserSubscribeSingleList(singleArr)
//套装订阅列表
let collectionArr: any = []
for(let item of res.data.data.FreeProducts){
if(!collectionArr.some((arr_item : any) => arr_item.PrdtId === item.PrdtId)){
item.isFree = 1
collectionArr.push(item)
}
}
for(let item of res.data.data.SubscribedProducts){
if(!collectionArr.some((arr_item : any) => arr_item.PrdtId === item.PrdtId)){
item.isFree = 0
collectionArr.push(item)
}
}
console.log('套装订阅列表', collectionArr)
setuserSubscribeCollectionList(collectionArr)
}
})
}
})
return (
<View className='search_bg'>
<View className='subscribe_header'>
<View
className='subscribe_header_searchContainer'
>
</View>
<Input
className='subscribe_header_input'
placeholder='请输入搜索内容'
value={searchText}
onInput={handleInputChange}
></Input>
<View
className='subscribe_header_dressing'
// onClick={() => setisPopupOpen(!isPopupOpen)}
></View>
<Image
className='subscribe_header_scanCodeBtn'
src='https://oss.jm-kid.com/wx_5colorflower/searchIcon.png'
// onClick={handleScanCode}
></Image>
<Image
src='https://oss.jm-kid.com/wx_5colorflower/error.png'
className='subscribe_header_errorIcon'
onClick={()=>handleClearResearch()}
></Image>
</View>
<View className='subscribe_selection'>
<View
className='subscribe_selection_item'
style={userSelect === 0 ? {color: '#3ba366', fontSize: '1rem', height: '1rem', lineHeight: '1rem'} : {color: 'rgba(0, 0, 0, .3)', fontSize: '.875rem', height: '.875rem', lineHeight: '.875rem'}}
onClick={()=>{setuserSelect(0)}}
>
<Text className='subscribe_selection_item_text'></Text>
</View>
<View
className='subscribe_selection_item'
style={userSelect === 1 ? {color: '#3ba366', fontSize: '1rem', height: '1rem', lineHeight: '1rem'} : {color: 'rgba(0, 0, 0, .3)', fontSize: '.875rem', height: '.875rem', lineHeight: '.875rem'}}
onClick={()=>{setuserSelect(1)}}
>
<Text className='subscribe_selection_item_text'></Text>
</View>
</View>
{/* 列表渲染 */}
{
!isGetUsePhone &&
<ScrollView
scrollY
scrollWithAnimation
className='subscribe_content'
enableFlex
>
<View
className='subscribe_container'
style={userSelect === 0 ? {gridTemplateColumns: 'repeat(3, 1fr)'} : {gridTemplateColumns: 'repeat(2, 1fr)'}}
>
{
userSelect === 0 && searchSingleResults && searchSingleResults.length > 0 &&searchSingleResults.map((item: any, index: number) => (
<View
className='subscribe_content_singleItem'
key={index}
onClick={() => handleToSingleDetail(item.PrdtId)}
>
{
item.isFree === 1 && (
<View className='relative_container'>
<View className='subscribe_content_singleItem_label'>
<Text className='subscribe_content_singleItem_label_text'></Text>
</View>
</View>
)
}
<Image
className='subscribe_content_singleItem_cover'
src={item.PrdtCover}
mode='aspectFill'
lazyLoad
></Image>
<View className='subscribe_content_singleItem_title'>{item.PrdtTitle}</View>
</View>
))
}
{
userSelect === 1 && searchCollectionResults && searchCollectionResults.length > 0 && searchCollectionResults.map((item: any, index: number) => (
<View
className='subscribe_content_collectionItem'
key={index}
onClick={() => handleToCollectionDetail(item.PrdtId)}
>
{
item.isFree === 1 && (
<View className='relative_container'>
<View className='subscribe_content_singleItem_label'>
<Text className='subscribe_content_singleItem_label_text'></Text>
</View>
</View>
)
}
<Image
className='subscribe_content_singleItem_cover'
src={item.PrdtCover}
mode='aspectFit'
lazyLoad
></Image>
<View className='subscribe_content_singleItem_title'>{item.PrdtTitle}</View>
<View className='subscribe_content_collectionItem_count'>{`${item.ChildCount}`}</View>
</View>
))
}
</View>
</ScrollView>
}
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationStyle: 'custom',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,195 @@
.single_detail {
width: 100vw;
height: calc(100vh - 7.125rem);
display: flex;
flex-direction: column;
.single_back {
position: fixed;
top: .625rem;
left: .625rem;
width: .7181rem;
height: 1.25rem; //20px
background-image: url(https://oss.jm-kid.com/wx_5colorflower/turnBack.png);
background-repeat: no-repeat;
background-size: cover;
z-index: 1000;
}
.single_bg {
width: 100vw;
height: 9.375rem;
filter: blur(1rem);
}
.single_container {
background-color: #fff;
width: calc(100vw - 2rem);
height: auto;
display: flex;
flex-direction: column;
padding: 0 1rem;
.single_title {
width: auto;
height: 2rem;
font-size: 1.125rem;
font-weight: 600;
margin: 5rem auto .5rem auto;
}
.single_label_container {
width: auto;
height: auto;
display: flex;
flex-direction: row;
margin: 0 auto 1rem auto;
.single_label {
width: auto;
height: 1rem;
background-color: #3ba366;
border-radius: .375rem;
display: flex;
margin: 0 .25rem 1rem 0;
.single_label_item {
font-size: .625rem;
margin: .0625rem .5625rem;
color: #fff;
}
}
}
.single_fixedTitle {
width: 100%;
height: 1.5rem;
font-size: 1rem;
font-weight: 600;
margin: 0 auto 1rem 0;
}
.single_intro {
width: calc(100% - .625rem);
// height: calc(5.625rem - .625rem);
height: auto;
line-height: 1.25rem;
padding: .3125rem;
font-size: .875rem;
font-weight: 600;
color: rgba(0, 0, 0, .4);
letter-spacing: .125rem;
margin-bottom: 1rem;
// white-space: nowrap;//不支持换行
// overflow: hidden;//隐藏多出部分文字
// text-overflow: ellipsis;//用省略号代替多出部分文字
// -webkit-line-clamp: 3; // 限制显示的行数
}
.single_images_container {
width: 100%;
height: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1rem;
.single_images_item {
width: 7.5rem;
height: 7.5rem;
}
}
}
.single_cover_container {
width: 100%;
height: 0;
position: relative;
top: calc(9.375rem - 4.5rem);
left: 0;
.single_cover {
position: absolute;
left: calc((100vw - 9rem) / 2);
width: 9rem;
height: 9rem;
background-image: url('https://oss.jm-kid.com/wx_5colorflower/《屁》.png');
background-repeat: no-repeat;
background-size: cover;
z-index: 1001;
border-radius: .75rem 1.5rem;
box-shadow:
.375rem 0 0 #fff,
0 .25rem .25rem rgba(0, 0, 0, .25)
}
}
.single_tabbar {
position: fixed;
bottom: 0;
width: 100%;
height: 7.125rem;
display: flex;
flex-direction: row;
box-shadow: 0 -0.125rem .5rem rgba(0, 0, 0, .05);
z-index: 999;
.single_tabbar_item {
width: 3.75rem;
height: 5.125rem;
margin: auto;
gap: .125rem;
z-index: 1000;
display: flex;
flex-direction: column;
.single_tabbar_item_cover {
width: 3.75rem;
height: 3.75rem;
border-radius: 1.875rem;
background-repeat: no-repeat;
background-size: cover;
}
.single_tabbar_item_name {
width: 100%;
height: 1.25rem;
font-size: .875rem;
font-weight: 600;
text-align: center;
}
}
}
}
.single_tabbar {
width: 100%;
height: 7.125rem;
display: flex;
flex-direction: row;
box-shadow: 0 -0.125rem .5rem rgba(0, 0, 0, .05);
.single_tabbar_item {
width: 3.75rem;
height: 5.125rem;
margin: auto;
gap: .125rem;
display: flex;
flex-direction: column;
.single_tabbar_item_cover {
width: 3.75rem;
height: 3.75rem;
border-radius: 1.875rem;
background-repeat: no-repeat;
background-size: cover;
}
.single_tabbar_item_name {
width: 100%;
height: 1.25rem;
font-size: .875rem;
font-weight: 600;
text-align: center;
}
}
}

@ -0,0 +1,281 @@
import { ScrollView, View, Image } from '@tarojs/components'
import React, { useEffect, useState } from 'react'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import './index.less'
const tabbarList = [
// {
// tabIndex: 0,
// name: '互动绘本',
// cover: 'https://oss.jm-kid.com/wx_5colorflower/detailsTabbar1.png',
// url: '/pages/DisplayCocos/index',
// },
{
tabIndex: 1,
name: '视频绘本',
cover: 'https://oss.jm-kid.com/wx_5colorflower/detailsTabbar2.png',
url: '/pages/DisplayVideo/index',
},
{
tabIndex: 2,
name: '听绘本',
cover: 'https://oss.jm-kid.com/wx_5colorflower/detailsTabbar3.png',
url: '/pages/ListenBookDisplay/index',
},
// {
// tabIndex: 3,
// name: '录绘本',
// cover: 'https://oss.jm-kid.com/wx_5colorflower/detailsTabbar4.png',
// url: '/pages/DisplayVideo/index',
// },
]
interface SingleDetailProps {
PrdtCover: string,
PrdtDescription: string,
PrdtId: number,
PrdtImages: string[],
PrdtKeys: string[],
PrdtRead: number,
PrdtSubtitle: string,
PrdtTitle: string,
}
export default function SingleDetail() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [navigationBarHeight, setnavigationBarHeight] = useState(0)
const [singleDetail, setsingleDetail] = useState<SingleDetailProps>()
const [isListenBook, setisListenBook] = useState(false)
useLoad((query) => {
console.log('query=>', query.id)
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
prdt_id: query.id
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
setsingleDetail(res.data.data.Product)
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
data: {
timestamp: Date.now(),
prdt_id: query.id
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
setsingleDetail(res.data.data.Product)
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}
//判断是否需要显示伴读图标
if(Taro.getStorageSync('UserToken')){
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
prdt_id: query.id,
res_type: '03',
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
if(res.data.data.StoryResource.length > 0){
setisListenBook(true)
}
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/resource',
method: 'POST',
data: {
timestamp: Date.now(),
prdt_id: query.id,
res_type: '03',
},
success: (res) => {
console.log('产品资源获取成功=>', res.data)
if(res.data.data.StoryResource.length > 0){
setisListenBook(true)
}
},
fail: (err) => {
console.log('产品资源获取失败=>', err)
}
})
}
})
useEffect(() => {
const sysInfo = Taro.getSystemInfoSync()
const statusBarHeight = sysInfo.statusBarHeight
if(statusBarHeight)
setnavigationBarHeight(statusBarHeight + 12)
console.log('navigationBarHeight=>', navigationBarHeight)
}, [])
const handleNavigateTo = (url: string) => {
if(url === '/pages/ListenBookDisplay/index'){
Taro.navigateTo({
url: url + `?prdtId=${singleDetail?.PrdtId}`
})
}else{
Taro.navigateTo({
url: url + `?id=${singleDetail?.PrdtId}`
})
}
}
return (
<>
<ScrollView
className='single_detail'
scrollY
scrollWithAnimation
>
<View
className='single_back'
style={{top: navigationBarHeight}}
onClick={()=>{Taro.navigateBack()}}
></View>
<View className='single_cover_container'>
{
singleDetail && <Image
className='single_cover'
src={singleDetail.PrdtCover}
></Image>
}
</View>
{
singleDetail && <Image
className='single_bg'
src={singleDetail.PrdtCover}
mode='aspectFill'
></Image>
}
<View className='single_container'>
<View className='single_title'>{singleDetail?.PrdtTitle}</View>
<View className='single_label_container'>
{
singleDetail?.PrdtKeys.map((key_item: any, key_index: number) => (
key_index < 4 && <View
className='single_label'
key={key_index}
>
<View className='single_label_item'>{key_item}</View>
</View>
))
}
</View>
<View className='single_fixedTitle'></View>
<View className='single_intro'>{singleDetail?.PrdtDescription}</View>
<View className='single_fixedTitle'></View>
<View className='single_images_container'>
{
singleDetail && singleDetail.PrdtImages.length > 0 && singleDetail.PrdtImages.map((image_item: any, image_index: number) => (
<Image
src={image_item}
key={image_index}
className='single_images_item'
lazyLoad
></Image>
))
}
</View>
</View>
{/* <View className='single_tabbar'>
{
tabbarList.map((item: any, index: number) => (
<View
className='single_tabbar_item'
key={index}
onClick={() => handleNavigateTo(item.url)}
>
<View
style={{backgroundImage: `url(${item.cover})`}}
className='single_tabbar_item_cover'
></View>
<View className='single_tabbar_item_name'>{item.name}</View>
</View>
))
}
</View> */}
</ScrollView>
<View className='single_tabbar'>
{
tabbarList.map((item: any, index: number) => (
<View
className='single_tabbar_item'
key={index}
onClick={() => handleNavigateTo(item.url)}
style={( item.tabIndex === 2 && !isListenBook ) ? {display: 'none'} : {}}
>
<View
style={{backgroundImage: `url(${item.cover})`}}
className='single_tabbar_item_cover'
></View>
<View className='single_tabbar_item_name'>{item.name}</View>
</View>
))
}
</View>
</>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '商城',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,35 @@
.default1_bg {
display: flex;
height: 100vh;
flex-direction: column;
margin: auto;
gap: 1.25rem;
.default1_img {
width: 15.625rem;
height: 15.625rem;
margin: auto auto 1rem auto;
}
.default1_context {
margin: 0 auto;
color: black;
font-size: .875rem;
font-weight: 600;
}
.default1_btn {
margin: 0 auto auto auto;
width: 6.25rem;
height: 1.75rem;
background: linear-gradient(#329C5E, #3BA366);
border-radius: 2.0625rem;
display: flex;
.default1_btn_text {
margin: auto;
color: white;
font-size: .875rem;
}
}
}

@ -0,0 +1,56 @@
import { View, Image, Text} from '@tarojs/components'
import { useState } from 'react';
import Taro, { useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import './index.less'
import GetPhoneNumber from '../../components/getPhoneModal';
export default function Store() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const handleNavigateToMiniProgram = () => {
Taro.navigateToMiniProgram({
appId: 'wxbd3d383851fea776',
path: 'pages/home/dashboard/index',
success: (res) => {
console.log('打开成功=>',res)
},
fail: (res) => {
console.log('打开失败=>',res)
}
})
}
return (
<View className='default1_bg'>
<Image src='https://oss.jm-kid.com/wx_5colorflower/defaultBg1.png' className='default1_img'></Image>
{/* <Text className='default1_context'>当前没有订阅绘本,请前往商城购买哦~</Text> */}
<View
className='default1_btn'
onClick={()=>handleNavigateToMiniProgram()}
>
<Text
className='default1_btn_text'
>
~
</Text>
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '书架',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,273 @@
.subscribe_bg {
width: calc(100vw - 2rem);
height: calc(100vh - 1rem);
display: flex;
flex-direction: column;
padding: 1rem 1rem 0 1rem;
.subscribe_header {
width: 100%;
height: 2.75rem;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
.subscribe_header_input {
width: calc(100% - 2.5rem - 4rem);
height: 2.5rem;
background: #f8f8f8;
border-radius: 2.25rem;
padding-left: 3rem;
border: .0625rem solid green;
}
.subscribe_header_dressing {
width: 2.5rem;
height: 2.5rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/screenIcon.svg);
background-repeat: no-repeat;
background-size: cover;
margin: auto 0 auto auto;
}
.subscribe_header_scanCodeBtn {
position: absolute;
top: 1.5625rem;
left: 2rem;
width: 1.5rem;
height: 1.5rem;
}
.subscribe_header_errorIcon {
position: absolute;
top: 1.5625rem;
right: calc(2rem + 3.375rem);
width: 1.5rem;
height: 1.5rem;
z-index: 999;
}
.subscribe_header_searchContainer {
position: relative;
width: 0;
height: 2.5rem;
top: calc(2.5rem + .125rem);
left: 0;
.subscribe_searchContainer {
position: absolute;
left: 1.125rem;
width: calc(100vw - 2rem - 3.375rem - 2.25rem);
height: auto;
background: #fafafa;
display: flex;
flex-direction: column;
z-index: 999;
opacity: .9;
.subscribe_searchItem {
// width: 100%;
width: auto;
height: 2.5rem;
background: #fff;
border: .0625rem solid #f8f8f8;
display: flex;
flex-direction: row;
.subscribe_searchItem_cover {
width: 2.5rem;
height: 2.5rem;
}
.subscribe_searchItem_title {
width: auto;
font-size: 1.125rem;
font-weight: 600;
margin: auto .25rem;
}
}
}
}
}
.subscribe_selection {
width: 100%;
height: 1.5rem;
display: flex;
flex-direction: row;
gap: 1rem;
margin-bottom: 1rem;
.subscribe_selection_item {
width: 2.5rem;
height: 1.5rem;
margin: auto 0;
display: flex;
.subscribe_selection_item_text {
margin: auto;
}
}
}
.subscribe_content {
width: 100%;
height: calc(100% - 3.75rem - 2.5rem);
display: flex;
flex-direction: column;
.subscribe_container {
display: grid;
grid-template-columns: repeat(3, 1fr);
// height: auto;
gap: .625rem;
.subscribe_content_singleItem {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3 + .5rem + 2.5rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc((100vw - 2rem - 1.25rem) / 3 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc((100vw - 2rem - 1.25rem) / 3);
border-radius: .75rem;
margin-bottom: auto;
}
.subscribe_content_singleItem_title {
width: 100%;
height: 2.5rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
}
}
.subscribe_content_collectionItem {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625 + .5rem + 2rem);
display: flex;
flex-direction: column;
.relative_container {
position: relative;
width: 100%;
height: 0;
top: 0;
left: 0;
.subscribe_content_singleItem_label {
position: absolute;
left: calc(100% - 3rem);
top: calc(((100vw - 2rem - .625rem) / 2) * .5625 - 1rem);
width: 3rem;
height: 1rem;
border-radius: .75rem 0;
background-color: #fcca1e;
display: flex;
.subscribe_content_singleItem_label_text {
font-size: .5rem;
margin: auto;
}
}
}
.subscribe_content_singleItem_cover {
width: 100%;
height: calc(((100vw - 2rem - .625rem) / 2) * .5625);
border-radius: .75rem;
margin-bottom: .625rem;
}
.subscribe_content_singleItem_title {
width: calc(((100vw - 2rem - .625rem) / 2));
height: 1.25rem;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
white-space: nowrap;//不支持换行
overflow: hidden;//隐藏多出部分文字
text-overflow: ellipsis;//用省略号代替多出部分文字
margin-bottom: 0;
}
.subscribe_content_collectionItem_count {
height: .625rem;
line-height: .625rem;
font-size: .625rem;
color: rgba(0, 0, 0, .3);
}
}
.subscribe_content_singleItem_add {
width: calc(100% - .25rem);
height: calc((100vw - 2rem - 1.25rem) / 3 - .25rem);
border: .125rem dashed rgba(0, 0, 0, .6);
border-radius: .75rem;
display: flex;
.subscribe_content_singleItem_addLabel {
background-image: url(https://oss.jm-kid.com/wx_5colorflower/add.png);
background-size: cover;
background-repeat: no-repeat;
width: 2rem;
height: 2rem;
margin: auto;
}
}
}
.subscribe_footer {
width: 100%;
height: 2.5rem;
display: flex;
flex-direction: column;
margin-top: auto;
.subscribe_footer_tips {
// height: 1.25rem;
line-height: 1.125rem;
font-size: .75rem;
color: rgba(0, 0, 0, .3);
text-align: center;
}
.subscribe_footer_add {
// height: 1.25rem;
line-height: 1.125rem;
font-size: .75rem;
font-weight: 600;
color: #3ba366;
text-align: center;
}
}
}
}

@ -0,0 +1,669 @@
import { useEffect, useRef, useState } from 'react'
import Taro, { useDidShow, useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import { Image, Input, ScrollView, View, Text } from '@tarojs/components'
import PopupHalfScreen from '../../components/Popup'
import DefaultPage1 from '../../components/defaultPage1'
import DefaultPage2 from '../../components/defaultPage2'
import GetPhoneNumber from '../../components/getPhoneModal'
import GoToStoreModal from '../../components/goToStoreModal'
import errorIcon from '../../assets/images/error.png'
import './index.less'
import DefaultPage3 from '../../components/defaultPage3'
export default function Subscribe() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
//单本订阅列表
const [userSubscribeSingleList, setuserSubscribeSingleList] = useState([])
//套装订阅列表
const [userSubscribeCollectionList, setuserSubscribeCollectionList] = useState([])
//单本免费订阅统计
const [userSubscribeSingleFreeCount, setuserSubscribeSingleFreeCount] = useState(0)
//单本付费订阅统计
const [userSubscribeSinglePaidCount, setuserSubscribeSinglePaidCount] = useState(0)
//套装免费订阅统计
const [userSubscribeCollectionFreeCount, setuserSubscribeCollectionFreeCount] = useState(0)
//套装付费订阅统计
const [userSubscribeCollectionPaidCount, setuserSubscribeCollectionPaidCount] = useState(0)
//搜索框内容
const [searchValue, setsearchValue] = useState('')
//搜索内容
const [searchResult, setsearchResult] = useState([])
//管理登录弹窗
const [isGetUsePhone, setisGetUsePhone] = useState(false)
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
//记录用户筛选状态
const [isFilter, setisFilter] = useState('')
useEffect(() => {
if(isFilter){
if(isFilter === 'reset'){
console.log('重置筛选状态', isFilter)
//查询用户订阅信息
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/subscribed',
method: 'POST',
header: {
authorization: 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
timestamp: Date.now(),
// filter: ''
},
success: (res: any) => {
console.log('用户订阅信息', res)
//单本订阅列表
let singleArr: any = []
//统计单本免费订阅数量
let a: number = 0
//统计套装免费订阅数量
let b: number = 0
//统计单本付费订阅数量
let c: number = 0
//统计套装付费订阅数量
let d: number = 0
for(let item of res.data.data.FreeProducts){
b++
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item === sec_item)){
sec_item.isFree = 1
singleArr.push(sec_item)
a++
}
}
}
for(let item of res.data.data.SubscribedProducts){
d++
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item === sec_item)){
sec_item.isFree = 0
singleArr.push(sec_item)
c++
}
}
}
console.log('单本订阅列表', singleArr)
setuserSubscribeSingleList(singleArr)
setuserSubscribeSingleFreeCount(a)
setuserSubscribeSinglePaidCount(c)
setuserSubscribeCollectionFreeCount(b)
setuserSubscribeCollectionPaidCount(d)
//套装订阅列表
let collectionArr: any = []
for(let item of res.data.data.FreeProducts){
if(!collectionArr.some((arr_item : any) => arr_item === item)){
item.isFree = 1
collectionArr.push(item)
}
}
for(let item of res.data.data.SubscribedProducts){
if(!collectionArr.some((arr_item : any) => arr_item === item)){
item.isFree = 0
collectionArr.push(item)
}
}
console.log('套装订阅列表', collectionArr)
setuserSubscribeCollectionList(collectionArr)
}
})
}else{
console.log('筛选状态=>', isFilter)
//查询用户订阅信息
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/subscribed',
method: 'POST',
header: {
authorization: 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
timestamp: Date.now(),
filter: isFilter
},
success: (res: any) => {
console.log('用户订阅信息', res)
//单本订阅列表
let singleArr: any = []
for(let item of res.data.data.FreeProducts){
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item === sec_item)){
sec_item.isFree = 1
singleArr.push(sec_item)
}
}
}
for(let item of res.data.data.SubscribedProducts){
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item === sec_item)){
sec_item.isFree = 0
singleArr.push(sec_item)
}
}
}
console.log('单本订阅列表', singleArr)
setuserSubscribeSingleList(singleArr)
//套装订阅列表
let collectionArr: any = []
for(let item of res.data.data.FreeProducts){
if(!collectionArr.some((arr_item : any) => arr_item === item)){
item.isFree = 1
collectionArr.push(item)
}
}
for(let item of res.data.data.SubscribedProducts){
if(!collectionArr.some((arr_item : any) => arr_item === item)){
item.isFree = 0
collectionArr.push(item)
}
}
console.log('套装订阅列表', collectionArr)
setuserSubscribeCollectionList(collectionArr)
}
})
}
}
}, [isFilter])
const requestUserSubscribe = () => {
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
}else{
//查询用户订阅信息
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/subscribed',
method: 'POST',
header: {
authorization: 'bearer ' + Taro.getStorageSync('UserToken')
},
data: {
timestamp: Date.now(),
// filter: ''
},
success: (res: any) => {
console.log('用户订阅信息', res)
//单本订阅列表
let singleArr: any = []
//统计单本免费订阅数量
let a: number = 0
//统计套装免费订阅数量
let b: number = 0
//统计单本付费订阅数量
let c: number = 0
//统计套装付费订阅数量
let d: number = 0
for(let item of res.data.data.FreeProducts){
b++
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item.PrdtId === sec_item.PrdtId)){
sec_item.isFree = 1
singleArr.push(sec_item)
a++
}
}
}
for(let item of res.data.data.SubscribedProducts){
d++
for(let sec_item of item.Child){
if(!singleArr.some((arr_item : any) => arr_item.PrdtId === sec_item.PrdtId)){
sec_item.isFree = 0
singleArr.push(sec_item)
c++
}
}
}
console.log('单本订阅列表', singleArr)
setuserSubscribeSingleList(singleArr)
setuserSubscribeSingleFreeCount(a)
setuserSubscribeSinglePaidCount(c)
setuserSubscribeCollectionFreeCount(b)
setuserSubscribeCollectionPaidCount(d)
//套装订阅列表
let collectionArr: any = []
for(let item of res.data.data.FreeProducts){
if(!collectionArr.some((arr_item : any) => arr_item.PrdtId === item.PrdtId)){
item.isFree = 1
collectionArr.push(item)
}
}
for(let item of res.data.data.SubscribedProducts){
if(!collectionArr.some((arr_item : any) => arr_item.PrdtId === item.PrdtId)){
item.isFree = 0
collectionArr.push(item)
}
}
console.log('套装订阅列表', collectionArr)
setuserSubscribeCollectionList(collectionArr)
}
})
}
}
useDidShow(() => {
console.log('componentDidShow')
if(Taro.getStorageSync('UserToken')){
setisGetUsePhone(true)
}
requestUserSubscribe()
})
useEffect(() => {
if(isGetUsePhone){
requestUserSubscribe()
}
}, [isGetUsePhone])
const [userSelect, setuserSelect] = useState(0)
// 生成关键字(id)二维码
// useEffect(() => {
// Taro.request({
// url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential',
// data: {
// appid: 'wxc5c21dae2f45470e',
// secret: '599f2cf20740d630f06f447719653660',
// },
// success: function (res) {
// const access_token = res.data.access_token
// Taro.request({
// method: 'POST',
// url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token,
// data: {
// // check_path: 'false',
// // env_version: 'develop',
// scene: 'id=5390', //兑换码
// page: 'pages/UserHome/index' //需要跳转到的页面
// },
// responseType: 'arraybuffer',
// success: function (coderes) {
// //arraybuffer转base64
// console.log('64', Taro.arrayBufferToBase64(coderes.data))
// }
// })
// }
// })
// }, [])
const [isPopupOpen, setisPopupOpen] = useState(false)
const [isToStoreOpen, setisToStoreOpen] = useState(false)
const [userScene, setuserScene] = useState<any>(null)
//唤起扫码
const handleScanCode = () => {
console.log('唤起扫码')
Taro.scanCode({
success: (res: any) => {
console.log(res.path.slice(-8))
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
setuserScene(res.path.slice(-8))
}else{
Taro.request({
url: 'https://interapi.jm-kid.com/api/product/exchange',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
change_code: res.path.slice(-8)
},
success: (s_res: any) => {
console.log('兑换成功=>', s_res.data)
if(s_res.data.state === '200'){
let modalContent = ''
s_res.data.data.Subscribed.forEach(element => {
modalContent += `兑换成功: ${element.PrdtTitle}\n`
})
Taro.showModal({
title: '兑换成功',
content: modalContent,
showCancel: true,
success: (modal_res) => {
if (modal_res.confirm) {
console.log('用户点击确定')
requestUserSubscribe()
} else if (modal_res.cancel) {
console.log('用户点击取消')
}
}
})
}else if(s_res.data.state === '207'){
Taro.showToast({
title: '兑换码已使用',
icon: 'error'
})
}
},
fail: (err: any) => {
console.log('兑换失败=>', err)
}
})
}
}
})
}
//跳转详情页
const handleToCollectionDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + id
})
}
const handleToSingleDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/SingleDetail/index?id=' + id
})
}
const handleNavigateToMiniProgram = () => {
Taro.navigateToMiniProgram({
appId: 'wxbd3d383851fea776',
path: 'pages/home/dashboard/index',
success: (res) => {
console.log('打开成功=>',res)
},
fail: (res) => {
console.log('打开失败=>',res)
}
})
}
//键盘点击search开始检索
const handleSearch = () => {
const arr: any = []
if(userSelect === 0){
userSubscribeSingleList.forEach((item: any) => {
if(item.PrdtTitle.includes(searchValue)){
arr.push(item)
}
})
}else if(userSelect === 1){
userSubscribeCollectionList.forEach((item: any) => {
if(item.PrdtTitle.includes(searchValue)){
arr.push(item)
}
})
}
setsearchResult(arr)
console.log('搜索结果=>', arr)
}
//搜索栏点击跳转搜索页
const handleSearchToDetail = () => {
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
}else{
Taro.navigateTo({
url: '/pages/SearchDetail/index'
})
}
}
return (
<View className='subscribe_bg'>
<View className='subscribe_header'>
<View
className='subscribe_header_searchContainer'
>
</View>
<Input
className='subscribe_header_input'
placeholder='请输入绘本名称'
value={searchValue}
confirmType='search'
onConfirm={() => handleSearch()}
onInput={(e) => {
setsearchValue(e.detail.value)
}}
onClick={() => handleSearchToDetail()}
></Input>
<View
className='subscribe_header_dressing'
onClick={() => setisPopupOpen(!isPopupOpen)}
></View>
<Image
className='subscribe_header_scanCodeBtn'
src='https://oss.jm-kid.com/wx_5colorflower/scanCodeIcon.svg'
onClick={handleScanCode}
></Image>
</View>
<PopupHalfScreen
visible={isPopupOpen}
onClose={() => setisPopupOpen(!isPopupOpen)}
isfilter={isFilter}
onFilter={setisFilter}
></PopupHalfScreen>
<View className='subscribe_selection'>
<View
className='subscribe_selection_item'
style={userSelect === 0 ? {color: '#3ba366', fontSize: '1rem', height: '1rem', lineHeight: '1rem'} : {color: 'rgba(0, 0, 0, .3)', fontSize: '.875rem', height: '.875rem', lineHeight: '.875rem'}}
onClick={()=>{setuserSelect(0)}}
>
<Text className='subscribe_selection_item_text'></Text>
</View>
<View
className='subscribe_selection_item'
style={userSelect === 1 ? {color: '#3ba366', fontSize: '1rem', height: '1rem', lineHeight: '1rem'} : {color: 'rgba(0, 0, 0, .3)', fontSize: '.875rem', height: '.875rem', lineHeight: '.875rem'}}
onClick={()=>{setuserSelect(1)}}
>
<Text className='subscribe_selection_item_text'></Text>
</View>
</View>
{/* 列表渲染 */}
{
isGetUsePhone &&
<ScrollView
scrollY
scrollWithAnimation
className='subscribe_content'
enableFlex
>
<View
className='subscribe_container'
style={userSelect === 0 ? {gridTemplateColumns: 'repeat(3, 1fr)'} : {gridTemplateColumns: 'repeat(2, 1fr)'}}
>
{
userSelect === 0 && userSubscribeSingleList.length > 0 && userSubscribeSingleList.map((item: any, index: number) => (
<View
className='subscribe_content_singleItem'
key={index}
onClick={() => handleToSingleDetail(item.PrdtId)}
>
{
item.isFree === 1 && (
<View className='relative_container'>
<View className='subscribe_content_singleItem_label'>
<Text className='subscribe_content_singleItem_label_text'></Text>
</View>
</View>
)
}
<Image
className='subscribe_content_singleItem_cover'
src={item.PrdtCover}
mode='aspectFill'
lazyLoad
></Image>
<View className='subscribe_content_singleItem_title'>{item.PrdtTitle}</View>
</View>
))
}
{
userSelect === 1 && userSubscribeCollectionList.length > 0 && userSubscribeCollectionList.map((item: any, index: number) => (
<View
className='subscribe_content_collectionItem'
key={index}
onClick={() => handleToCollectionDetail(item.PrdtId)}
>
{
item.isFree === 1 && (
<View className='relative_container'>
<View className='subscribe_content_singleItem_label'>
<Text className='subscribe_content_singleItem_label_text'></Text>
</View>
</View>
)
}
<Image
className='subscribe_content_singleItem_cover'
src={item.PrdtCover}
mode='aspectFit'
lazyLoad
></Image>
<View className='subscribe_content_singleItem_title'>{item.PrdtTitle}</View>
<View className='subscribe_content_collectionItem_count'>{`${item.ChildCount}`}</View>
</View>
))
}
{
isGetUsePhone && (isFilter === '' || isFilter === 'reset') && <View
className='subscribe_content_singleItem_add'
onClick={()=>{setisToStoreOpen(true)}}
>
<View className='subscribe_content_singleItem_addLabel'></View>
</View>
}
</View>
{
isGetUsePhone && (isFilter === '' || isFilter === 'reset') &&
<View className='subscribe_footer'>
<Text className='subscribe_footer_tips'>
{
userSelect === 0 ? `${userSubscribeSingleFreeCount}本免费绘本,${userSubscribeSinglePaidCount}本订阅绘本 ` : `${userSubscribeCollectionFreeCount}套免费绘本,${userSubscribeCollectionPaidCount}套订阅绘本 `
}
</Text>
<Text
className='subscribe_footer_add'
onClick={handleNavigateToMiniProgram}
>
</Text>
</View>
}
{
isGetUsePhone && userSelect === 0 && userSubscribeSingleList.length === 0 &&
<DefaultPage3></DefaultPage3>
}
{
isGetUsePhone && userSelect === 1 && userSubscribeCollectionList.length === 0 &&
<DefaultPage3></DefaultPage3>
}
</ScrollView>
}
{/* 用户未登录 */}
{
!isGetUsePhone &&
<DefaultPage1
setisGetUsePhone={setisGetUsePhone}
></DefaultPage1>
}
<GetPhoneNumber
onClose={setisGetUsePhone}
scene={userScene}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
{/* 跳转商城 */}
<GoToStoreModal
visible={isToStoreOpen}
onClose={() => setisToStoreOpen(false)}
type={1}
setmallLink={(link: string) => {}}
></GoToStoreModal>
</View>
)
}

@ -0,0 +1,7 @@
export default {
navigationBarTitleText: '修改个人资料',
// navigationStyle: 'custom',
// navigationBarBackgroundColor: '#000'
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,75 @@
.info_bg {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
gap: 1rem;
background: #fafafa;
.info_header {
width: 100%;
height: auto;
display: flex;
background: #fff;
.info_avatar {
width: 6.25rem;
height: 6.25rem;
border-radius: 3.125rem;
padding: 0;
margin: 2rem auto;
.info_avatar_img {
width: 6.25rem;
height: 6.25rem;
}
}
}
.info_content {
width: 100%;
height: auto;
display: flex;
flex-direction: column;
background: #fff;
padding: .5rem 0;
.info_content_item {
width: 100%;
height: 3.125rem;
display: flex;
padding: .8438rem 1rem;
.info_content_item_title {
width: 6.25rem;
height: 1.4375rem;
font-size: 1rem;
font-weight: 600;
text-align: center;
}
.info_content_item_input {
width: auto;
height: 1.4375rem;
padding-left: 1.875rem;
}
}
}
.info_content_btn {
width: 10rem;
height: 2rem;
border-radius: 1rem;
background: #3BA366;
margin: 0 auto;
display: flex;
.info_content_btn_text {
text-align: center;
color: #ffffff;
font-size: 1rem;
font-weight: 600;
margin: auto;
}
}
}

@ -0,0 +1,157 @@
import { useEffect, useState } from 'react'
import { Button, Image, Input, View, Text } from '@tarojs/components'
import Taro, { useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import './index.less'
export default function UserPersonalInfo() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [userAvatar, setuserAvatar] = useState(
Taro.getStorageSync('UserAvatar') ? Taro.getStorageSync('UserAvatar') : ''
)
const [userNickname, setuserNickname] = useState(
Taro.getStorageSync('UserNickName') ? Taro.getStorageSync('UserNickName') : ''
)
const [userPhoneNumber, setuserPhoneNumber] = useState(
Taro.getStorageSync('UserPhoneNumber') ? Taro.getStorageSync('UserPhoneNumber') : ''
)
const [isChangeAvatar, setisChangeAvatar] = useState(false)
useEffect(()=> {
console.log('用户昵称=>', userNickname)
console.log('用户头像=>', userAvatar)
// setuserNickname('123123123312')
//将用户手机号第四位到第八位隐藏
setuserPhoneNumber(userPhoneNumber.slice(0,3) + '****' + userPhoneNumber.slice(7))
}, [userPhoneNumber])
const handleChooseAvatar = (e: any) => {
//回调用户头像地址
console.log(e.detail.avatarUrl)
setisChangeAvatar(true)
setuserAvatar(e.detail.avatarUrl)
}
const handleSave = () => {
console.log('userAvatar=>', userAvatar)
if(isChangeAvatar){
Taro.uploadFile({
url: 'https://interapi.jm-kid.com/api/user/edit',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
filePath: userAvatar,
name: 'avatar',
formData: {
timestamp: Date.now(),
nick_name: userNickname,
access_token: Taro.getStorageSync('UserToken'),
avatar: userAvatar,
},
success: (res: any) => {
console.log('保存成功=>', JSON.parse(res.data))
Taro.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
Taro.setStorageSync('UserAvatar', JSON.parse(res.data).data.user.Avatar)
Taro.setStorageSync('UserNickName', JSON.parse(res.data).data.user.NickName)
setisChangeAvatar(false)
// Taro.navigateBack()
}
})
}else{
Taro.request({
method: 'POST',
url: 'https://interapi.jm-kid.com/api/user/edit',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`
},
data: {
timestamp: Date.now(),
nick_name: userNickname,
},
success: (res: any) => {
console.log('保存成功=>', res.data)
Taro.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
Taro.setStorageSync('UserNickName', res.data.data.user.NickName)
setisChangeAvatar(false)
// Taro.navigateBack()0000
}
})
}
}
return (
<View className='info_bg'>
<View className='info_header'>
<Button
openType='chooseAvatar'
className='info_avatar'
onChooseAvatar={handleChooseAvatar}
>
<Image
src={userAvatar}
mode='aspectFill'
className='info_avatar_img'
></Image>
</Button>
</View>
<View className='info_content'>
<View className='info_content_item'>
<Text className='info_content_item_title'></Text>
<Input
className='info_content_item_input'
value={userNickname}
onInput={(e)=>{setuserNickname(e.detail.value)}}
placeholder='name'
></Input>
</View>
<View className='info_content_item'>
<Text className='info_content_item_title'></Text>
<Input
className='info_content_item_input'
value={userPhoneNumber}
disabled
></Input>
</View>
</View>
<View
className='info_content_btn'
onClick={handleSave}
>
<Text
className='info_content_btn_text'
></Text>
</View>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '我的订阅',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,180 @@
.subscribe_bg {
width: 100vw;
height: 100vh;
background: #fafafa;
padding: 0 1rem;
.subscribe_scrollview {
width: calc(100% - 2rem);
height: 100vh;
background: #fafafa;
display: flex;
flex-direction: column;
.subscribe_item {
width: calc(100% - 2rem);
height: auto;
display: flex;
padding: 1rem;
flex-direction: column;
background: #ffffff;
border-radius: 1rem;
gap: 1rem;
margin-bottom: 1rem;
.item_header {
width: 100%;
height: 1.5rem;
display: flex;
flex-direction: row;
margin: auto;
.item_header_addtime_icon {
width: 1.5rem;
height: 1.5rem;
margin: auto 0 auto 0;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/subscribeListHeaderIcon.png);
background-repeat: no-repeat;
background-size: cover;
}
.item_header_addtime_text {
width: auto;
font-size: .875rem;
color: rgba(0, 0, 0, .6);
margin: auto auto auto .25rem;
}
.item_header_icon {
width: 3rem;
height: 1.5rem;
border-radius: 1.5rem;
display: flex;
.item_header_icon_text {
font-size: .875rem;
font-weight: 600;
margin: auto;
text-align: center;
}
}
}
.item_content {
width: 100%;
height: auto;
background: #ffffff;
display: flex;
flex-direction: row;
.content_container0 {
width: 7rem;
height: auto;
.aspect_ratio_flex_container0 {
position: relative;
width: 100%; /* 或者任意宽度 */
padding-top: calc((1 / 1) * 100%); /* 计算高度以保持16:9比例 */
.item_content_image0 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0; /* 使内容填充整个容器 */
width: 100%;
height: 100%;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/subscribeListHeaderIcon.png);
background-repeat: no-repeat;
background-size: cover;
}
}
}
.content_container1 {
width: 10.75rem;
height: auto;
.aspect_ratio_flex_container1 {
position: relative;
width: 100%; /* 或者任意宽度 */
padding-top: calc((9 / 16) * 100%); /* 计算高度以保持16:9比例 */
.shade {
position: absolute;
top: 0;
left: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .4);
z-index: 10;
display: flex;
border-radius: .75rem;
.shade_context {
color: #ffffff;
font-size: 1.125rem;
margin: auto;
}
}
.item_content_image1 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0; /* 使内容填充整个容器 */
width: 100%;
height: 100%;
border-radius: .75rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/《屁》.png);
background-repeat: no-repeat;
background-size: cover;
z-index: 9;
}
}
}
.item_content_container {
display: flex;
flex-direction: column;
margin-left: auto;
.item_content_title {
width: auto;
font-size: 1rem;
font-weight: 600;
margin: auto auto .25rem 0;
}
.item_content_endtime {
width: auto;
font-size: .875rem;
color: rgba(0, 0, 0, .4);
margin: 0 auto auto 0;
}
.item_content_btn {
width: 6.25rem;
height: 1.75rem;
border-radius: 2.0625rem;
background: linear-gradient(to right, #fcb11e, #fcca1e);
margin: auto auto .25rem 0;
display: flex;
.item_content_btn_context {
width: auto;
line-height: 1.25rem;
font-size: .875rem;
font-weight: 600;
color: #000000;
margin: auto;
}
}
}
}
}
}
}

@ -0,0 +1,139 @@
import { ScrollView, View, Text } from '@tarojs/components'
import React, { useState } from 'react'
import Taro, { useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import DefaultPage2 from '../../../components/defaultPage2'
import './index.less'
interface subscribeProps {
OrdDate: string,
OrdRefer: number,
PrdtCover: string,
PrdtDeadline: string,
PrdtId: number,
PrdtSubtitle: string,
PrdtTitle: string,
}
export default function UserSubscribe() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [userSubuscribed, setuserSubuscribed] = useState<subscribeProps[]>()
useLoad(() => {
Taro.request({
url: 'https://interapi.jm-kid.com/api/user/subscribed',
method: 'POST',
header: {
authorization: `bearer ${Taro.getStorageSync('UserToken')}`,
},
success: (res: any) => {
console.log('用户订阅查询成功=>', res.data)
setuserSubuscribed(res.data.data)
}
})
})
//跳转详情页
const handleToCollectionDetail = (id: string) => {
Taro.navigateTo({
url: '/pages/CollectionDetail/index?id=' + id
})
}
return (
<View className='subscribe_bg'>
<ScrollView
scrollY
scrollWithAnimation
className='subscribe_scrollview'
>
{
userSubuscribed && userSubuscribed.length > 0 && userSubuscribed.map((item: any, index: number) => (
<View
className='subscribe_item'
key={index}
onClick={()=>handleToCollectionDetail(item.PrdtId)}
>
<View className='item_header'>
<View className='item_header_addtime_icon'></View>
<Text className='item_header_addtime_text'>{item.OrdDate}</Text>
<View
className='item_header_icon'
style={
item.OrdRefer === 2 ? { backgroundColor: '#3BA366' } : { backgroundColor: '#FCCA1E' }
}
>
<View
className='item_header_icon_text'
style={
item.OrdRefer === 2 ? { color: '#fff' } : { color: '#000' }
}
>
{
item.OrdRefer === 2 ? '兑换' : '购买'
}
</View>
</View>
</View>
<View className='item_content'>
<View className={'content_container' + 1}>
<View className={'aspect_ratio_flex_container' + 1}>
{
Date.parse(item.PrdtDeadline.split(' ')[0] + 'T' + item.PrdtDeadline.split(' ')[1] + 'Z') < Date.now() &&
<View className='shade'>
<View className='shade_context'></View>
</View>
}
<View
className={'item_content_image' + 1}
style={{backgroundImage: `url(${item.PrdtCover})`}}
></View>
</View>
</View>
<View
className='item_content_container'
style={
item.OrdRefer === 0 ? { width: 'calc(100% - 1rem - 7rem)', height: '7rem' } : { width: 'calc(100% - 1rem - 10.75rem)', height: '6.0469rem' }
}
>
<View className='item_content_title'>{item.PrdtTitle}</View>
<View className='item_content_endtime'>{item.PrdtDeadline.slice(0,10)}</View>
{
Date.parse(item.PrdtDeadline.split(' ')[0] + 'T' + item.PrdtDeadline.split(' ')[1] + 'Z') < Date.now() &&
<View className='item_content_btn'>
<View className='item_content_btn_context'>~</View>
</View>
}
</View>
<View></View>
</View>
</View>
))
}
{
userSubuscribed && userSubuscribed.length === 0 &&
<DefaultPage2></DefaultPage2>
}
</ScrollView>
</View>
)
}

@ -0,0 +1,5 @@
export default {
navigationBarTitleText: '我的',
enableShareAppMessage: true,
enableShareTimeline: true,
}

@ -0,0 +1,99 @@
.user_home_bg {
width: calc(100vw - 2rem);
height: calc(100vh - 2rem);
display: flex;
flex-direction: column;
padding: 1rem;
.aspect_ratio_flex_container {
position: relative;
width: 100%; /* 或者任意宽度 */
padding-top: calc((160 / 358) * 100%); /* 计算高度以保持16:9比例 */
.aspect_ratio_inner {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0; /* 使内容填充整个容器 */
.user_home_header_bg {
width: 100%;
height: 100%;
border-radius: 1rem;
background-image: url(https://oss.jm-kid.com/wx_5colorflower/userCard.png);
background-repeat: no-repeat;
background-size: cover;
}
.use_home_header_info {
position: absolute;
top: 1rem;
left: 1rem;
width: 100%;
height: 3.75rem;
display: flex;
flex-direction: row;
.user_home_header_info_icon {
width: 3.75rem;
height: 3.75rem;
border: .0625rem solid #ccc;
border-radius: 50%;
}
.user_home_header_info_name {
width: auto;
font-size: 1.125rem;
font-weight: 600;
color: #fff;
margin: .2813rem auto auto .5rem;
}
}
}
}
.user_home_content {
width: calc(100% - 2rem);
height: auto;
min-height: calc(100% - 6.25rem - 3rem - 2rem);
display: flex;
flex-direction: column;
margin-top: 1rem;
gap: 1rem;
.user_home_content_item {
width: 100%;
height: 3.125rem;
display: flex;
flex-direction: row;
padding: 0;
background-color: #fff;
.user_home_content_item_icon {
width: 2.5rem;
height: 2.5rem;
margin: auto .5rem auto 1rem;
}
.user_home_content_item_name {
width: auto;
height: 1rem;
line-height: 1rem;
font-size: 1rem;
text-align: center;
margin: auto auto auto .5rem;
}
.user_home_content_item_btn {
width: 1.5rem;
height: 1.5rem;
margin: auto 1rem auto auto;
}
}
.user_home_content_item::after {
border: 0;
}
}
}

@ -0,0 +1,210 @@
import React, { useEffect, useState } from 'react'
import Taro, { useDidHide, useDidShow, useLoad, useShareAppMessage, useShareTimeline } from '@tarojs/taro'
import { Button, Image, View, Text } from '@tarojs/components'
import UserExchangeModal from '../../components/UserExchangeModal'
import serviceIcon from '../../assets/images/service.svg'
import storeIcon from '../../assets/images/store.png'
import './index.less'
import GetPhoneNumber from '../../components/getPhoneModal'
const userOperateList = [
{
index: 0,
name: '兑换码',
icon: 'https://oss.jm-kid.com/wx_5colorflower/operate1.svg',
pushUrl: '',
},
{
index: 1,
name: '我的订阅',
icon: 'https://oss.jm-kid.com/wx_5colorflower/operate2.svg',
pushUrl: '/pages/UserHome/UserSubscribe/index',
},
{
index: 2,
name: '联系客服',
icon: serviceIcon,
pushUrl: '',
},
{
index: 3,
name: '商城',
icon: storeIcon,
pushUrl: '',
},
]
export default function UserHome() {
useShareAppMessage((res) => {
if (res.from === 'button') {
console.log(res.target);
}
return {
title: '五色花',
path: '/pages/Home/index'
}
})
useShareTimeline(() => {
return {
title: '五色花',
path: '/pages/Home/index'
}
})
const [userAvator, setuserAvator] = useState('')
const [userNickName, setuserNickName] = useState('')
const [userName, setuserName] = useState('')
const [isUserExchangeModalOpen, setisUserExchangeModalOpen] = useState(false)
//管理登录弹窗
const [isGetUsePhone, setisGetUsePhone] = useState(false)
//管理登录弹窗
const [isLoginOpen, setisLoginOpen] = useState(false)
const handleGetUserProfile = () => {
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
}else{
Taro.navigateTo({
url: '/pages/UserHome/UserPersonalInfo/index'
})
}
// Taro.getUserProfile({
// desc: '用于完善用户资料',
// success: (res: any) => {
// console.log(res.userInfo)
// setuserAvator(res.userInfo.avatarUrl)
// setuserName(res.userInfo.nickName)
// }
// })
}
//更新用户信息
useDidShow(() => {
console.log('更新用户信息', Taro.getStorageSync('UserNickName'))
if(Taro.getStorageSync('UserToken')){
setuserAvator(Taro.getStorageSync('UserAvatar'))
setuserNickName(Taro.getStorageSync('UserNickName'))
}
})
useDidHide(() => {
if(Taro.getStorageSync('UserToken')){
setuserAvator(Taro.getStorageSync('UserAvatar'))
setuserNickName(Taro.getStorageSync('UserNickName'))
}
})
// useLoad((query) => {
// if (decodeURIComponent(query.scene)) {
// let resid_reg = /id=(\d*)/;
// let bookid = resid_reg.exec(decodeURIComponent(query.scene))?.[1].trim()
// console.log('2useload', bookid)
// }
// })
const handlePush = (index: number,url: string) => {
if(!Taro.getStorageSync('UserToken')){
setisLoginOpen(true)
}else{
if(index === 1){
Taro.navigateTo({
url: url,
})
}else if(index === 0){
setisUserExchangeModalOpen(true)
}
}
}
const handleNavigateToMiniProgram = () => {
Taro.navigateToMiniProgram({
appId: 'wxbd3d383851fea776',
path: 'pages/home/dashboard/index',
success: (res) => {
console.log('打开成功=>',res)
},
fail: (res) => {
console.log('打开失败=>',res)
}
})
}
return (
<View className='user_home_bg'>
<View className='aspect_ratio_flex_container'>
<View className='aspect_ratio_inner'>
{/* 内容可以放在这里 */}
<View className='user_home_header_bg'></View>
<View className='use_home_header_info'>
<Image className='user_home_header_info_icon'
src={userAvator === '' ? 'https://oss.jm-kid.com/wx_5colorflower/header.svg' : userAvator}
onClick={handleGetUserProfile}
></Image>
<Text className='user_home_header_info_name'>{userNickName ? userNickName : '未登录'}</Text>
</View>
</View>
</View>
<View className='user_home_content'>
{
userOperateList.map((item: any, index: number) => (
index < 2 && <View
key={index}
className='user_home_content_item'
onClick={()=>handlePush(item.index ,item.pushUrl)}
>
<Image className='user_home_content_item_icon' src={item.icon}></Image>
<Text className='user_home_content_item_name'>{item.name}</Text>
<Image
className='user_home_content_item_btn'
src='https://oss.jm-kid.com/wx_5colorflower/next.svg'
></Image>
</View>
))
}
<Button
className='user_home_content_item'
openType='contact'
>
<Image className='user_home_content_item_icon' src={userOperateList[2].icon}></Image>
<Text className='user_home_content_item_name'>{userOperateList[2].name}</Text>
<Image
className='user_home_content_item_btn'
src='https://oss.jm-kid.com/wx_5colorflower/next.svg'
></Image>
</Button>
<View
className='user_home_content_item'
onClick={()=>handleNavigateToMiniProgram()}
>
<Image className='user_home_content_item_icon' src={userOperateList[3].icon}></Image>
<Text className='user_home_content_item_name'>{userOperateList[3].name}</Text>
<Image
className='user_home_content_item_btn'
src='https://oss.jm-kid.com/wx_5colorflower/next.svg'
></Image>
</View>
</View>
<UserExchangeModal isOpen={isUserExchangeModalOpen} setIsOpen={setisUserExchangeModalOpen}></UserExchangeModal>
<GetPhoneNumber
onClose={setisGetUsePhone}
modalVisible={isLoginOpen}
onModalClose={() => setisLoginOpen(false)}
></GetPhoneNumber>
</View>
)
}

@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"removeComments": false,
"preserveConstEnums": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"sourceMap": true,
"baseUrl": ".",
"rootDir": ".",
"jsx": "react-jsx",
"allowJs": true,
"resolveJsonModule": true,
"typeRoots": [
"node_modules/@types"
]
},
"include": ["./src", "./types"],
"compileOnSave": false
}

20
types/global.d.ts vendored

@ -0,0 +1,20 @@
/// <reference types="@tarojs/taro" />
declare module '*.png';
declare module '*.gif';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.svg';
declare module '*.css';
declare module '*.less';
declare module '*.scss';
declare module '*.sass';
declare module '*.styl';
declare namespace NodeJS {
interface ProcessEnv {
TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd'
}
}
Loading…
Cancel
Save