Compare commits

...

3 Commits

Author SHA1 Message Date
ChoChoX
e1e45cee1a feat: 更新项目代码 2026-06-15 21:05:05 +08:00
Kyaru
cbbade3b9c Merge branch 'main' of https://chochox.asia/ChoChoX/backmanagerweb 2026-06-15 20:53:55 +08:00
Kyaru
b067ea3723 首页和第一页的部分完成,css部分待完善 2026-06-15 20:49:34 +08:00
25 changed files with 3065 additions and 2699 deletions

View File

@@ -10,7 +10,7 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.2",
"axios": "^1.17.0",
"element-china-area-data": "^6.1.0",
"element-plus": "^2.14.1",
"pinia": "^3.0.4",
"vue": "^3.5.34",

BIN
public/mixue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

194
src/components/home.vue Normal file
View File

@@ -0,0 +1,194 @@
<template>
<div class="home-container">
<div class="banner">
<video src="../../public/蜜雪冰城-雪王百科.mp4" autoplay muted loop></video>
</div>
</div>
<div class="home-body">
<div class="first-head">雪王简介</div>
<div class="intro-content">
<div class="pic">
<img src="../../public/mixue.png" alt="雪王">
</div>
<div class="txt">
<div class="second-head">
"我是手拿冰淇凌权杖的雪王"
<br>
"一生只爱冰淇凌与茶"
</div>
<ul class="xuewang-list">
<li v-for="(item, index) in snowKingInfo" :key="index">
<span class="label">{{ item.label }}</span>
<span class="divider"></span>
<span class="value">{{ item.value }}</span>
</li>
</ul>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const snowKingInfo = ref([
{ label: '生日', value: '11月22日' },
{ label: '性格', value: '正直、友善、热情、进取' },
{ label: '职位', value: '蜜雪冰城首席品控官兼全球品牌代言人' },
{ label: '口头禅', value: '你爱我,我爱你,蜜雪冰城甜蜜蜜' },
{ label: '爱好', value: '唱歌跳舞,研究冰淇淋与茶的新奇吃法' }
])
</script>
<style scoped>
.home-container {
padding: 0;
text-align: center;
}
.banner {
width: 100%;
height: 90vh;
min-height: 500px;
}
.banner video {
width: 100%;
height: 100%;
object-fit: cover;
}
.home-body {
padding: 100px 80px;
background: linear-gradient(180deg, #FEF7F7 0%, rgba(254, 247, 247, 0.00) 64.96%);
}
.first-head {
text-align: center;
font-size: 58px;
font-weight: 700;
color: #2E2F30;
margin-bottom: 68px;
line-height: 1.17;
}
.intro-content {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1400px;
margin: 0 auto;
}
.pic {
width: 750px;
height: 660px;
border-radius: 30px;
overflow: hidden;
}
.pic img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s;
}
.pic:hover img {
transform: scale(1.05);
}
.txt {
width: 676px;
}
.second-head {
font-size: 46px;
font-weight: 700;
color: #E60012;
line-height: 1.33;
margin-bottom: 67px;
}
.xuewang-list {
list-style: none;
padding: 0;
}
.xuewang-list li {
display: flex;
align-items: center;
margin-bottom: 18px;
color: #666;
font-size: 24px;
font-weight: 400;
line-height: 1.5;
}
.xuewang-list li:last-child {
margin-bottom: 0;
}
.xuewang-list .label {
color: #2E2F30;
font-weight: 700;
min-width: 80px;
}
.xuewang-list .divider {
width: 1px;
height: 18px;
background-color: #999;
margin: 0 15px;
}
.xuewang-list .value {
display: flex;
align-items: center;
}
/* 响应式适配 */
@media (max-width: 1200px) {
.intro-content {
flex-direction: column;
}
.pic {
width: 100%;
height: auto;
aspect-ratio: 750/660;
}
.txt {
width: 100%;
margin-top: 48px;
}
}
@media (max-width: 768px) {
.home-body {
padding: 50px 20px;
}
.first-head {
font-size: 36px;
margin-bottom: 40px;
}
.second-head {
font-size: 28px;
margin-bottom: 40px;
}
.xuewang-list li {
font-size: 18px;
flex-direction: column;
align-items: flex-start;
}
.xuewang-list .divider {
display: none;
}
}
</style>

View File

@@ -1,9 +1,146 @@
<script setup>
import { Search } from '@element-plus/icons-vue'
import { ref,reactive } from 'vue'
import { regionData } from 'element-china-area-data'
import { ElMessage } from 'element-plus'
const form = reactive({
name: '', // 姓名,默认为空字符串
phone: '', // 电话,默认为空字符串
region: [], // 地区,默认为空数组(省市区三级代码)
address: '', // 详细地址,默认为空字符串
email: '', // 电子邮箱,默认为空字符串
customer_type: 'Normal' // 客户类型,默认选中"普通客户"
})
const search = ref('')
const select = ref('1')
const searchResults=ref([])
const showSearchResults=ref(false) //是否显示搜索结果
const showAddForm=ref(false) //是否显示新增表单
const isEditMode = ref(false) //是否为编辑模式
const currentCustomerId = ref(null) //当前编辑的客户的ID
// 清空表单
const resetForm = () => {
form.name = ''
form.phone = ''
form.region = []
form.address = ''
form.email = ''
form.customer_type = 'Normal'
isEditMode.value = false
currentCustomerId.value = null
}
// 显示新增表单
const addCustomer = () => {
resetForm()
showAddForm.value = true
showSearchResults.value = false
}
// 清空搜索
const clearSearch = () => {
search.value = ''
showSearchResults.value = false
showAddForm.value = false
}
</script>
<template>
<h1>hello ,im 1</h1>
<div class="customer-container">
<!-- 搜索栏区域 -->
<div class="customer-search">
<el-input v-model="search" style="max-width: 600px" placeholder="Please input"
class="customer-search-with-select">
<template #prepend>
<el-select v-model="select" placeholder="Select" style="width: 115px">
<el-option label="姓名" value="1" />
<el-option label="电话" value="2" />
<el-option label="邮箱" value="3" />
</el-select>
</template>
<template #append>
<el-button :icon="Search" />
</template>
</el-input>
<el-button type="primary" @click="addCustomer" style="margin-left: 20px">
新增用户
</el-button>
</div>
<div v-if="showSearchResults" class="customer-table">
<el-table :data="searchResults" border style="width: 100%">
<el-table-column prop="name" label="姓名" width="120" />
<el-table-column prop="phone" label="电话" width="150" />
<el-table-column prop="regionText" label="地区" width="200" />
<el-table-column prop="address" label="详细地址" width="200" />
<el-table-column prop="email" label="电子邮箱" width="200" />
<el-table-column prop="customer_type" label="代理商类型" width="120">
<template #default="{ row }">
<el-tag :type="row.customer_type === 'VIP' ? 'danger' : 'info'">
{{ row.customer_type === 'VIP' ? '地区总代理' : '普通代理' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="editCustomer(row)">编辑</el-button>
<el-button link type="danger" @click="deleteCustomer(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 10px; color: #909399; font-size: 14px;">
找到 {{ searchResults.length }} 条结果
<el-button link type="primary" @click="clearSearch">清空搜索</el-button>
</div>
</div>
<!-- 新增客户表单 -->
<div v-if="showAddForm" class="customer-info-label">
<el-form :model="form" label-width="auto" style="max-width: 600px" label-position="top">
<el-form-item label="姓名">
<el-input v-model="form.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" :controls="false" :min="0" :max="99999999999" :precision="0"
placeholder="请输入11位手机号" style="width: 100%" />
</el-form-item>
<el-form-item label="地区">
<el-cascader v-model="form.region" :options="regionData" :props="{ expandTrigger: 'hover' }"
placeholder="请选择省/市/区" clearable style="width: 100%" />
</el-form-item>
<el-form-item label="详细地址">
<el-input v-model="form.address" placeholder=" 请输入详细地址" />
</el-form-item>
<el-form-item label="电子邮箱">
<el-input v-model="form.email" placeholder=" 请输入邮箱地址" />
</el-form-item>
<el-form-item label="代理商类型">
<el-radio-group v-model="form.customer_type">
<el-radio value="VIP">地区总代理</el-radio>
<el-radio value="Normal">普通代理</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveCustomer">保存</el-button>
<el-button type="danger" @click="cancelAdd">取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<style scoped>

View File

@@ -1,7 +1,6 @@
<script setup>
import {ref} from 'vue'
import {useRoute} from 'vue-router'
import {ArrowLeft, Location, Menu as IconMenu, SwitchButton,} from '@element-plus/icons-vue'
const route = useRoute()
@@ -43,24 +42,38 @@ const switchFold = () => {
router
style="flex: 1; display: flex; flex-direction: column"
>
<el-sub-menu index="1">
<!-- <el-sub-menu index="1">
<template #title>
<el-icon><IconMenu/></el-icon>
<span>一号栏</span>
</template>
<el-menu-item index="/panel/page1">
<el-icon><Location/></el-icon>
<template #title>item one</template>
</el-sub-menu> -->
<el-menu-item index="/panel/home">
<el-icon><House /></el-icon>
<template #title>首页</template>
</el-menu-item>
<el-menu-item index="/panel/page1">
<el-icon><Avatar /></el-icon>
<template #title>客户管理</template>
</el-menu-item>
</el-sub-menu>
<el-menu-item index="/panel/page2">
<el-icon><Location/></el-icon>
<template #title>二号栏</template>
<el-icon><Document /></el-icon>
<template #title>合同管理</template>
</el-menu-item>
<el-menu-item index="/panel/page3">
<el-icon><Location/></el-icon>
<template #title>三号栏</template>
<el-icon><Service /></el-icon>
<template #title>售后管理</template>
</el-menu-item>
<el-menu-item index="/panel/page3">
<el-icon><IceTea /></el-icon>
<template #title>产品管理</template>
</el-menu-item>
<el-menu-item index="/panel/page3">
<el-icon><User /></el-icon>
<template #title>员工管理</template>
</el-menu-item>
<!-- 关键margin-top: auto 把它推到最底部 -->

View File

@@ -3,11 +3,16 @@ import {createApp} from 'vue'
import './style.css'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(ElementPlus)
app.use(router)
router.isReady().then(() => app.mount('#app'))

View File

@@ -1,5 +1,6 @@
import {createRouter, createWebHistory} from "vue-router";
import Login from "./components/Login.vue";
import Home from "./components/home.vue"
import Panel from "./components/panel.vue";
import Page1 from "./components/page1.vue";
import Page2 from "./components/page2.vue";
@@ -11,9 +12,9 @@ const routes = [
{
path: "/panel",
component: Panel,
redirect: "/panel/page1",
meta: { requiresAuth: true},
redirect: "/panel/home",
children: [
{ path: "home", component:Home},
{ path: "page1", component: Page1 },
{ path: "page2", component: Page2 },
{ path: "page3", component: Page3 },

View File

@@ -34,7 +34,7 @@
"@element-plus/icons-vue@^2.3.2":
version "2.3.2"
resolved "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz"
resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz#7e9cb231fb738b2056f33e22c3a29e214b538dcf"
integrity sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==
"@emnapi/core@1.10.0":
@@ -359,6 +359,12 @@ async-validator@^4.2.5:
resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz"
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
<<<<<<< HEAD
china-division@^2.7.0:
version "2.7.0"
resolved "https://registry.npmmirror.com/china-division/-/china-division-2.7.0.tgz#4060a4d243be66c7833dea64a48a4038f3e53e74"
integrity sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA==
=======
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -400,6 +406,7 @@ copy-anything@^4:
integrity sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==
dependencies:
is-what "^5.2.0"
>>>>>>> 7b927ff6e9b2436d1a599c56ca3f1719cdd1a9ab
csstype@^3.2.3:
version "3.2.3"
@@ -428,6 +435,14 @@ detect-libc@^2.0.3:
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz"
integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
<<<<<<< HEAD
element-china-area-data@^6.1.0:
version "6.1.0"
resolved "https://registry.npmmirror.com/element-china-area-data/-/element-china-area-data-6.1.0.tgz#f14b90c0762b21432e097ed5be8423514a0b57e3"
integrity sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==
dependencies:
china-division "^2.7.0"
=======
dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
@@ -436,6 +451,7 @@ dunder-proto@^1.0.1:
call-bind-apply-helpers "^1.0.1"
es-errors "^1.3.0"
gopd "^1.2.0"
>>>>>>> 7b927ff6e9b2436d1a599c56ca3f1719cdd1a9ab
element-plus@^2.14.1:
version "2.14.1"