feat: 初始化项目配置和样式- 添加项目环境变量配置文件 (.env)

- 创建代码忽略文件列表 (.gitignore)
- 设置代码格式化规则 (.prettierrc)- 添加各种样式文件,包括背景、边框、按钮、卡片等组件样式
- 创建暗黑主题样式文件
- 添加表单和代码样式文件
This commit is contained in:
liguigong
2025-09-12 09:53:45 +08:00
commit b91b273686
582 changed files with 90552 additions and 0 deletions
+206
View File
@@ -0,0 +1,206 @@
import DiyApi from '@/sheep/api/promotion/diy';
import { getTenantByWebsite } from '@/sheep/api/infra/tenant';
import { getTenantId } from '@/sheep/request';
import { defineStore } from 'pinia';
import $platform from '@/sheep/platform';
import $router from '@/sheep/router';
import user from './user';
import sys from './sys';
import { baseUrl, h5Url } from '@/sheep/config';
const app = defineStore({
id: 'app',
state: () => ({
info: {
// 应用信息
name: '', // 商城名称
logo: '', // logo
version: '', // 版本号
copyright: '', // 版权信息 I
copytime: '', // 版权信息 II
cdnurl: '', // 云存储域名
filesystem: '', // 云存储平台
},
platform: {
share: {
methods: [], // 支持的分享方式
forwardInfo: {}, // 默认转发信息
posterInfo: {}, // 海报信息
linkAddress: '', // 复制链接地址
},
bind_mobile: 0, // 登陆后绑定手机号提醒 (弱提醒,可手动关闭)
},
template: {
// 店铺装修模板
basic: {}, // 基本信息
home: {
// 首页模板
style: {},
data: [],
},
user: {
// 个人中心模板
style: {},
data: [],
},
},
shareInfo: {}, // 全局分享信息
has_wechat_trade_managed: 0, // 小程序发货信息管理 0 没有 || 1 有
}),
actions: {
// 获取Shopro应用配置和模板
async init(templateId = null) {
// 检查网络
const networkStatus = await $platform.checkNetwork();
if (!networkStatus) {
$router.error('NetworkError');
}
// 检查配置
if (typeof baseUrl === 'undefined') {
$router.error('EnvError');
}
// 加载租户
await adaptTenant();
// 加载装修配置
await adaptTemplate(this.template, templateId);
// TODO 芋艿:【初始化优化】未来支持管理后台可配;对应 https://api.shopro.sheepjs.com/shop/api/init
if (true) {
this.info = {
name: '商城',
logo: 'https://static.iocoder.cn/ruoyi-vue-pro-logo.png',
version: '2025.09',
copyright: '全部开源,个人与企业可 100% 免费使用',
copytime: 'Copyright© 2018-2025',
cdnurl: 'https://file.sheepjs.com', // 云存储域名
filesystem: 'qcloud', // 云存储平台
};
this.platform = {
share: {
methods: ['forward', 'poster', 'link'],
linkAddress: h5Url,
posterInfo: {
user_bg: '/static/img/shop/config/user-poster-bg.png',
goods_bg: '/static/img/shop/config/goods-poster-bg.png',
groupon_bg: '/static/img/shop/config/groupon-poster-bg.png',
},
forwardInfo: {
title: '',
image: '',
desc: '',
},
},
bind_mobile: 0,
};
this.has_wechat_trade_managed = 0;
// 加载主题
const sysStore = sys();
sysStore.setTheme();
// 模拟用户登录
const userStore = user();
if (userStore.isLogin) {
userStore.loginAfter();
}
return Promise.resolve(true);
} else {
$router.error('InitError', res.msg || '加载失败');
}
},
},
persist: {
enabled: true,
strategies: [
{
key: 'app-store',
},
],
},
});
/** 初始化租户编号 */
const adaptTenant = async () => {
// 1. 获取当前租户 ID
const oldTenantId = getTenantId();
let newTenantId = null;
try {
// 2.1 情况一:H5:根据 url 参数、域名来获取新的租户ID
// #ifdef H5
// H5 环境下的处理逻辑
if (window?.location) {
// 优先从 URL 查询参数获取 tenantId
const urlParams = new URLSearchParams(window.location.search);
newTenantId = urlParams.get('tenantId');
// 如果 URL 参数中没有,则通过 host 获取
if (!newTenantId && window.location.host) {
const { data } = await getTenantByWebsite(window.location.host);
newTenantId = data?.id;
}
}
// #endif
// 2.2 情况二:微信小程序:小程序环境下的处理逻辑 - 根据 appId 获取租户
// #ifdef MP
const appId = uni.getAccountInfoSync()?.miniProgram?.appId;
if (appId) {
const { data } = await getTenantByWebsite(appId);
newTenantId = data?.id;
}
// #endif
// 3. 如果是新租户(不相等),则进行切换
// noinspection EqualityComparisonWithCoercionJS
if (newTenantId && newTenantId != oldTenantId) {
// 清理掉登录用户的 token
const userStore = user();
userStore.setToken();
// 设置新的 tenantId 到本地存储
uni.setStorageSync('tenant-id', newTenantId);
console.log('租户 ID 已更新:', `${oldTenantId} -> ${newTenantId}`);
}
} catch (error) {
console.error('adaptTenant 执行失败:', error);
}
};
/** 初始化装修模版 */
const adaptTemplate = async (appTemplate, templateId) => {
const { data: diyTemplate } = templateId
? // 查询指定模板,一般是预览时使用
await DiyApi.getDiyTemplate(templateId)
: await DiyApi.getUsedDiyTemplate();
// 模板不存在
if (!diyTemplate) {
$router.error('TemplateError');
return;
}
const tabBar = diyTemplate?.property?.tabBar;
if (tabBar) {
appTemplate.basic.tabbar = tabBar;
// TODO 商城装修没有对 tabBar 进行角标配置,测试角标需打开以下注释
// appTemplate.basic.tabbar.items.forEach((tabBar) => {
// tabBar.dot = false
// tabBar.badge = 100
// })
// appTemplate.basic.tabbar.badgeStyle = {
// backgroundColor: '#882222',
// }
if (tabBar?.theme) {
appTemplate.basic.theme = tabBar?.theme;
}
}
appTemplate.home = diyTemplate?.home;
appTemplate.user = diyTemplate?.user;
};
export default app;
+121
View File
@@ -0,0 +1,121 @@
import { defineStore } from 'pinia';
import CartApi from '@/sheep/api/trade/cart';
const cart = defineStore({
id: 'cart',
state: () => ({
list: [], // 购物车列表(invalidList + validList
selectedIds: [], // 已选列表
isAllSelected: false, // 是否全选
totalPriceSelected: 0, // 选中项总金额
newList: [], // 除去已下架的购物车列表(validList)
editMode: false, // 是否是编辑模式
}),
actions: {
// 获取购物车列表
async getList() {
const { data, code } = await CartApi.getCartList();
if (code === 0) {
this.list = [...data.validList, ...data.invalidList];
this.newList = data.validList;
// 计算各种关联属性
this.selectedIds = [];
this.isAllSelected = true;
this.totalPriceSelected = 0;
(this.editMode ? this.list : this.newList).forEach((item) => {
if (item.selected) {
this.selectedIds.push(item.id);
this.totalPriceSelected += item.count * item.sku?.price;
} else {
this.isAllSelected = false;
}
});
}
},
onChangeEditMode(flag) {
this.editMode = flag;
this.selectedIds = [];
this.getList();
},
// 添加购物车
async add(goodsInfo) {
// 添加购物项
const { code } = await CartApi.addCart({
skuId: goodsInfo.id,
count: goodsInfo.goods_num,
});
// 刷新购物车列表
if (code === 0) {
await this.getList();
}
},
// 更新购物车
async update(goodsInfo) {
const { code } = await CartApi.updateCartCount({
id: goodsInfo.goods_id,
count: goodsInfo.goods_num,
});
if (code === 0) {
await this.getList();
}
},
// 移除购物车
async delete(ids) {
let idsTemp = '';
if (Array.isArray(ids)) {
idsTemp = ids.join(',');
} else {
idsTemp = ids;
}
const { code } = await CartApi.deleteCart(idsTemp);
if (code === 0) {
await this.getList();
}
},
// 单选购物车商品
async selectSingle(goodsId) {
const { code } = await CartApi.updateCartSelected({
ids: [goodsId],
selected: !this.selectedIds.includes(goodsId), // 取反
});
if (code === 0) {
await this.getList();
}
},
// 全选购物车商品
async selectAll(flag) {
const { code } = await CartApi.updateCartSelected({
ids: this.list.map((item) => item.id),
selected: flag,
});
if (code === 0) {
await this.getList();
}
},
// 清空购物车。注意,仅用于用户退出时,重置数据
emptyList() {
this.list = [];
this.selectedIds = [];
this.isAllSelected = true;
this.totalPriceSelected = 0;
},
},
persist: {
enabled: true,
strategies: [
{
key: 'cart-store',
},
],
},
});
export default cart;
+20
View File
@@ -0,0 +1,20 @@
import { createPinia } from 'pinia';
import piniaPersist from 'pinia-plugin-persist-uni';
// 自动注入所有pinia模块
const files = import.meta.glob('./*.js', { eager: true });
const modules = {};
Object.keys(files).forEach((key) => {
modules[key.replace(/(.*\/)*([^.]+).*/gi, '$2')] = files[key].default;
});
export const setupPinia = (app) => {
const pinia = createPinia();
pinia.use(piniaPersist);
app.use(pinia);
};
export default (name) => {
return modules[name]();
};
+29
View File
@@ -0,0 +1,29 @@
import { defineStore } from 'pinia';
const modal = defineStore({
id: 'modal',
state: () => ({
auth: '', // 授权弹框 accountLogin|smsLogin|resetPassword|changeMobile|changePassword|changeUsername
share: false, // 分享弹框
menu: false, // 快捷菜单弹框
advHistory: [], // 广告弹框记录
lastTimer: {
// 短信验证码计时器,为了防止刷新请求做了持久化
smsLogin: 0,
changeMobile: 0,
resetPassword: 0,
changePassword: 0,
}
}),
persist: {
enabled: true,
strategies: [
{
key: 'modal-store',
paths: ['lastTimer', 'advHistory'],
},
],
},
});
export default modal;
+32
View File
@@ -0,0 +1,32 @@
import { defineStore } from 'pinia';
import app from './app';
const sys = defineStore({
id: 'sys',
state: () => ({
theme: '', // 主题,
mode: 'light', // 明亮模式、暗黑模式(暂未支持)
modeAuto: false, // 跟随系统
fontSize: 1, // 设置默认字号等级(0-4)
}),
getters: {},
actions: {
setTheme(theme = '') {
if (theme === '') {
this.theme = app().template?.basic.theme || 'orange';
} else {
this.theme = theme;
}
},
},
persist: {
enabled: true,
strategies: [
{
key: 'sys-store',
},
],
},
});
export default sys;
+164
View File
@@ -0,0 +1,164 @@
import { defineStore } from 'pinia';
import $share from '@/sheep/platform/share';
import { clone, cloneDeep } from 'lodash-es';
import cart from './cart';
import app from './app';
import { showAuthModal } from '@/sheep/hooks/useModal';
import UserApi from '@/sheep/api/member/user';
import PayWalletApi from '@/sheep/api/pay/wallet';
import OrderApi from '@/sheep/api/trade/order';
import CouponApi from '@/sheep/api/promotion/coupon';
// 默认用户信息
const defaultUserInfo = {
avatar: '', // 头像
nickname: '', // 昵称
gender: 0, // 性别
mobile: '', // 手机号
point: 0, // 积分
};
// 默认钱包信息
const defaultUserWallet = {
balance: 0, // 余额
};
// 默认订单、优惠券等其他资产信息
const defaultNumData = {
unusedCouponCount: 0,
orderCount: {
allCount: 0,
unpaidCount: 0,
undeliveredCount: 0,
deliveredCount: 0,
uncommentedCount: 0,
afterSaleCount: 0,
},
};
const user = defineStore({
id: 'user',
state: () => ({
userInfo: clone(defaultUserInfo), // 用户信息
userWallet: clone(defaultUserWallet), // 用户钱包信息
isLogin: !!uni.getStorageSync('token'), // 登录状态
numData: cloneDeep(defaultNumData), // 用户其他数据
lastUpdateTime: 0, // 上次更新时间
}),
actions: {
// 获取用户信息
async getInfo() {
const { code, data } = await UserApi.getUserInfo();
if (code !== 0) {
return;
}
this.userInfo = data;
return Promise.resolve(data);
},
// 获得用户钱包
async getWallet() {
const { code, data } = await PayWalletApi.getPayWallet();
if (code !== 0) {
return;
}
this.userWallet = data;
},
// 获取订单、优惠券等其他资产信息
getNumData() {
OrderApi.getOrderCount().then((res) => {
if (res.code === 0) {
this.numData.orderCount = res.data;
}
});
CouponApi.getUnusedCouponCount().then((res) => {
if (res.code === 0) {
this.numData.unusedCouponCount = res.data;
}
});
},
// 设置 token
setToken(token = '', refreshToken = '') {
if (token === '') {
this.isLogin = false;
uni.removeStorageSync('token');
uni.removeStorageSync('refresh-token');
} else {
this.isLogin = true;
uni.setStorageSync('token', token);
uni.setStorageSync('refresh-token', refreshToken);
this.loginAfter();
}
return this.isLogin;
},
// 更新用户相关信息 (手动限流,5 秒之内不刷新)
async updateUserData() {
if (!this.isLogin) {
this.resetUserData();
return;
}
// 防抖,5 秒之内不刷新
const nowTime = new Date().getTime();
if (this.lastUpdateTime + 5000 > nowTime) {
return;
}
this.lastUpdateTime = nowTime;
// 获取最新信息
await this.getInfo();
this.getWallet();
this.getNumData();
return this.userInfo;
},
// 重置用户默认数据
resetUserData() {
// 清空 token
this.setToken();
// 清空用户相关的缓存
this.userInfo = clone(defaultUserInfo);
this.userWallet = clone(defaultUserWallet);
this.numData = cloneDeep(defaultNumData);
// 清空购物车的缓存
cart().emptyList();
},
// 登录后,加载各种信息
async loginAfter() {
await this.updateUserData();
// 加载购物车
cart().getList();
// 登录后设置全局分享参数
$share.getShareInfo();
// 提醒绑定手机号
if (app().platform.bind_mobile && !this.userInfo.mobile) {
showAuthModal('changeMobile');
}
// 绑定推广员
$share.bindBrokerageUser();
},
// 登出系统
async logout() {
this.resetUserData();
return !this.isLogin;
},
},
persist: {
enabled: true,
strategies: [
{
key: 'user-store',
},
],
},
});
export default user;