This commit is contained in:
yuhawu 2025-08-13 10:03:12 +08:00
parent ed742ddd4a
commit 9c7ea6ff0b
6 changed files with 493 additions and 198 deletions

View File

@ -11,4 +11,5 @@ export { adminApi } from './modules/admin'
export { invitationApi } from './modules/invitation'
export { depotApi } from './modules/depot'
export { userApi } from './modules/user'
export { userLoginApi } from './modules/userLogin'
export { userLoginApi } from './modules/userLogin'
export { priceTemplateApi } from './modules/priceTemplate'

View File

@ -1,73 +1,23 @@
import request from '@/utils/axios'
import instance from '../../utils/axios.js'
/**
* 获取所有省级数据
* 地区管理相关接口
*/
export function getProvinces() {
return request({
url: '/district/provinces',
method: 'get'
})
}
/**
* 根据省份ID获取城市列表
*/
export function getCitiesByProvinceId(provinceId) {
return request({
url: `/district/cities/${provinceId}`,
method: 'get'
})
}
// 获取省份列表
export const getProvinces = () => {
return instance.get('/district/provinces');
};
/**
* 根据城市ID获取区县列表
*/
export function getDistrictsByCityId(cityId) {
return request({
url: `/district/districts/${cityId}`,
method: 'get'
})
}
// 获取运费信息
export const getFreInfo = (templateId) => {
return instance.get(`/district/freInfo/${templateId}`);
};
/**
* 获取省级市级树形结构
*/
export function getDistrictTree() {
return request({
url: '/district/getDistrictTree',
method: 'get'
})
}
// 为了向后兼容,也导出整个对象
export const districtApi = {
getProvinces,
getFreInfo
};
/**
* 新增物流模板
*/
export function createTemplate(data) {
return request({
url: '/logistics/logistics',
method: 'post',
data: data
})
}
/**
* 获取运费信息
*/
export function getFreInfo(id) {
return request({
url: '/logistics/logistics/' + id,
method: 'get'
})
}
/**
* 更新物流模板
*/
export function UpdateTemplate(data) {
return request({
url: '/logistics/logistics',
method: 'put',
data: data
})
}
export default districtApi;

View File

@ -75,6 +75,10 @@ const menuData = shallowRef([
title: '店铺列表',
path: '/shop/list',
permission: 'shop:list:view'
},
{
title: '价格模板',
path: '/shop/priceTemplate'
}
]
},
@ -87,6 +91,11 @@ const menuData = shallowRef([
title: '选品中心',
path: '/book/selection/center',
permission: 'book:selection:view'
},
{
title: '自营书品',
path: '/book/shopGoods',
// permission: 'book:shopGoods:view'
}
]
},

View File

@ -113,6 +113,18 @@ const routes = [{
// meta: { title: '物流模板', permission: 'logistics:view' }
meta: { title: '物流模板' }
},
{
path: '/shop/priceTemplate',
component: () => import('@/views/PriceTemplate/index.vue'),
// meta: { title: '价格模板', permission: 'priceTemplate:list:view' }
meta: { title: '价格模板' }
},
{
path: '/book/shopGoods',
component: () => import('@/views/shopGoods/index.vue'),
// meta: { title: '自营书品', permission: 'book:shopGoods:view' }
meta: { title: '自营书品'}
}
]

View File

@ -15,7 +15,7 @@
<el-input v-model="queryParams.fileName" placeholder="请输入文件名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
@ -119,12 +119,30 @@
<el-cascader :options="catsList" v-model="formRelease.bookCategoryAppoint" :show-all-levels="false" />
</el-form-item>
<el-form-item label="店铺选择" prop="shopIds" label-width="100px" style="width: 100%">
<el-checkbox-group v-model="formRelease.shopIds" style="flex: 1;">
<el-checkbox v-for="item in shopList" :key="item.value" :label="item.value" style="margin-right: 15px;">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-form-item prop="shopIds" label-width="100px" style="width: 100%">
<div style="flex: 1;">
<!-- 孔夫子店铺 -->
<div v-if="shopList.kfzShops && shopList.kfzShops.length > 0" style="margin-bottom: 15px;">
<span style="margin-right: 15px; color: #606266; font-size: 14px;">孔夫子店铺</span>
<el-checkbox-group v-model="formRelease.shopIds" style="display: inline-block;">
<el-checkbox v-for="item in shopList.kfzShops" :key="item.value" :label="item.value"
style="margin-right: 15px;">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</div>
<!-- 拼多多店铺 -->
<div v-if="shopList.pddShops && shopList.pddShops.length > 0">
<span style="margin-right: 15px; color: #606266; font-size: 14px;">拼多多店铺</span>
<el-checkbox-group v-model="formRelease.shopIds" style="display: inline-block;">
<el-checkbox v-for="item in shopList.pddShops" :key="item.value" :label="item.value"
style="margin-right: 15px;">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</el-form-item>
<el-form-item label="优先图片" prop="imageSelect" label-width="100px" style="width: 100%">
@ -420,11 +438,31 @@ const getShopListData = async () => {
const data = response.data;
if (data && Array.isArray(data) && data.length > 0) {
//
shopList.value = data.map(shop => ({
value: shop.id,
label: shop.shopName || shop.name
}));
// shop_type
const kfzShops = []; // (shop_type = 2)
const pddShops = []; // (shop_type = 1)
data.forEach(shop => {
const shopItem = {
value: shop.id,
label: shop.shopName || shop.name,
shopType: shop.shopType
};
// APIshopType
if (shop.shopType === '2') {
kfzShops.push(shopItem);
} else if (shop.shopType === '1') {
pddShops.push(shopItem);
}
});
//
shopList.value = {
kfzShops,
pddShops
};
console.log('设置后的 shopList:', shopList.value);
}
} catch (error) {
@ -568,7 +606,7 @@ const handleAdd = async () => {
}
//
if (shopList.value.length === 0) {
if (!shopList.value.kfzShops && !shopList.value.pddShops) {
await getShopListData();
}

View File

@ -1,100 +1,107 @@
<template>
<div class="register-page">
<div class="register-container">
<div class="register-form">
<!-- 标题 -->
<div class="form-header">
<h2>与书同行</h2>
<!-- <div class="language-switch">
<span>A</span>
</div> -->
<div class="page-container">
<!-- 左侧注册区域 -->
<div class="left-section">
<div class="section-title">
<h1>未注册用户请在下方注册</h1>
</div>
<div class="register-form">
<!-- 标题 -->
<div class="form-header">
<h2>与书同行</h2>
</div>
<!-- 表单 -->
<el-form ref="formRef" :model="formData" :rules="rules" label-width="0">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input
v-model="formData.username"
placeholder="用户名"
size="large"
:prefix-icon="User"
disabled
/>
</el-form-item>
<!-- 表单 -->
<el-form ref="formRef" :model="formData" :rules="rules" label-width="0">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input v-model="formData.username" placeholder="用户名" size="large" :prefix-icon="User"
disabled />
</el-form-item>
<!-- 手机号 -->
<el-form-item prop="phoneNumber">
<el-input
v-model="formData.phoneNumber"
placeholder="手机号"
size="large"
:prefix-icon="Phone"
/>
</el-form-item>
<!-- 手机号 -->
<el-form-item prop="phoneNumber">
<el-input v-model="formData.phoneNumber" placeholder="手机号" size="large"
:prefix-icon="Phone" />
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input
v-model="formData.password"
type="password"
placeholder="密码"
size="large"
:prefix-icon="Lock"
show-password
/>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input v-model="formData.password" type="password" placeholder="密码" size="large"
:prefix-icon="Lock" show-password />
</el-form-item>
<!-- 确认密码 -->
<el-form-item prop="confirmPassword">
<el-input
v-model="formData.confirmPassword"
type="password"
placeholder="确认密码"
size="large"
:prefix-icon="Lock"
show-password
/>
</el-form-item>
<!-- 确认密码 -->
<el-form-item prop="confirmPassword">
<el-input v-model="formData.confirmPassword" type="password" placeholder="确认密码" size="large"
:prefix-icon="Lock" show-password />
</el-form-item>
<!-- 邀请码 -->
<el-form-item prop="inviteCode">
<el-input
v-model="formData.inviteCode"
placeholder="邀请码(非必填)"
size="large"
:prefix-icon="Message"
/>
</el-form-item>
<!-- 邀请码 -->
<el-form-item prop="inviteCode">
<el-input v-model="formData.inviteCode" placeholder="邀请码(非必填)" size="large"
:prefix-icon="Message" />
</el-form-item>
<!-- 验证码 -->
<el-form-item v-if="captchaEnabled" prop="code">
<div class="captcha-row">
<el-input
v-model="formData.code"
placeholder="验证码"
size="large"
:prefix-icon="Key"
/>
<div class="captcha-image" @click="getCaptcha">
<img v-if="captchaImg" :src="captchaImg" alt="验证码" />
<!-- 验证码 -->
<el-form-item v-if="captchaEnabled" prop="code">
<div class="captcha-row">
<el-input v-model="formData.code" placeholder="验证码" size="large" :prefix-icon="Key" />
<div class="captcha-image" @click="getCaptcha">
<img v-if="captchaImg" :src="captchaImg" alt="验证码" />
</div>
</div>
</div>
</el-form-item>
</el-form-item>
<!-- 注册按钮 -->
<el-form-item>
<el-button
type="primary"
size="large"
class="register-btn"
@click="handleRegister"
:loading="loading"
>
注册
</el-button>
</el-form-item>
</el-form>
<!-- 注册按钮 -->
<el-form-item>
<el-button type="primary" size="large" class="register-btn" @click="handleRegister"
:loading="loading">
注册
</el-button>
</el-form-item>
</el-form>
</div>
</div>
<!-- 右侧已注册用户区域 -->
<div class="right-section">
<div class="section-title">
<h1>已注册用户请到浏览器打开后台管理系统</h1>
</div>
<div class="login-info">
<div class="login-url">
<p class="url-label">后台管理系统地址</p>
<div class="url-box">
<span class="url-text">https://erp.buzhiyushu.cn/</span>
<el-button type="primary" size="small" @click="copyLoginUrl" class="copy-btn">
复制链接
</el-button>
</div>
</div>
<div class="flow-chart">
<h3>操作流程图</h3>
<div class="chart-container" @click="showFlowChart">
<img src="/flow-chart.png" alt="操作流程图" class="flow-image" />
<div class="click-tip">点击查看大图</div>
</div>
</div>
</div>
</div>
</div>
<!-- 全屏图片查看器 -->
<div v-if="showImageViewer" class="image-viewer-overlay" @click="closeImageViewer">
<div class="image-viewer-container">
<div class="image-viewer-header">
<h3>操作流程图</h3>
<button class="close-btn" @click="closeImageViewer">×</button>
</div>
<div class="image-viewer-content">
<img src="/flow-chart.png" alt="操作流程图" class="full-image" />
</div>
</div>
</div>
</div>
@ -408,6 +415,39 @@ const showSuccessDialog = () => {
})
}
//
const copyLoginUrl = async () => {
const loginUrl = 'https://erp.buzhiyushu.cn/'
try {
await navigator.clipboard.writeText(loginUrl)
ElMessage.success('链接已复制到剪贴板!')
} catch (err) {
// 使
try {
const textArea = document.createElement('textarea')
textArea.value = loginUrl
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
ElMessage.success('链接已复制到剪贴板!')
} catch (fallbackErr) {
ElMessage.error('复制失败,请手动复制链接')
}
}
}
//
const showImageViewer = ref(false)
const showFlowChart = () => {
showImageViewer.value = true
}
const closeImageViewer = () => {
showImageViewer.value = false
}
// URL
onMounted(() => {
getUrlParams()
@ -425,11 +465,33 @@ onMounted(() => {
padding: 20px;
}
.register-container {
.page-container {
display: flex;
width: 100%;
max-width: 1200px;
gap: 40px;
align-items: flex-start;
}
/* 左侧注册区域 */
.left-section {
flex: 0 0 400px;
max-width: 400px;
}
.section-title {
text-align: center;
margin-bottom: 30px;
}
.section-title h1 {
color: white;
font-size: 24px;
font-weight: 500;
margin: 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.register-form {
background: white;
border-radius: 12px;
@ -439,7 +501,7 @@ onMounted(() => {
.form-header {
display: flex;
justify-content: space-between;
justify-content: center;
align-items: center;
margin-bottom: 30px;
}
@ -451,23 +513,107 @@ onMounted(() => {
font-weight: 500;
}
.language-switch {
width: 32px;
height: 32px;
background: #f0f0f0;
border-radius: 6px;
/* 右侧已注册用户区域 */
.right-section {
flex: 1;
max-width: 600px;
}
.login-info {
background: white;
border-radius: 12px;
padding: 40px 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.login-url {
margin-bottom: 30px;
}
.url-label {
font-size: 16px;
color: #333;
margin-bottom: 15px;
font-weight: 500;
}
.url-box {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
gap: 10px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
border: 1px solid #e9ecef;
}
.language-switch span {
.url-text {
flex: 1;
color: #495057;
font-size: 14px;
color: #666;
font-weight: bold;
word-break: break-all;
}
.copy-btn {
flex-shrink: 0;
}
.flow-chart {
text-align: center;
}
.flow-chart h3 {
font-size: 18px;
color: #333;
margin-bottom: 20px;
font-weight: 500;
}
.chart-container {
position: relative;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
}
.chart-container:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
transform: translateY(-2px);
}
.flow-image {
width: 100%;
height: auto;
display: block;
max-width: 100%;
transition: transform 0.3s ease;
}
.chart-container:hover .flow-image {
transform: scale(1.02);
}
.click-tip {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
color: white;
text-align: center;
padding: 15px 10px 10px;
font-size: 14px;
opacity: 0;
transition: opacity 0.3s ease;
}
.chart-container:hover .click-tip {
opacity: 1;
}
/* 表单样式 */
.el-form-item {
margin-bottom: 20px;
}
@ -490,8 +636,6 @@ onMounted(() => {
box-shadow: 0 0 0 1px #409eff;
}
.captcha-row {
display: flex;
gap: 10px;
@ -531,30 +675,171 @@ onMounted(() => {
background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
}
.login-link {
text-align: center;
margin-top: 20px;
}
.login-link span {
color: #666;
font-size: 14px;
cursor: pointer;
}
.login-link span:hover {
color: #409eff;
}
/* 移动端适配 */
@media (max-width: 480px) {
.register-form {
@media (max-width: 768px) {
.page-container {
flex-direction: column;
gap: 30px;
}
.left-section,
.right-section {
max-width: 100%;
}
.register-form,
.login-info {
padding: 30px 20px;
margin: 10px;
}
.section-title h1 {
font-size: 20px;
}
.form-header h2 {
font-size: 20px;
}
.url-box {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.copy-btn {
align-self: center;
}
}
@media (max-width: 480px) {
.register-page {
padding: 10px;
}
.page-container {
gap: 20px;
}
.section-title h1 {
font-size: 18px;
}
.register-form,
.login-info {
padding: 25px 15px;
}
}
/* 全屏图片查看器样式 */
.image-viewer-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.9);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.image-viewer-container {
background: white;
border-radius: 12px;
max-width: 95vw;
max-height: 95vh;
display: flex;
flex-direction: column;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.image-viewer-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 30px;
border-bottom: 1px solid #eee;
flex-shrink: 0;
}
.image-viewer-header h3 {
margin: 0;
font-size: 20px;
color: #333;
font-weight: 500;
}
.close-btn {
background: none;
border: none;
font-size: 28px;
color: #999;
cursor: pointer;
padding: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.close-btn:hover {
background: #f5f5f5;
color: #333;
}
.image-viewer-content {
padding: 20px;
overflow: auto;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.full-image {
max-width: none;
max-height: none;
width: auto;
height: auto;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
/* 确保图片以原始尺寸显示,但不超过容器 */
max-width: calc(95vw - 40px);
max-height: calc(95vh - 120px);
}
/* 移动端图片查看器适配 */
@media (max-width: 768px) {
.image-viewer-overlay {
padding: 10px;
}
.image-viewer-container {
max-width: 100vw;
max-height: 100vh;
border-radius: 8px;
}
.image-viewer-header {
padding: 15px 20px;
}
.image-viewer-header h3 {
font-size: 18px;
}
.image-viewer-content {
padding: 15px;
}
.full-image {
max-width: calc(100vw - 30px);
max-height: calc(100vh - 100px);
}
}
</style>