chore: scaffold linhelp applications

This commit is contained in:
王鹏
2026-07-07 15:06:33 +08:00
parent 95685efa82
commit edffda2a84
70 changed files with 537 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
.worktrees/
target/
*.class
*.log
node_modules/
dist/
.vite/
coverage/
.idea/
.vscode/
*.iml
.env
.env.*
backend/logs/
deploy/.data/
miniapp/miniprogram_npm/
miniapp/private.*

23
README.md Normal file
View File

@@ -0,0 +1,23 @@
# LinHelp
LinHelp is the phase-one implementation workspace for "Lin Xiao Bang", a community life service MVP.
## Stack
- Backend: Java 8, Spring Boot 2.7.18, MyBatis Plus, Sa-Token, MySQL, Redis, Flyway, Knife4j, MinIO
- Admin web: Vue 3, TypeScript, Vite, Element Plus
- Resident miniapp: WeChat native mini program, WXML, WXSS, JavaScript
- Rider H5: Vue 3, TypeScript, Vite
## Local Runtime
```powershell
docker compose -f deploy/docker-compose.dev.yml up -d
cd backend
mvn test
```
Project docs:
- `docs/superpowers/specs/2026-07-07-linxiaobang-prd-design.md`
- `docs/superpowers/plans/2026-07-07-linxiaobang-phase-one-implementation.md`

27
admin-web/package.json Normal file
View File

@@ -0,0 +1,27 @@
{
"name": "linhelp-admin-web",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0 --port 5173",
"build": "vue-tsc -b && vite build",
"test": "vitest run",
"lint": "eslint ."
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.2",
"element-plus": "^2.7.6",
"pinia": "^2.1.7",
"vue": "^3.4.31",
"vue-router": "^4.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.5",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vitest": "^2.0.2",
"vue-tsc": "^2.0.26"
}
}

9
admin-web/vite.config.ts Normal file
View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5173
}
})

112
backend/pom.xml Normal file
View File

@@ -0,0 +1,112 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.linhelp</groupId>
<artifactId>linhelp-backend</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>linhelp-backend</name>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.7.18</spring-boot.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<sa-token.version>1.38.0</sa-token.version>
<knife4j.version>4.4.0</knife4j.version>
<minio.version>8.5.11</minio.version>
<mysql.version>8.0.33</mysql.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,12 @@
package com.linhelp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LinHelpApplication {
public static void main(String[] args) {
SpringApplication.run(LinHelpApplication.class, args);
}
}

View File

@@ -0,0 +1,26 @@
spring:
datasource:
url: jdbc:mysql://localhost:3306/linhelp?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: linhelp
password: linhelp
redis:
host: localhost
port: 6379
flyway:
enabled: true
locations: classpath:db/migration
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
sa-token:
token-name: Authorization
timeout: 2592000
linhelp:
storage:
endpoint: http://localhost:9000
access-key: linhelp
secret-key: linhelp123
bucket: linhelp

View File

@@ -0,0 +1,11 @@
spring:
profiles:
active: dev
application:
name: linhelp-backend
server:
port: 8080
knife4j:
enable: true

View File

@@ -0,0 +1,15 @@
package com.linhelp;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = {
"spring.flyway.enabled=false",
"spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"
})
class LinHelpApplicationTests {
@Test
void contextLoads() {
}
}

View File

@@ -0,0 +1,30 @@
services:
mysql:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: linhelp
MYSQL_USER: linhelp
MYSQL_PASSWORD: linhelp
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7
ports:
- "6379:6379"
minio:
image: minio/minio:RELEASE.2025-04-22T22-12-26Z
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: linhelp
MINIO_ROOT_PASSWORD: linhelp123
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
volumes:
mysql_data:
minio_data:

View File

@@ -0,0 +1,6 @@
App({
globalData: {
apiBaseUrl: 'http://localhost:8080',
token: ''
}
})

View File

@@ -0,0 +1,46 @@
{
"pages": [
"pages/home/index",
"pages/products/index",
"pages/products/detail",
"pages/orders/index",
"pages/orders/detail",
"pages/express/create",
"pages/group-buy/index",
"pages/group-buy/detail",
"pages/second-hand/index",
"pages/second-hand/create",
"pages/notices/index",
"pages/profile/index",
"pages/address/index"
],
"window": {
"navigationBarTitleText": "邻小帮",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f6f7f9"
},
"tabBar": {
"color": "#6b7280",
"selectedColor": "#0f766e",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/home/index",
"text": "首页"
},
{
"pagePath": "pages/group-buy/index",
"text": "团购"
},
{
"pagePath": "pages/second-hand/index",
"text": "闲置"
},
{
"pagePath": "pages/profile/index",
"text": "我的"
}
]
}
}

View File

@@ -0,0 +1,9 @@
page {
background: #f6f7f9;
color: #111827;
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
}
.page {
padding: 24rpx;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "地址管理"
}

View File

@@ -0,0 +1 @@
<view class="page">地址管理</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "代取快递"
}

View File

@@ -0,0 +1 @@
<view class="page">代取快递</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "团购详情"
}

View File

@@ -0,0 +1 @@
<view class="page">团购详情</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "今日团购"
}

View File

@@ -0,0 +1 @@
<view class="page">今日团购</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "邻小帮"
}

View File

@@ -0,0 +1 @@
<view class="page">邻小帮</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "社区公告"
}

View File

@@ -0,0 +1 @@
<view class="page">社区公告</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "订单详情"
}

View File

@@ -0,0 +1 @@
<view class="page">订单详情</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "我的订单"
}

View File

@@ -0,0 +1 @@
<view class="page">我的订单</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "商品详情"
}

View File

@@ -0,0 +1 @@
<view class="page">商品详情</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "商品预定"
}

View File

@@ -0,0 +1 @@
<view class="page">商品预定</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "我的"
}

View File

@@ -0,0 +1 @@
<view class="page">我的</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "发布闲置"
}

View File

@@ -0,0 +1 @@
<view class="page">发布闲置</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1 @@
Page({})

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "二手闲置"
}

View File

@@ -0,0 +1 @@
<view class="page">二手闲置</view>

View File

@@ -0,0 +1,3 @@
.page {
min-height: 100vh;
}

View File

@@ -0,0 +1,26 @@
function request(options) {
const app = getApp()
const token = app.globalData.token
return new Promise((resolve, reject) => {
wx.request({
url: app.globalData.apiBaseUrl + options.url,
method: options.method || 'GET',
data: options.data || {},
header: Object.assign({
Authorization: token
}, options.header || {}),
success(res) {
if (res.statusCode >= 200 && res.statusCode < 300 && res.data && res.data.code === 0) {
resolve(res.data.data)
return
}
reject(new Error((res.data && res.data.message) || '请求失败'))
},
fail: reject
})
})
}
module.exports = {
request
}

13
miniapp/package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "linhelp-miniapp",
"version": "0.1.0",
"private": true,
"scripts": {
"test": "jest --runInBand",
"ci:preview": "miniprogram-ci preview --pp ./project.config.json --robot 1"
},
"devDependencies": {
"jest": "^29.7.0",
"miniprogram-ci": "^2.0.0"
}
}

View File

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

25
rider-h5/package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "linhelp-rider-h5",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0 --port 5174",
"build": "vue-tsc -b && vite build",
"test": "vitest run",
"lint": "eslint ."
},
"dependencies": {
"axios": "^1.7.2",
"pinia": "^2.1.7",
"vue": "^3.4.31",
"vue-router": "^4.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.5",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vitest": "^2.0.2",
"vue-tsc": "^2.0.26"
}
}

9
rider-h5/vite.config.ts Normal file
View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5174
}
})