This commit is contained in:
2025-09-29 21:38:32 +08:00
parent ed26244cdb
commit 19117de6c8
182 changed files with 11590 additions and 2156 deletions

1
frontend/.env.local Normal file
View File

@@ -0,0 +1 @@
VITE_APP_API_BASE_URL=http://192.168.31.192:8080

View File

@@ -49,3 +49,8 @@ export const KPI_ICONS = {
stockCount: '/static/icons/product.png'
}
// 登录页顶部图片,避免在页面硬编码,允许通过环境变量或本地存储覆盖
const envAuthLoginImg = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_AUTH_LOGIN_TOP_IMAGE || process.env.AUTH_LOGIN_TOP_IMAGE)) || '';
const storageAuthLoginImg = typeof uni !== 'undefined' ? (uni.getStorageSync('AUTH_LOGIN_TOP_IMAGE') || '') : '';
export const AUTH_LOGIN_TOP_IMAGE = String(envAuthLoginImg || storageAuthLoginImg || '/static/icons/undraw_visual-data_1eya.png');

View File

@@ -42,3 +42,11 @@ export const STORAGE_KEYS = {
}
// KPI 标签常量,避免页面硬编码
export const KPI_LABELS = {
todaySales: '今日销售额',
monthSales: '本月销售额',
monthProfit: '本月利润',
stockCount: '库存量'
}

View File

@@ -38,11 +38,23 @@
}
},
{
"path": "pages/product/form",
"path": "pages/product/submission-detail",
"style": {
"navigationBarTitleText": "编辑货品"
"navigationBarTitleText": "提交详情"
}
},
{
"path": "pages/product/form",
"style": {
"navigationBarTitleText": "编辑货品"
}
},
{
"path": "pages/product/product-detail",
"style": {
"navigationBarTitleText": "货品详情"
}
},
{
"path": "pages/product/categories",
"style": {

View File

@@ -1,18 +1,21 @@
<template>
<view class="auth-page">
<view class="tabs">
<view :class="['tab', tab==='login'?'active':'']" @click="tab='login'">登录</view>
<view :class="['tab', tab==='register'?'active':'']" @click="tab='register'">注册</view>
<view :class="['tab', tab==='reset'?'active':'']" @click="tab='reset'">忘记密码</view>
<view class="login-hero">
<image class="login-hero-img" :src="authLoginTopImage" mode="widthFix" />
</view>
<view class="header"><text class="title">邮箱密码登录</text></view>
<view v-if="tab==='login'" class="panel">
<view v-if="tab==='login'" class="panel">
<input class="input" type="text" v-model.trim="loginForm.email" placeholder="输入邮箱" />
<input class="input" type="password" v-model="loginForm.password" placeholder="输入密码" />
<button class="btn primary" :disabled="loading" @click="onLogin">登录</button>
<view class="quick-inline">
<button class="quick-link" @click="gotoRegister">注册</button>
<button class="quick-link" @click="gotoReset">忘记密码</button>
</view>
</view>
<view v-else-if="tab==='register'" class="panel">
<view class="panel minor" v-if="tab==='register'">
<input class="input" type="text" v-model.trim="regForm.name" placeholder="输入用户名" />
<input class="input" type="text" v-model.trim="regForm.email" placeholder="输入邮箱" />
<view class="row">
@@ -24,7 +27,7 @@
<button class="btn primary" :disabled="loading" @click="onRegister">注册新用户</button>
</view>
<view v-else class="panel">
<view class="panel minor" v-if="tab==='reset'">
<input class="input" type="text" v-model.trim="resetForm.email" placeholder="输入邮箱" />
<view class="row">
<input class="input flex1" type="text" v-model.trim="resetForm.code" placeholder="邮箱验证码" />
@@ -35,16 +38,19 @@
<button class="btn primary" :disabled="loading" @click="onReset">重置密码</button>
</view>
</view>
</template>
<script>
import { get, post } from '../../common/http.js'
import { AUTH_LOGIN_TOP_IMAGE } from '../../common/config.js'
export default {
data(){
data(){
return {
loading: false,
tab: 'login',
tab: 'login',
authLoginTopImage: AUTH_LOGIN_TOP_IMAGE,
loginForm: { email: '', password: '' },
regForm: { name: '', email: '', code: '', password: '', password2: '' },
resetForm: { email: '', code: '', password: '', password2: '' },
@@ -55,6 +61,8 @@ export default {
},
beforeUnmount(){ this._timers.forEach(t=>clearInterval(t)) },
methods: {
gotoRegister(){ this.tab='register' },
gotoReset(){ this.tab='reset' },
toast(msg){ try{ uni.showToast({ title: String(msg||'操作失败'), icon: 'none' }) } catch(_){} },
validateEmail(v){ return /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(String(v||'').trim()) },
startCountdown(key){
@@ -136,20 +144,39 @@ export default {
}catch(e){ this.toast(e.message) }
finally{ this.loading=false }
}
}
}
}
</script>
<style lang="scss">
.auth-page{ padding: 32rpx; display:flex; flex-direction: column; gap: 24rpx; }
.tabs{ display:flex; gap: 24rpx; }
.tab{ padding: 12rpx 20rpx; border-radius: 999rpx; background:#f2f4f8; color:#5b6b80; font-weight:700; }
.tab.active{ background:#2d6be6; color:#fff; }
.panel{ display:flex; flex-direction: column; gap: 16rpx; background:#fff; padding: 24rpx; border-radius: 16rpx; border:2rpx solid #eef2f9; }
.input{ background:#f7f9ff; border:2rpx solid rgba(45,107,230,0.12); border-radius: 12rpx; padding: 22rpx 20rpx; font-size: 28rpx; }
@import '../../uni.scss';
.auth-page{ padding: 32rpx; display:flex; flex-direction: column; gap: 24rpx; position: relative; min-height: 100vh; }
.header{ display:flex; align-items:center; justify-content:center; padding: 8rpx 0 0; }
.title{ font-size: 34rpx; font-weight: 800; color: $uni-text-color; }
.login-hero{ display:flex; justify-content:center; padding: 16rpx 0 0; }
.login-hero-img{ width: 72%; max-width: 560rpx; border-radius: 8rpx; }
.panel{ display:flex; flex-direction: column; gap: 16rpx; background: transparent; padding: 0; border-radius: 0; border: none; }
.panel.minor{ margin-top: 12rpx; }
.input{ background:#ffffff; border:2rpx solid #e5e7eb; border-radius: 12rpx; padding: 22rpx 20rpx; font-size: 28rpx; }
.row{ display:flex; gap: 12rpx; align-items:center; }
.flex1{ flex:1; }
.btn{ padding: 22rpx 20rpx; border-radius: 12rpx; font-weight: 800; text-align:center; }
.btn.primary{ background: linear-gradient(135deg, #4788ff 0%, #2d6be6 100%); color:#fff; }
.btn.primary{ background: linear-gradient(135deg, #4788ff 0%, #2d6be6 100%); color:#fff; border: 1rpx solid rgba(45,107,230,0.25); width: 72%; margin: 0 auto; padding: 14rpx 16rpx; }
.btn.ghost{ background:#eef3ff; color:#2d6be6; }
/* 右下角快捷入口:贴着登录功能,无边框、无背景 */
.quick-inline{ display:flex; gap: 28rpx; justify-content:flex-end; align-items:center; margin-top: 10rpx; }
.quick-link{ background: transparent !important; color: #2d6be6; border: none !important; outline: none; padding: 0; font-size: 26rpx; font-weight: 700; box-shadow: none; line-height: 1.2; }
.quick-link::after{ border: none !important; }
/* 注册/重置页:验证码按钮与左侧输入框等高,且更紧凑 */
.panel.minor .row > .input{ height: $app-form-control-height; padding: 0 $app-form-control-padding-x; }
.panel.minor .row > .btn.ghost{
height: $app-form-control-height;
padding: 0 $app-form-control-padding-x;
border-radius: $app-form-control-border-radius;
display: inline-flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -12,28 +12,28 @@
<view class="kpi-item kpi-card">
<image :src="KPI_ICONS.todaySales" class="kpi-icon" mode="aspectFit"></image>
<view class="kpi-content">
<text class="kpi-label">今日销售额</text>
<text class="kpi-label">{{ KPI_LABELS.todaySales }}</text>
<text class="kpi-value">{{ kpi.todaySales }}</text>
</view>
</view>
<view class="kpi-item kpi-card">
<image :src="KPI_ICONS.monthSales" class="kpi-icon" mode="aspectFit"></image>
<view class="kpi-content">
<text class="kpi-label">本月销售额</text>
<text class="kpi-label">{{ KPI_LABELS.monthSales }}</text>
<text class="kpi-value">{{ kpi.monthSales }}</text>
</view>
</view>
<view class="kpi-item kpi-card">
<image :src="KPI_ICONS.monthProfit" class="kpi-icon" mode="aspectFit"></image>
<view class="kpi-content">
<text class="kpi-label">本月利润</text>
<text class="kpi-label">{{ KPI_LABELS.monthProfit }}</text>
<text class="kpi-value">{{ kpi.monthProfit }}</text>
</view>
</view>
<view class="kpi-item kpi-card">
<image :src="KPI_ICONS.stockCount" class="kpi-icon" mode="aspectFit"></image>
<view class="kpi-content">
<text class="kpi-label">库存商品数量</text>
<text class="kpi-label">{{ KPI_LABELS.stockCount }}</text>
<text class="kpi-value">{{ kpi.stockCount }}</text>
</view>
</view>
@@ -93,12 +93,13 @@
<script>
import { get, post, put } from '../../common/http.js'
import { ROUTES } from '../../common/constants.js'
import { ROUTES, KPI_LABELS } from '../../common/constants.js'
import { KPI_ICONS as KPI_ICON_MAP } from '../../common/config.js'
export default {
data() {
return {
KPI_ICONS: KPI_ICON_MAP,
KPI_LABELS,
kpi: { todaySales: '0.00', monthSales: '0.00', monthProfit: '0.00', stockCount: '0' },
activeTab: 'home',
notices: [],
@@ -238,6 +239,11 @@
// 报表非 tab 页,使用 navigateTo 进入
uni.navigateTo({ url: ROUTES.report })
return
}
if (item.key === 'vip') {
// 跳转“我的 - VIP会员”页面
uni.navigateTo({ url: '/pages/my/vip' })
return
}
if (item.key === 'otherPay') {
// 进入开单页并预选“其他支出”

View File

@@ -222,9 +222,16 @@ export default {
formatDisplay(value) {
if (!value) return '-'
const s = String(value)
// 简单规范化:只保留到分钟
const m = s.match(/^(\d{4}-\d{2}-\d{2})([ T](\d{2}:\d{2}))/)
if (m) return `${m[1]} ${m[3]}`
// 仅显示“YYYY-MM-DD”
const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
if (m) return m[1]
const d = new Date(s)
if (!isNaN(d.getTime())) {
const y = d.getFullYear()
const mo = String(d.getMonth() + 1).padStart(2, '0')
const da = String(d.getDate()).padStart(2, '0')
return `${y}-${mo}-${da}`
}
return s
},
startLogin() {

View File

@@ -46,6 +46,17 @@
</view>
</view>
<!-- 已是VIP展示申请普通管理员入口 -->
<view v-if="isVip" class="apply-card">
<view class="apply-text">
<text class="apply-title">申请成为普通管理员</text>
<text class="apply-desc">在普通管理端参与配件审核</text>
</view>
<view role="button" :class="['apply-btn', { disabled: applyDisabled }]" @click="onApplyNormalAdmin">
<text>{{ applyBtnText }}</text>
</view>
</view>
<view v-if="!isVip" class="purchase-card">
<view class="purchase-text">
<text class="purchase-title">立即升级 VIP</text>
@@ -67,21 +78,59 @@ export default {
isVip: false,
expire: '',
price: 0,
benefits: []
benefits: [],
normalAdmin: { isNormalAdmin: false, applicationStatus: 'none' }
}
},
onShow(){
this.loadVip()
this.loadNormalAdminStatus()
this.composeBenefits()
},
computed: {
expireDisplay(){
const s = String(this.expire || '')
return s || '11年11月11日'
const v = this.expire
if (v === null || v === undefined) return ''
if (typeof v === 'number') {
const d = new Date(v)
if (!isNaN(d.getTime())) {
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
return `${y}-${m}-${dd}`
}
return ''
}
const s = String(v)
const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
if (m) return m[1]
const idx = s.search(/[ T]/)
if (idx > 0) {
const head = s.slice(0, idx)
if (head) return head
}
const d2 = new Date(s)
if (!isNaN(d2.getTime())) {
const y = d2.getFullYear()
const m2 = String(d2.getMonth() + 1).padStart(2, '0')
const dd2 = String(d2.getDate()).padStart(2, '0')
return `${y}-${m2}-${dd2}`
}
return s
},
priceDisplay(){
const n = Number(this.price)
return Number.isFinite(n) && n > 0 ? n.toFixed(2) : '0.00'
},
applyDisabled(){
const s = String(this.normalAdmin?.applicationStatus || 'none')
return !!(this.normalAdmin?.isNormalAdmin || s === 'approved' || s === 'pending')
},
applyBtnText(){
if (this.normalAdmin?.isNormalAdmin || this.normalAdmin?.applicationStatus === 'approved') return '已通过'
if (this.normalAdmin?.applicationStatus === 'pending') return '审核中'
if (!this.isVip) return '仅限VIP'
return '提交申请'
}
},
methods: {
@@ -103,6 +152,17 @@ export default {
this.isVip = false
}
},
async loadNormalAdminStatus(){
try {
const data = await get('/api/normal-admin/application/status')
this.normalAdmin = {
isNormalAdmin: !!data?.isNormalAdmin,
applicationStatus: String(data?.applicationStatus || 'none')
}
} catch(e) {
this.normalAdmin = { isNormalAdmin: false, applicationStatus: 'none' }
}
},
async onPay(){
try {
await post('/api/vip/pay', {})
@@ -111,7 +171,20 @@ export default {
} catch(e) {
uni.showToast({ title: String(e.message || '开通失败'), icon: 'none' })
}
}
},
async onApplyNormalAdmin(){
if (this.applyDisabled) {
const msg = this.normalAdmin?.isNormalAdmin || this.normalAdmin?.applicationStatus === 'approved' ? '已通过,无需重复申请' : (this.normalAdmin?.applicationStatus === 'pending' ? '审核中,请耐心等待' : '不可申请')
return uni.showToast({ title: msg, icon: 'none' })
}
try {
await post('/api/normal-admin/apply', { remark: '从我的-会员发起申请' })
uni.showToast({ title: '申请已提交', icon: 'success' })
await this.loadNormalAdminStatus()
} catch(e) {
uni.showToast({ title: String(e.message || '申请失败'), icon: 'none' })
}
}
}
}
</script>
@@ -186,6 +259,9 @@ page {
border-color: #4c8dff;
}
/* 指定 hero 内激活态徽标文本为黑色 */
.vip-hero .status-pill.active text { color: #000 !important; }
.vip-summary {
display: grid;
grid-template-columns: repeat(2, minmax(0,1fr));
@@ -337,6 +413,45 @@ page {
opacity: 0.88;
}
.apply-card {
margin-top: 0;
background: linear-gradient(135deg, rgba(30,173,145,0.14) 0%, rgba(30,173,145,0.06) 100%);
border-radius: 28rpx;
padding: 30rpx 28rpx;
display: flex;
align-items: center;
gap: 24rpx;
border: 2rpx solid rgba(30,173,145,0.18);
box-shadow: 0 10rpx 24rpx rgba(30,173,145,0.15);
}
.apply-text { flex: 1; display:flex; flex-direction: column; gap: 10rpx; }
.apply-title { font-size: 32rpx; font-weight: 800; color: #1ead91; }
.apply-desc { font-size: 24rpx; color: #247a66; line-height: 34rpx; }
.apply-btn {
flex: 0 0 auto;
padding: 20rpx 36rpx;
border-radius: 999rpx;
border: none;
background-color: transparent;
background: linear-gradient(135deg, #1ead91 0%, #159b7e 100%);
color: #fff;
font-size: 28rpx;
font-weight: 700;
box-shadow: 0 10rpx 22rpx rgba(21,155,126,0.20);
}
.apply-btn::after { border: none; }
.apply-btn:active { opacity: .9; }
.apply-btn.disabled {
opacity: .5;
background: #c7e8df;
color: #fff;
box-shadow: none;
pointer-events: none;
}
@media (max-width: 375px) {
.vip-summary {
grid-template-columns: 1fr;

View File

@@ -31,41 +31,18 @@
<view class="row">
<input v-model.trim="form.spec" placeholder="规格" />
</view>
<!-- 隐藏产地输入 -->
<!-- 隐藏主单位选择 -->
<view class="row">
<input v-model.trim="form.origin" placeholder="产地" />
</view>
<view class="row">
<picker mode="selector" :range="unitNames" @change="onPickUnit">
<view class="picker">主单位{{ unitLabel }}</view>
</picker>
<picker mode="selector" :range="categoryNames" @change="onPickCategory">
<view class="picker">类别{{ categoryLabel }}</view>
</picker>
</view>
</view>
<view class="section">
<view class="row">
<text class="label">库存与安全库存</text>
</view>
<view class="row">
<input type="number" v-model.number="form.stock" placeholder="当前库存" />
<input type="number" v-model.number="form.safeMin" placeholder="安全库存下限" />
<input type="number" v-model.number="form.safeMax" placeholder="安全库存上限" />
</view>
</view>
<!-- 隐藏库存与安全库存输入 -->
<view class="section">
<view class="row">
<text class="label">价格进价/零售/批发/大单</text>
</view>
<view class="row prices">
<input type="number" v-model.number="form.purchasePrice" placeholder="进货价" />
<input type="number" v-model.number="form.retailPrice" placeholder="零售价" />
<input type="number" v-model.number="form.wholesalePrice" placeholder="批发价" />
<input type="number" v-model.number="form.bigClientPrice" placeholder="大单价" />
</view>
</view>
<!-- 隐藏价格相关输入 -->
<view class="section">
<text class="label">图片</text>
@@ -94,14 +71,11 @@ export default {
return {
id: '',
form: {
name: '', barcode: '', brand: '', model: '', spec: '', origin: '',
categoryId: '', unitId: '',
stock: null, safeMin: null, safeMax: null,
purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null,
name: '', barcode: '', brand: '', model: '', spec: '',
categoryId: '',
images: [], remark: '',
platformStatus: '', sourceSubmissionId: ''
},
units: [],
categories: [],
keyboardHeight: 0
}
@@ -115,12 +89,7 @@ export default {
this.disposeKeyboardListener()
},
computed: {
unitNames() { return this.units.map(u => u.name) },
categoryNames() { return this.categories.map(c => c.name) },
unitLabel() {
const u = this.units.find(x => String(x.id) === String(this.form.unitId))
return u ? u.name : '选择单位'
},
categoryLabel() {
const c = this.categories.find(x => String(x.id) === String(this.form.categoryId))
return c ? c.name : '选择类别'
@@ -128,7 +97,7 @@ export default {
},
methods: {
async bootstrap() {
await Promise.all([this.fetchUnits(), this.fetchCategories()])
await Promise.all([this.fetchCategories()])
if (this.id) this.loadDetail()
},
initKeyboardListener() {
@@ -147,22 +116,12 @@ export default {
}
} catch (_) {}
},
async fetchUnits() {
try {
const res = await get('/api/product-units')
this.units = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
} catch (_) {}
},
async fetchCategories() {
try {
const res = await get('/api/product-categories')
this.categories = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
} catch (_) {}
},
onPickUnit(e) {
const idx = Number(e.detail.value); const u = this.units[idx]
this.form.unitId = u ? u.id : ''
},
onPickCategory(e) {
const idx = Number(e.detail.value); const c = this.categories[idx]
this.form.categoryId = c ? c.id : ''
@@ -193,12 +152,8 @@ export default {
const data = await get('/api/products/' + this.id)
Object.assign(this.form, {
name: data.name,
barcode: data.barcode, brand: data.brand, model: data.model, spec: data.spec, origin: data.origin,
categoryId: data.categoryId, unitId: data.unitId,
stock: data.stock,
safeMin: data.safeMin, safeMax: data.safeMax,
purchasePrice: data.purchasePrice, retailPrice: data.retailPrice,
wholesalePrice: data.wholesalePrice, bigClientPrice: data.bigClientPrice,
barcode: data.barcode, brand: data.brand, model: data.model, spec: data.spec,
categoryId: data.categoryId,
images: (data.images || []).map(i => i.url || i),
remark: data.remark || '',
platformStatus: data.platformStatus || '',
@@ -208,21 +163,13 @@ export default {
},
validate() {
if (!this.form.name) { uni.showToast({ title: '请填写名称', icon: 'none' }); return false }
if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) {
uni.showToast({ title: '安全库存区间不合法', icon: 'none' }); return false
}
return true
},
buildPayload() {
const f = this.form
return {
name: f.name, barcode: f.barcode, brand: f.brand, model: f.model, spec: f.spec, origin: f.origin,
categoryId: f.categoryId || null, unitId: f.unitId,
safeMin: f.safeMin, safeMax: f.safeMax,
prices: {
purchasePrice: f.purchasePrice, retailPrice: f.retailPrice, wholesalePrice: f.wholesalePrice, bigClientPrice: f.bigClientPrice
},
stock: f.stock,
name: f.name, barcode: f.barcode, brand: f.brand, model: f.model, spec: f.spec,
categoryId: f.categoryId || null,
images: f.images,
remark: f.remark
}
@@ -236,7 +183,7 @@ export default {
else await post('/api/products', payload)
uni.showToast({ title: '保存成功', icon: 'success', mask: false })
if (goOn && !this.id) {
this.form = { name: '', barcode: '', brand: '', model: '', spec: '', origin: '', categoryId: '', unitId: '', stock: null, safeMin: null, safeMax: null, purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null, images: [], remark: '', platformStatus: '', sourceSubmissionId: '' }
this.form = { name: '', barcode: '', brand: '', model: '', spec: '', categoryId: '', images: [], remark: '', platformStatus: '', sourceSubmissionId: '' }
} else {
setTimeout(() => uni.navigateBack(), 400)
}

View File

@@ -2,32 +2,59 @@
<view class="page">
<view class="tabs">
<view class="tab" :class="{active: tab==='all'}" @click="switchTab('all')">全部</view>
<view class="tab" :class="{active: tab==='category'}" @click="switchTab('category')">按类别</view>
<view class="tab" :class="{active: tab==='search'}" @click="switchTab('search')">查询</view>
<view class="tab extra" @click="goMySubmissions">我的提交</view>
</view>
<view class="search">
<input v-model.trim="query.kw" placeholder="输入名称/条码/规格查询" @confirm="reload" />
<picker mode="selector" :range="categoryNames" v-if="tab==='category'" @change="onPickCategory">
<view class="picker">{{ categoryLabel }}</view>
</picker>
<view class="search" :class="{ 'template-mode': query.mode==='template' }" v-if="tab==='search'">
<view class="mode">
<picker mode="selector" :range="['直接查询','名称模糊查询','按模板参数查询']" @change="e => (query.mode = ['direct','nameLike','template'][Number(e.detail.value)] || 'direct')">
<view class="picker">{{ modeLabel }}</view>
</picker>
</view>
<block v-if="query.mode==='direct' || query.mode==='nameLike'">
<input v-model.trim="query.kw" placeholder="输入名称/条码/规格查询" @confirm="reload" />
</block>
<block v-if="query.mode==='template'">
<view class="picker-row">
<picker mode="selector" :range="categoryNames" @change="onPickCategory">
<view class="picker">{{ categoryLabel }}</view>
</picker>
<picker mode="selector" :range="templateNames" @change="onPickTemplate">
<view class="picker">{{ templateLabel }}</view>
</picker>
</view>
<view class="params-wrap">
<view class="param-row" v-for="(p,idx) in selectedTemplateParams" :key="p.fieldKey">
<input v-if="p.type==='string'" v-model.trim="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
<input v-else-if="p.type==='number'" type="number" v-model.number="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
<switch v-else-if="p.type==='boolean'" :checked="!!paramValues[p.fieldKey]" @change="onParamBoolChange(p, $event)" />
<picker v-else-if="p.type==='enum'" mode="selector" :range="p.enumOptions||[]" @change="onPickParamEnumWrapper(p, $event)">
<view class="picker">{{ displayParamEnum(p) }}</view>
</picker>
<picker v-else-if="p.type==='date'" mode="date" @change="onParamDateChange(p, $event)">
<view class="picker">{{ paramValues[p.fieldKey] || ('选择' + p.fieldLabel) }}</view>
</picker>
<input v-else v-model.trim="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
</view>
</view>
</block>
<button size="mini" @click="reload">查询</button>
</view>
<scroll-view scroll-y class="list" @scrolltolower="loadMore">
<block v-if="items.length">
<view class="item" v-for="it in items" :key="it.id" @click="openForm(it.id)">
<view class="item" v-for="it in items" :key="it.id" @click="openDetail(it.id)">
<image v-if="it.cover" :src="it.cover" class="thumb" mode="aspectFill" />
<view class="content">
<view class="name">
<text>{{ it.name }}</text>
<view class="name">
<text>{{ it.name }}</text>
<text v-if="it.deleted" class="tag-deleted">已删除</text>
<text v-if="it.platformStatus==='platform'" class="tag-platform">平台推荐</text>
<text v-else-if="it.sourceSubmissionId" class="tag-custom">我的提交</text>
</view>
<view class="meta">{{ it.brand || '-' }} {{ it.model || '' }} {{ it.spec || '' }}</view>
<view class="meta">库存{{ it.stock ?? 0 }}
<text class="price">零售价¥{{ (it.retailPrice ?? it.price ?? 0).toFixed(2) }}</text>
</view>
<!-- 隐藏库存与价格展示按需求仅展示基础信息 -->
</view>
</view>
</block>
@@ -47,11 +74,13 @@ export default {
data() {
return {
items: [],
query: { kw: '', page: 1, size: 20, categoryId: '' },
query: { kw: '', page: 1, size: 20, categoryId: '', mode: 'direct', templateId: '', params: {} },
finished: false,
loading: false,
tab: 'all',
categories: []
categories: [],
templates: [],
paramValues: {}
}
},
onLoad() {
@@ -76,26 +105,59 @@ export default {
categoryLabel() {
const c = this.categories.find(x => String(x.id) === String(this.query.categoryId))
return c ? '类别:' + c.name : '选择类别'
}
},
modeLabel() {
const map = { direct: '直接查询', nameLike: '名称模糊查询', template: '按模板参数查询' }
return map[this.query.mode] || '直接查询'
},
templateNames() { return this.templates.map(t => t.name) },
templateLabel() {
const t = this.templates.find(x => String(x.id) === String(this.query.templateId))
return t ? '模板:' + t.name : '选择模板'
},
selectedTemplate() { return this.templates.find(t => String(t.id) === String(this.query.templateId)) || null },
selectedTemplateParams() { return (this.selectedTemplate && Array.isArray(this.selectedTemplate.params)) ? this.selectedTemplate.params : [] }
},
methods: {
switchTab(t) {
this.tab = t
this.query.categoryId = ''
this.query.templateId = ''
this.paramValues = {}
this.reload()
},
onPickCategory(e) {
const idx = Number(e.detail.value)
const c = this.categories[idx]
this.query.categoryId = c ? c.id : ''
this.reload()
this.fetchTemplates()
},
onPickTemplate(e) {
const idx = Number(e.detail.value)
const t = this.templates[idx]
this.query.templateId = t ? t.id : ''
this.paramValues = {}
},
onPickParamEnumWrapper(p, e) {
const idx = Number(e.detail.value)
const arr = p.enumOptions || []
this.paramValues[p.fieldKey] = arr[idx]
},
onParamBoolChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value ? true : false },
onParamDateChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value || '' },
async fetchCategories() {
try {
const res = await get('/api/product-categories', {})
this.categories = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
} catch (_) {}
},
async fetchTemplates() {
try {
const res = await get('/api/product-templates', this.query.categoryId ? { categoryId: this.query.categoryId } : {})
const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
this.templates = list
} catch (_) { this.templates = [] }
},
reload() {
this.items = []
this.query.page = 1
@@ -107,7 +169,16 @@ export default {
this.loading = true
try {
const params = { kw: this.query.kw, page: this.query.page, size: this.query.size }
if (this.tab === 'category' && this.query.categoryId) params.categoryId = this.query.categoryId
if (this.tab === 'search') {
if (this.query.categoryId) params.categoryId = this.query.categoryId
if (this.query.templateId) params.templateId = this.query.templateId
if (this.paramValues && Object.keys(this.paramValues).length) {
for (const k of Object.keys(this.paramValues)) {
const v = this.paramValues[k]
if (v !== undefined && v !== null && v !== '') params['param_' + k] = v
}
}
}
const res = await get('/api/products', params)
const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
this.items = this.items.concat(list)
@@ -119,13 +190,26 @@ export default {
this.loading = false
}
},
openForm(id) {
const url = '/pages/product/form' + (id ? ('?id=' + id) : '')
uni.navigateTo({ url })
},
goMySubmissions() {
openDetail(id) {
uni.navigateTo({ url: '/pages/product/product-detail?id=' + id })
},
goMySubmissions() {
uni.navigateTo({ url: '/pages/product/submissions' })
}
},
async remove(it) {
try {
const r = await new Promise(resolve => {
uni.showModal({ content: '确认删除该货品?删除后可在后台恢复', success: resolve })
})
if (!r || !r.confirm) return
const { del } = require('../../common/http.js')
await del('/api/products/' + it.id)
uni.showToast({ title: '已删除', icon: 'success' })
this.reload()
} catch (e) {
uni.showToast({ title: '删除失败', icon: 'none' })
}
}
}
}
</script>
@@ -139,6 +223,9 @@ export default {
.search { display:flex; gap: 12rpx; padding: 16rpx; background:$uni-bg-color-grey; align-items: center; }
.search input { flex:1; background:$uni-bg-color-hover; border-radius: 12rpx; padding: 12rpx; color: $uni-text-color; }
.picker { padding: 8rpx 12rpx; background:$uni-bg-color-hover; border-radius: 10rpx; color:$uni-text-color-grey; }
.template-mode { flex-direction: column; align-items: stretch; gap: 8rpx; }
.picker-row { display:flex; gap: 12rpx; }
.params-wrap { margin-top: 6rpx; background:$uni-bg-color-grey; border-radius: 12rpx; padding: 8rpx 8rpx; }
.list { flex:1; }
.item { display:flex; padding: 20rpx; background:$uni-bg-color-grey; border-bottom: 1rpx solid $uni-border-color; }
.thumb { width: 120rpx; height: 120rpx; border-radius: 12rpx; margin-right: 16rpx; background:$uni-bg-color-hover; }
@@ -146,6 +233,7 @@ export default {
.name { color:$uni-text-color; margin-bottom: 6rpx; font-weight: 600; display:flex; align-items:center; gap: 12rpx; }
.tag-platform { font-size: 22rpx; color:#fff; background:#2d8cf0; padding: 4rpx 10rpx; border-radius: 8rpx; }
.tag-custom { font-size: 22rpx; color:#fff; background:#67c23a; padding: 4rpx 10rpx; border-radius: 8rpx; }
.tag-deleted { font-size: 22rpx; color:#fff; background:#909399; padding: 4rpx 10rpx; border-radius: 8rpx; }
.meta { color:$uni-text-color-grey; font-size: 24rpx; }
.price { margin-left: 20rpx; color:$uni-color-primary; }
.empty { height: 60vh; display:flex; align-items:center; justify-content:center; color:$uni-text-color-grey; }

View File

@@ -0,0 +1,142 @@
<template>
<scroll-view scroll-y class="page" v-if="detail">
<view class="header">
<text class="model">{{ detail.model }}</text>
<text v-if="detail.deleted" class="status deleted">已删除</text>
</view>
<view class="section">
<view class="row"><text class="label">名称</text><text class="value">{{ detail.name || '-' }}</text></view>
<view class="row"><text class="label">品牌</text><text class="value">{{ detail.brand || '-' }}</text></view>
<view class="row"><text class="label">型号</text><text class="value">{{ detail.model || '-' }}</text></view>
<view class="row"><text class="label">条码</text><text class="value">{{ detail.barcode || '-' }}</text></view>
<view class="row"><text class="label">类别</text><text class="value">{{ categoryName }}</text></view>
<view class="row"><text class="label">模板</text><text class="value">{{ templateName }}</text></view>
<view class="row" v-if="detail.externalCode"><text class="label">编号</text><text class="value">{{ detail.externalCode }}</text></view>
</view>
<view class="section">
<view class="block-title">参数</view>
<view v-if="labeledPairs.length" class="params">
<view class="param" v-for="item in labeledPairs" :key="item.key">
<text class="param-key">{{ item.label }}<text v-if="item.unit">{{ item.unit }}</text></text>
<text class="param-val">{{ item.value }}</text>
</view>
</view>
<view v-else class="placeholder">未填写参数</view>
</view>
<view class="section">
<view class="block-title">图片</view>
<view v-if="detail.images && detail.images.length" class="images">
<image v-for="(img, idx) in detail.images" :key="idx" :src="img.url || img" class="image" mode="aspectFill" @click="preview(idx)" />
</view>
<view v-else class="placeholder">未上传图片</view>
</view>
<view class="section">
<view class="block-title">备注</view>
<view class="placeholder">{{ detail.remark || '无' }}</view>
</view>
<view class="footer">
<button size="mini" @click="back">返回</button>
<button size="mini" type="warn" @click="remove">删除</button>
</view>
</scroll-view>
<view v-else class="loading">加载中...</view>
</template>
<script>
import { get, del } from '../../common/http.js'
export default {
data() {
return { id: '', detail: null, categoryName: '-', templateName: '-' }
},
async onLoad(query) {
this.id = query?.id || ''
if (!this.id) { uni.showToast({ title: '参数缺失', icon: 'none' }); return }
await this.preloadDictionaries()
await this.loadDetail()
},
methods: {
async preloadDictionaries() {
try {
const needCats = !Array.isArray(uni.getStorageSync('CACHE_CATEGORIES'))
const needTpls = !Array.isArray(uni.getStorageSync('CACHE_TEMPLATES'))
if (!needCats && !needTpls) return
const reqs = []
if (needCats) reqs.push(get('/api/product-categories'))
if (needTpls) reqs.push(get('/api/product-templates'))
const res = await Promise.all(reqs)
let idx = 0
if (needCats) { const r = res[idx++]; const list = Array.isArray(r?.list)?r.list:(Array.isArray(r)?r:[]); uni.setStorageSync('CACHE_CATEGORIES', list) }
if (needTpls) { const r = res[idx++]; const list = Array.isArray(r?.list)?r.list:(Array.isArray(r)?r:[]); uni.setStorageSync('CACHE_TEMPLATES', list) }
} catch (_) {}
},
async loadDetail() {
try {
const data = await get('/api/products/' + this.id)
this.detail = data
this.categoryName = this.categoryLookup(data.categoryId)
this.templateName = this.templateLookup(data.templateId)
} catch (e) { uni.showToast({ title: e?.message || '加载失败', icon: 'none' }) }
},
preview(idx) {
try { const list = (this.detail?.images||[]).map(i => i.url || i); uni.previewImage({ urls: list, current: idx }) } catch (_) {}
},
categoryLookup(id) {
try { const list = uni.getStorageSync('CACHE_CATEGORIES') || []; const f = list.find(x => String(x.id)===String(id)); return f?f.name:'-'} catch(_){return'-'}
},
templateLookup(id) {
try { const list = uni.getStorageSync('CACHE_TEMPLATES') || []; const f = list.find(x => String(x.id)===String(id)); return f?f.name:'-'} catch(_){return'-'}
},
async remove() {
try {
const r = await new Promise(resolve => { uni.showModal({ content: '确认删除该货品?删除后可在后台恢复', success: resolve }) })
if (!r || !r.confirm) return
await del('/api/products/' + this.id)
uni.showToast({ title: '已删除', icon: 'success' })
setTimeout(() => uni.navigateBack(), 400)
} catch (e) { uni.showToast({ title: '删除失败', icon: 'none' }) }
},
back(){ uni.navigateBack({ delta: 1 }) }
},
computed: {
labeledPairs() {
const params = this.detail?.parameters
if (!params || typeof params !== 'object') return []
let labelMap = {}, unitMap = {}
try {
const templates = uni.getStorageSync('CACHE_TEMPLATES') || []
const tpl = templates.find(t => String(t.id) === String(this.detail?.templateId))
if (tpl && Array.isArray(tpl.params)) for (const p of tpl.params) { labelMap[p.fieldKey] = p.fieldLabel; unitMap[p.fieldKey] = p.unit }
} catch (_) {}
return Object.keys(params).map(k => ({ key: k, label: labelMap[k] || k, unit: unitMap[k] || '', value: params[k] }))
}
}
}
</script>
<style lang="scss">
.page { padding: 24rpx 24rpx 160rpx; background: #f6f7fb; }
.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; }
.model { font-size: 36rpx; font-weight: 700; color: #2d3a4a; }
.status.deleted { font-size: 24rpx; padding: 6rpx 18rpx; border-radius: 999rpx; background: #c0c4cc; color: #fff; }
.section { background: #fff; border-radius: 16rpx; padding: 20rpx 22rpx; margin-bottom: 24rpx; box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.04); }
.row { display: flex; justify-content: space-between; padding: 12rpx 0; border-bottom: 1rpx solid #f1f2f5; }
.row:last-child { border-bottom: none; }
.label { width: 160rpx; font-size: 26rpx; color: #7a8899; }
.value { flex: 1; text-align: right; font-size: 26rpx; color: #2d3a4a; word-break: break-all; }
.block-title { font-size: 28rpx; font-weight: 600; color: #2d3a4a; margin-bottom: 12rpx; }
.placeholder { font-size: 26rpx; color: #7a8899; }
.params { display: flex; flex-direction: column; gap: 12rpx; }
.param { display: flex; justify-content: space-between; font-size: 26rpx; color: #2d3a4a; }
.param-key { color: #7a8899; }
.images { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12rpx; }
.image { width: 100%; height: 200rpx; border-radius: 16rpx; background: #f0f2f5; }
.footer { display: flex; justify-content: flex-end; gap: 20rpx; }
.loading { height: 100vh; display: flex; align-items: center; justify-content: center; color: #7a8899; }
</style>

View File

@@ -9,18 +9,17 @@
<view class="row"><text class="label">名称</text><text class="value">{{ detail.name || '-' }}</text></view>
<view class="row"><text class="label">品牌</text><text class="value">{{ detail.brand || '-' }}</text></view>
<view class="row"><text class="label">规格</text><text class="value">{{ detail.spec || '-' }}</text></view>
<view class="row"><text class="label">产地</text><text class="value">{{ detail.origin || '-' }}</text></view>
<view class="row"><text class="label">条码</text><text class="value">{{ detail.barcode || '-' }}</text></view>
<view class="row"><text class="label">单位</text><text class="value">{{ unitName }}</text></view>
<view class="row"><text class="label">类别</text><text class="value">{{ categoryName }}</text></view>
<view class="row"><text class="label">安全库存</text><text class="value">{{ stockRange }}</text></view>
<view class="row"><text class="label">模板</text><text class="value">{{ templateName }}</text></view>
<!-- 隐藏产地/单位/安全库存显示 -->
</view>
<view class="section">
<view class="block-title">参数</view>
<view v-if="parameterPairs.length" class="params">
<view class="param" v-for="item in parameterPairs" :key="item.key">
<text class="param-key">{{ item.key }}</text>
<view v-if="labeledPairs.length" class="params">
<view class="param" v-for="item in labeledPairs" :key="item.key">
<text class="param-key">{{ item.label }}</text>
<text class="param-val">{{ item.value }}</text>
</view>
</view>
@@ -63,7 +62,8 @@ export default {
id: '',
detail: null,
unitName: '-',
categoryName: '-'
categoryName: '-',
templateName: '-'
}
},
async onLoad(query) {
@@ -79,8 +79,9 @@ export default {
try {
const data = await get(`/api/products/submissions/${this.id}`)
this.detail = data
this.unitName = this.unitLookup(data.unitId)
// 单位已移除
this.categoryName = this.categoryLookup(data.categoryId)
this.templateName = this.templateLookup(data.templateId)
} catch (e) {
const msg = e?.message || '加载失败'
uni.showToast({ title: msg, icon: 'none' })
@@ -96,11 +97,7 @@ export default {
if (s === 'rejected') return 'rejected'
return 'pending'
},
parameterPairs() {
const params = this.detail?.parameters
if (!params || typeof params !== 'object') return []
return Object.keys(params).map(k => ({ key: k, value: params[k] }))
},
preview(idx) {
if (!this.detail?.images || !this.detail.images.length) return
uni.previewImage({ urls: this.detail.images, current: idx })
@@ -120,7 +117,7 @@ export default {
},
unitLookup(id) {
try {
const list = uni.getStorageSync('CACHE_UNITS') || []
const list = []
const found = list.find(x => String(x.id) === String(id))
return found ? found.name : '-'
} catch (_) { return '-' }
@@ -132,6 +129,13 @@ export default {
return found ? found.name : '-'
} catch (_) { return '-' }
},
templateLookup(id) {
try {
const list = uni.getStorageSync('CACHE_TEMPLATES') || []
const found = list.find(x => String(x.id) === String(id))
return found ? found.name : '-'
} catch (_) { return '-' }
},
back() {
uni.navigateBack({ delta: 1 })
},
@@ -160,6 +164,20 @@ export default {
if (min != null && max != null) return `${min} ~ ${max}`
if (min != null) return `${min}`
return `${max}`
},
labeledPairs() {
const params = this.detail?.parameters
if (!params || typeof params !== 'object') return []
// 从缓存模板中读取 label
let labelMap = {}
try {
const templates = uni.getStorageSync('CACHE_TEMPLATES') || []
const tpl = templates.find(t => String(t.id) === String(this.detail?.templateId))
if (tpl && Array.isArray(tpl.params)) {
for (const p of tpl.params) labelMap[p.fieldKey] = p.fieldLabel
}
} catch (_) {}
return Object.keys(params).map(k => ({ key: k, label: labelMap[k] || k, value: params[k] }))
}
}
}

View File

@@ -68,9 +68,10 @@ export default {
methods: {
async preloadDictionaries() {
try {
const [units, categories] = await Promise.all([
const [units, categories, templates] = await Promise.all([
this.cacheUnitsLoaded ? Promise.resolve(null) : get('/api/product-units'),
this.cacheCategoriesLoaded ? Promise.resolve(null) : get('/api/product-categories')
this.cacheCategoriesLoaded ? Promise.resolve(null) : get('/api/product-categories'),
get('/api/product-templates')
])
if (units) {
const list = Array.isArray(units?.list) ? units.list : (Array.isArray(units) ? units : [])
@@ -82,6 +83,10 @@ export default {
uni.setStorageSync('CACHE_CATEGORIES', list)
this.cacheCategoriesLoaded = true
}
if (templates) {
const list = Array.isArray(templates?.list) ? templates.list : (Array.isArray(templates) ? templates : [])
uni.setStorageSync('CACHE_TEMPLATES', list)
}
} catch (_) {
// 忽略缓存失败
}

View File

@@ -32,6 +32,13 @@
</view>
</view>
<view class="section">
<view class="row">
<text class="label">编号</text>
<input v-model.trim="form.externalCode" placeholder="内部/外部编号(可选)" />
</view>
</view>
<view class="section">
<view class="row">
<text class="label">模板</text>
@@ -43,6 +50,42 @@
</view>
</view>
<!-- 动态参数根据模板渲染必填/可选项 -->
<view class="section" v-if="selectedTemplate">
<view class="row">
<text class="label">参数</text>
</view>
<view class="param-list">
<view class="row" v-for="(p,idx) in (selectedTemplate.params||[])" :key="p.fieldKey">
<text class="label">
{{ p.fieldLabel }}<text v-if="p.unit">{{ p.unit }}</text><text v-if="p.required" style="color:#ff5b5b">*</text>
</text>
<block v-if="p.type==='string'">
<input v-model.trim="paramValues[p.fieldKey]" :placeholder="'请输入' + p.fieldLabel" />
</block>
<block v-else-if="p.type==='number'">
<input type="number" v-model.number="paramValues[p.fieldKey]" :placeholder="'请输入' + p.fieldLabel" />
</block>
<block v-else-if="p.type==='boolean'">
<switch :checked="!!paramValues[p.fieldKey]" @change="e => (paramValues[p.fieldKey]=e.detail.value)" />
</block>
<block v-else-if="p.type==='enum'">
<picker mode="selector" :range="p.enumOptions||[]" @change="onPickEnum(p, $event)">
<view class="picker">{{ displayEnum(p) }}</view>
</picker>
</block>
<block v-else-if="p.type==='date'">
<picker mode="date" @change="onPickDate(p, $event)">
<view class="picker">{{ paramValues[p.fieldKey] || ('选择' + p.fieldLabel) }}</view>
</picker>
</block>
<block v-else>
<input v-model.trim="paramValues[p.fieldKey]" :placeholder="'请输入' + p.fieldLabel" />
</block>
</view>
</view>
</view>
<view class="section">
<view class="row">
<text class="label">图片</text>
@@ -91,6 +134,7 @@ export default {
categoryId: '',
templateId: '',
externalCode: '',
parameters: {},
images: [],
remark: '',
@@ -172,11 +216,18 @@ export default {
this.form.templateId = t ? t.id : ''
this.paramValues = {}
},
onPickDate(p, e) {
this.paramValues[p.fieldKey] = e?.detail?.value || ''
},
onPickEnum(p, e) {
const idx = Number(e.detail.value)
const arr = p.enumOptions || []
this.paramValues[p.fieldKey] = arr[idx]
},
displayEnum(p) {
const v = this.paramValues[p.fieldKey]
return (v === undefined || v === null || v === '') ? ('选择' + p.fieldLabel) : String(v)
},
async scanBarcode() {
try {
const chooseRes = await uni.chooseImage({ count: 1, sourceType: ['camera','album'], sizeType: ['compressed'] })
@@ -253,6 +304,7 @@ export default {
model: this.form.model,
brand: this.form.brand,
barcode: this.form.barcode,
externalCode: this.form.externalCode || null,
categoryId: this.form.categoryId || null,
templateId: this.form.templateId || null,
parameters: paramsForSubmit,

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -74,3 +74,9 @@ $uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
$app-form-control-height: 76rpx; // 控件总高度(含边框)
$app-form-control-padding-x: 20rpx; // 水平方向内边距
$app-form-control-border-width: 2rpx; // 边框宽度
$app-form-control-border-radius: 12rpx; // 圆角半径

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"constants.js","sources":["common/constants.js"],"sourcesContent":["// 统一常量配置:其他收入/支出分类,禁止在业务中硬编码\r\nexport const INCOME_CATEGORIES = [\r\n\t{ key: 'sale_income', label: '销售收入' },\r\n\t{ key: 'operation_income', label: '经营所得' },\r\n\t{ key: 'interest_income', label: '利息收入' },\r\n\t{ key: 'investment_income', label: '投资收入' },\r\n\t{ key: 'other_income', label: '其它收入' }\r\n]\r\n\r\nexport const EXPENSE_CATEGORIES = [\r\n\t{ key: 'operation_expense', label: '经营支出' },\r\n\t{ key: 'office_supplies', label: '办公用品' },\r\n\t{ key: 'rent', label: '房租' },\r\n\t{ key: 'interest_expense', label: '利息支出' },\r\n\t{ key: 'other_expense', label: '其它支出' }\r\n]\r\n\r\n// 路由常量(集中管理页面路径,避免在业务中硬编码)\r\nexport const ROUTES = {\r\n\thome: '/pages/index/index',\r\n\tproductList: '/pages/product/list',\r\n\tproductForm: '/pages/product/form',\r\n\tproductSelect: '/pages/product/select',\r\n\tproductSettings: '/pages/product/settings',\r\n\torderCreate: '/pages/order/create',\r\n\tdetail: '/pages/detail/index',\r\n\tmy: '/pages/my/index',\r\n\tmyAbout: '/pages/my/about',\r\n\tmyVip: '/pages/my/vip',\r\n\treport: '/pages/report/index',\r\n\tcustomerSelect: '/pages/customer/select',\r\n\tsupplierSelect: '/pages/supplier/select',\r\n\taccountSelect: '/pages/account/select'\r\n}\r\n\r\n\r\n// 本地存储键:统一管理,避免在业务中散落硬编码\r\nexport const STORAGE_KEYS = {\r\n\tVIP_IS_VIP: 'USER_VIP_IS_VIP',\r\n\tVIP_START: 'USER_VIP_START',\r\n\tVIP_END: 'USER_VIP_END'\r\n}\r\n\r\n\r\n"],"names":[],"mappings":";AACY,MAAC,oBAAoB;AAAA,EAChC,EAAE,KAAK,eAAe,OAAO,OAAQ;AAAA,EACrC,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,gBAAgB,OAAO,OAAQ;AACvC;AAEY,MAAC,qBAAqB;AAAA,EACjC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,QAAQ,OAAO,KAAM;AAAA,EAC5B,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,iBAAiB,OAAO,OAAQ;AACxC;AAGY,MAAC,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAChB;;;;"}
{"version":3,"file":"constants.js","sources":["common/constants.js"],"sourcesContent":["// 统一常量配置:其他收入/支出分类,禁止在业务中硬编码\nexport const INCOME_CATEGORIES = [\n\t{ key: 'sale_income', label: '销售收入' },\n\t{ key: 'operation_income', label: '经营所得' },\n\t{ key: 'interest_income', label: '利息收入' },\n\t{ key: 'investment_income', label: '投资收入' },\n\t{ key: 'other_income', label: '其它收入' }\n]\n\nexport const EXPENSE_CATEGORIES = [\n\t{ key: 'operation_expense', label: '经营支出' },\n\t{ key: 'office_supplies', label: '办公用品' },\n\t{ key: 'rent', label: '房租' },\n\t{ key: 'interest_expense', label: '利息支出' },\n\t{ key: 'other_expense', label: '其它支出' }\n]\n\n// 路由常量(集中管理页面路径,避免在业务中硬编码)\nexport const ROUTES = {\n\thome: '/pages/index/index',\n\tproductList: '/pages/product/list',\n\tproductForm: '/pages/product/form',\n\tproductSelect: '/pages/product/select',\n\tproductSettings: '/pages/product/settings',\n\torderCreate: '/pages/order/create',\n\tdetail: '/pages/detail/index',\n\tmy: '/pages/my/index',\n\tmyAbout: '/pages/my/about',\n\tmyVip: '/pages/my/vip',\n\treport: '/pages/report/index',\n\tcustomerSelect: '/pages/customer/select',\n\tsupplierSelect: '/pages/supplier/select',\n\taccountSelect: '/pages/account/select'\n}\n\n\n// 本地存储键:统一管理,避免在业务中散落硬编码\nexport const STORAGE_KEYS = {\n\tVIP_IS_VIP: 'USER_VIP_IS_VIP',\n\tVIP_START: 'USER_VIP_START',\n\tVIP_END: 'USER_VIP_END'\n}\n\n\n// KPI 标签常量,避免页面硬编码\nexport const KPI_LABELS = {\n todaySales: '今日销售额',\n monthSales: '本月销售额',\n monthProfit: '本月利润',\n stockCount: '库存量'\n}\n\n"],"names":[],"mappings":";AACY,MAAC,oBAAoB;AAAA,EAChC,EAAE,KAAK,eAAe,OAAO,OAAQ;AAAA,EACrC,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,gBAAgB,OAAO,OAAQ;AACvC;AAEY,MAAC,qBAAqB;AAAA,EACjC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,QAAQ,OAAO,KAAM;AAAA,EAC5B,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,iBAAiB,OAAO,OAAQ;AACxC;AAGY,MAAC,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAChB;AAYY,MAAC,aAAa;AAAA,EACtB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAChB;;;;;"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
;(function(){
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"五金配件管家","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"林林林","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.76","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"tabBar":{"position":"bottom","color":"#8a7535","selectedColor":"#B4880F","borderStyle":"black","blurEffect":"none","fontSize":"10px","iconWidth":"24px","spacing":"3px","height":"50px","list":[{"pagePath":"pages/index/index","text":"首页","iconPath":"/static/logo.png","selectedIconPath":"/static/logo.png"},{"pagePath":"pages/product/list","text":"货品","iconPath":"/static/logo.png","selectedIconPath":"/static/logo.png"},{"pagePath":"pages/order/create","text":"开单","iconPath":"/static/logo.png","selectedIconPath":"/static/logo.png"},{"pagePath":"pages/detail/index","text":"明细","iconPath":"/static/logo.png","selectedIconPath":"/static/logo.png"},{"pagePath":"pages/my/index","text":"我的","iconPath":"/static/logo.png","selectedIconPath":"/static/logo.png"}],"backgroundColor":"#ffffff","selectedIndex":0,"shown":true},"locales":{},"darkmode":false,"themeConfig":{}};
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"isTabBar":true,"tabBarIndex":0,"navigationBar":{"titleText":"五金配件管家","type":"default"},"isNVue":false}},{"path":"pages/order/create","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":2,"navigationBar":{"titleText":"开单","type":"default"},"isNVue":false}},{"path":"pages/product/select","meta":{"navigationBar":{"titleText":"选择商品","type":"default"},"isNVue":false}},{"path":"pages/product/list","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":1,"navigationBar":{"titleText":"货品列表","type":"default"},"isNVue":false}},{"path":"pages/product/form","meta":{"navigationBar":{"titleText":"编辑货品","type":"default"},"isNVue":false}},{"path":"pages/product/categories","meta":{"navigationBar":{"titleText":"类别管理","type":"default"},"isNVue":false}},{"path":"pages/product/units","meta":{"navigationBar":{"titleText":"单位管理","type":"default"},"isNVue":false}},{"path":"pages/product/settings","meta":{"navigationBar":{"titleText":"货品设置","type":"default"},"isNVue":false}},{"path":"pages/customer/select","meta":{"navigationBar":{"titleText":"选择客户","type":"default"},"isNVue":false}},{"path":"pages/customer/form","meta":{"navigationBar":{"titleText":"新增客户","type":"default"},"isNVue":false}},{"path":"pages/customer/detail","meta":{"navigationBar":{"titleText":"客户详情","type":"default"},"isNVue":false}},{"path":"pages/supplier/select","meta":{"navigationBar":{"titleText":"选择供应商","type":"default"},"isNVue":false}},{"path":"pages/supplier/form","meta":{"navigationBar":{"titleText":"新增/编辑供应商","type":"default"},"isNVue":false}},{"path":"pages/account/select","meta":{"navigationBar":{"titleText":"选择账户","type":"default"},"isNVue":false}},{"path":"pages/account/ledger","meta":{"navigationBar":{"titleText":"账户流水","type":"default"},"isNVue":false}},{"path":"pages/account/form","meta":{"navigationBar":{"titleText":"新增/编辑账户","type":"default"},"isNVue":false}},{"path":"pages/detail/index","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":3,"navigationBar":{"titleText":"明细","type":"default"},"isNVue":false}},{"path":"pages/my/index","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":4,"navigationBar":{"titleText":"我的","type":"default"},"isNVue":false}},{"path":"pages/my/about","meta":{"navigationBar":{"titleText":"关于与协议","type":"default"},"isNVue":false}},{"path":"pages/report/index","meta":{"navigationBar":{"titleText":"报表","type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#FFFFFF","backgroundTextStyle":"dark","navigationBar":{"backgroundColor":"#FFFFFF","titleText":"五金配件管家","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"林林林","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.76","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"tabBar":{"position":"bottom","color":"#444444","selectedColor":"#4C8DFF","borderStyle":"black","blurEffect":"none","fontSize":"10px","iconWidth":"24px","spacing":"3px","height":"50px","list":[{"pagePath":"pages/index/index","text":"首页","iconPath":"/static/icons/home.png","selectedIconPath":"/static/icons/home.png"},{"pagePath":"pages/product/list","text":"货品","iconPath":"/static/icons/product.png","selectedIconPath":"/static/icons/product.png"},{"pagePath":"pages/order/create","text":"开单","iconPath":"/static/icons/icons8-purchase-order-100.png","selectedIconPath":"/static/icons/icons8-purchase-order-100.png"},{"pagePath":"pages/detail/index","text":"明细","iconPath":"/static/icons/icons8-more-details-100.png","selectedIconPath":"/static/icons/icons8-more-details-100.png"},{"pagePath":"pages/my/index","text":"我的","iconPath":"/static/icons/icons8-account-male-100.png","selectedIconPath":"/static/icons/icons8-account-male-100.png"}],"backgroundColor":"#FFFFFF","selectedIndex":0,"shown":true},"locales":{},"darkmode":false,"themeConfig":{}};
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"isTabBar":true,"tabBarIndex":0,"navigationBar":{"titleText":"五金配件管家","type":"default"},"isNVue":false}},{"path":"pages/order/create","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":2,"navigationBar":{"titleText":"开单","type":"default"},"isNVue":false}},{"path":"pages/product/select","meta":{"navigationBar":{"titleText":"选择商品","type":"default"},"isNVue":false}},{"path":"pages/product/list","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":1,"navigationBar":{"titleText":"货品列表","type":"default"},"isNVue":false}},{"path":"pages/product/submit","meta":{"navigationBar":{"backgroundColor":"#ffffff","titleText":"提交配件","type":"default"},"isNVue":false}},{"path":"pages/product/submissions","meta":{"navigationBar":{"titleText":"我的提交","type":"default"},"isNVue":false}},{"path":"pages/product/submission-detail","meta":{"navigationBar":{"titleText":"提交详情","type":"default"},"isNVue":false}},{"path":"pages/product/form","meta":{"navigationBar":{"titleText":"编辑货品","type":"default"},"isNVue":false}},{"path":"pages/product/product-detail","meta":{"navigationBar":{"titleText":"货品详情","type":"default"},"isNVue":false}},{"path":"pages/product/categories","meta":{"navigationBar":{"titleText":"类别管理","type":"default"},"isNVue":false}},{"path":"pages/product/units","meta":{"navigationBar":{"titleText":"单位管理","type":"default"},"isNVue":false}},{"path":"pages/product/settings","meta":{"navigationBar":{"titleText":"货品设置","type":"default"},"isNVue":false}},{"path":"pages/customer/select","meta":{"navigationBar":{"titleText":"选择客户","type":"default"},"isNVue":false}},{"path":"pages/customer/form","meta":{"navigationBar":{"titleText":"新增客户","type":"default"},"isNVue":false}},{"path":"pages/customer/detail","meta":{"navigationBar":{"titleText":"客户详情","type":"default"},"isNVue":false}},{"path":"pages/supplier/select","meta":{"navigationBar":{"titleText":"选择供应商","type":"default"},"isNVue":false}},{"path":"pages/supplier/form","meta":{"navigationBar":{"titleText":"新增/编辑供应商","type":"default"},"isNVue":false}},{"path":"pages/account/select","meta":{"navigationBar":{"titleText":"选择账户","type":"default"},"isNVue":false}},{"path":"pages/account/ledger","meta":{"navigationBar":{"titleText":"账户流水","type":"default"},"isNVue":false}},{"path":"pages/account/form","meta":{"navigationBar":{"titleText":"新增/编辑账户","type":"default"},"isNVue":false}},{"path":"pages/detail/index","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":3,"navigationBar":{"titleText":"明细","type":"default"},"isNVue":false}},{"path":"pages/auth/login","meta":{"navigationBar":{"titleText":"登录","type":"default"},"isNVue":false}},{"path":"pages/auth/register","meta":{"navigationBar":{"titleText":"注册","type":"default"},"isNVue":false}},{"path":"pages/my/index","meta":{"isQuit":true,"isTabBar":true,"tabBarIndex":4,"navigationBar":{"titleText":"我的","type":"default"},"isNVue":false}},{"path":"pages/my/about","meta":{"navigationBar":{"titleText":"关于与协议","type":"default"},"isNVue":false}},{"path":"pages/my/security","meta":{"navigationBar":{"titleText":"账号与安全","type":"default"},"isNVue":false}},{"path":"pages/my/vip","meta":{"backgroundColor":"#1a1a2e","backgroundTextStyle":"light","navigationBar":{"backgroundColor":"#1a1a2e","titleText":"VIP会员","type":"default","titleColor":"#ffffff"},"isNVue":false}},{"path":"pages/my/orders","meta":{"navigationBar":{"titleText":"我的订单","type":"default"},"isNVue":false}},{"path":"pages/report/index","meta":{"navigationBar":{"titleText":"报表","type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
__uniConfig.styles=[];//styles
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -72,14 +72,14 @@
"statusbar": {
"immersed": "supportedDevice",
"style": "dark",
"background": "#F8F8F8"
"background": "#FFFFFF"
},
"uniStatistics": {
"enable": false
},
"allowsInlineMediaPlayback": true,
"safearea": {
"background": "#ffffff",
"background": "#FFFFFF",
"bottom": {
"offset": "auto"
}
@@ -100,8 +100,8 @@
},
"tabBar": {
"position": "bottom",
"color": "#8a7535",
"selectedColor": "#B4880F",
"color": "#444444",
"selectedColor": "#4C8DFF",
"borderStyle": "rgba(0,0,0,0.4)",
"blurEffect": "none",
"fontSize": "10px",
@@ -112,35 +112,35 @@
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/static/logo.png",
"selectedIconPath": "/static/logo.png"
"iconPath": "/static/icons/home.png",
"selectedIconPath": "/static/icons/home.png"
},
{
"pagePath": "pages/product/list",
"text": "货品",
"iconPath": "/static/logo.png",
"selectedIconPath": "/static/logo.png"
"iconPath": "/static/icons/product.png",
"selectedIconPath": "/static/icons/product.png"
},
{
"pagePath": "pages/order/create",
"text": "开单",
"iconPath": "/static/logo.png",
"selectedIconPath": "/static/logo.png"
"iconPath": "/static/icons/icons8-purchase-order-100.png",
"selectedIconPath": "/static/icons/icons8-purchase-order-100.png"
},
{
"pagePath": "pages/detail/index",
"text": "明细",
"iconPath": "/static/logo.png",
"selectedIconPath": "/static/logo.png"
"iconPath": "/static/icons/icons8-more-details-100.png",
"selectedIconPath": "/static/icons/icons8-more-details-100.png"
},
{
"pagePath": "pages/my/index",
"text": "我的",
"iconPath": "/static/logo.png",
"selectedIconPath": "/static/logo.png"
"iconPath": "/static/icons/icons8-account-male-100.png",
"selectedIconPath": "/static/icons/icons8-account-male-100.png"
}
],
"backgroundColor": "#ffffff",
"backgroundColor": "#FFFFFF",
"selectedIndex": 0,
"shown": true,
"child": [
@@ -158,7 +158,7 @@
"enable": false
},
"safearea": {
"background": "#ffffff",
"background": "#FFFFFF",
"bottom": {
"offset": "auto"
}

View File

@@ -1,23 +1,77 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.form { background:#fff;
.form {
background: #ffffff;
}
.field { display:flex; align-items:center; justify-content: space-between; padding: 0.5625rem 0.625rem; border-bottom:0.03125rem solid #f3f3f3;
.field {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5625rem 0.625rem;
border-bottom: 0.03125rem solid #e5e7eb;
}
.label { color:#666;
.label {
color: #444;
}
.input { flex:1; text-align: right; color:#333;
.input {
flex: 1;
text-align: right;
color: #111;
}
.value { color:#333;
.value {
color: #111;
}
.actions { margin-top: 0.625rem; padding: 0 0.625rem;
.actions {
margin-top: 0.625rem;
padding: 0 0.625rem;
}
.primary { width: 100%; background: #3c9cff; color:#fff; border-radius: 0.25rem; padding: 0.6875rem 0;
.primary {
width: 100%;
background: #4C8DFF;
color: #fff;
border-radius: 0.25rem;
padding: 0.6875rem 0;
}
.sheet { background:#fff;
.sheet {
background: #ffffff;
}
.sheet-item { padding: 0.8125rem; text-align:center; border-bottom:0.03125rem solid #f2f2f2;
}
.sheet-cancel { padding: 0.8125rem; text-align:center; color:#666;
.sheet-item {
padding: 0.8125rem;
text-align: center;
border-bottom: 0.03125rem solid #e5e7eb;
}
.sheet-cancel {
padding: 0.8125rem;
text-align: center;
color: #444;
}

View File

@@ -1,35 +1,107 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.filters { display:flex; gap: 0.5rem; padding: 0.5rem; background:#fff;
.filters {
display: flex;
gap: 0.5rem;
padding: 0.5rem;
background: #ffffff;
}
.field { display:flex; justify-content: space-between; align-items:center; padding: 0.5rem; border:0.03125rem solid #eee; border-radius: 0.375rem; min-width: 9.375rem;
.field {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem;
border: 0.03125rem solid #e5e7eb;
border-radius: 0.375rem;
min-width: 9.375rem;
}
.label { color:#666;
.label {
color: #444;
}
.value { color:#333;
.value {
color: #111;
}
.summary { display:grid; grid-template-columns: repeat(4,1fr); gap: 0.375rem; padding: 0.375rem 0.5rem; background:#fff; border-top:0.03125rem solid #f1f1f1; border-bottom:0.03125rem solid #f1f1f1;
.summary {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.375rem;
padding: 0.375rem 0.5rem;
background: #ffffff;
border-top: 0.03125rem solid #e5e7eb;
border-bottom: 0.03125rem solid #e5e7eb;
}
.sum-item { padding: 0.375rem; text-align:center;
.sum-item {
padding: 0.375rem;
text-align: center;
}
.k { display:block; color:#888; font-size: 0.75rem;
.k {
display: block;
color: #444;
font-size: 0.75rem;
}
.v { display:block; margin-top:0.1875rem; font-weight:700; color:#333;
.v {
display: block;
margin-top: 0.1875rem;
font-weight: 700;
color: #111;
}
.list { flex:1;
.list {
flex: 1;
}
.item { padding: 0.5625rem 0.5rem; border-bottom:0.03125rem solid #f4f4f4; background:#fff;
.item {
padding: 0.5625rem 0.5rem;
border-bottom: 0.03125rem solid #e5e7eb;
background: #ffffff;
}
.row { display:flex; align-items:center; justify-content: space-between; margin-bottom: 0.1875rem;
.row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.1875rem;
}
.title { color:#333;
.title {
color: #111;
}
.amount { font-weight:700;
.amount {
font-weight: 700;
}
.amount.in { color:#2a9d8f;
.amount.in {
color: #2a9d8f;
}
.amount.out { color:#d35b5b;
}
.meta { color:#999; font-size: 0.75rem;
.amount.out {
color: #d35b5b;
}
.meta {
color: #444;
font-size: 0.75rem;
}

View File

@@ -1,13 +1,63 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.list { flex:1;
.list {
flex: 1;
}
.item { padding: 0.625rem 0.75rem; background:#fff; border-bottom: 0.03125rem solid #f1f1f1;
.item {
padding: 0.625rem 0.75rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.name { color:#333; margin-bottom: 0.1875rem;
.name {
color: #111;
margin-bottom: 0.1875rem;
}
.meta { color:#888; font-size: 0.75rem;
}
.fab { position: fixed; right: 1rem; bottom: 3.75rem; width: 3.125rem; height: 3.125rem; border-radius: 50%; background:#3c9cff; color:#fff; display:flex; align-items:center; justify-content:center; font-size: 1.625rem; box-shadow: 0 0.3125rem 0.625rem rgba(0,0,0,0.18);
.meta {
color: #444;
font-size: 0.75rem;
}
.fab {
position: fixed;
right: 1rem;
bottom: 3.75rem;
width: 3.125rem;
height: 3.125rem;
border-radius: 50%;
background: #4C8DFF;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.625rem;
box-shadow: 0 0.3125rem 0.625rem rgba(0, 0, 0, 0.18);
}

View File

@@ -0,0 +1,163 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.auth-page {
padding: 1rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
position: relative;
min-height: 100vh;
}
.header {
display: flex;
align-items: center;
justify-content: center;
padding: 0.25rem 0 0;
}
.title {
font-size: 1.0625rem;
font-weight: 800;
color: #111;
}
.login-hero {
display: flex;
justify-content: center;
padding: 0.5rem 0 0;
}
.login-hero-img {
width: 72%;
max-width: 17.5rem;
border-radius: 0.25rem;
}
.panel {
display: flex;
flex-direction: column;
gap: 0.5rem;
background: transparent;
padding: 0;
border-radius: 0;
border: none;
}
.panel.minor {
margin-top: 0.375rem;
}
.input {
background: #ffffff;
border: 0.0625rem solid #e5e7eb;
border-radius: 0.375rem;
padding: 0.6875rem 0.625rem;
font-size: 0.875rem;
}
.row {
display: flex;
gap: 0.375rem;
align-items: center;
}
.flex1 {
flex: 1;
}
.btn {
padding: 0.6875rem 0.625rem;
border-radius: 0.375rem;
font-weight: 800;
text-align: center;
}
.btn.primary {
background: linear-gradient(135deg, #4788ff 0%, #2d6be6 100%);
color: #fff;
border: 0.03125rem solid rgba(45, 107, 230, 0.25);
width: 72%;
margin: 0 auto;
padding: 0.4375rem 0.5rem;
}
.btn.ghost {
background: #eef3ff;
color: #2d6be6;
}
/* 右下角快捷入口:贴着登录功能,无边框、无背景 */
.quick-inline {
display: flex;
gap: 0.875rem;
justify-content: flex-end;
align-items: center;
margin-top: 0.3125rem;
}
.quick-link {
background: transparent !important;
color: #2d6be6;
border: none !important;
outline: none;
padding: 0;
font-size: 0.8125rem;
font-weight: 700;
box-shadow: none;
line-height: 1.2;
}
.quick-link::after {
border: none !important;
}
/* 注册/重置页:验证码按钮与左侧输入框等高,且更紧凑 */
.panel.minor .row > .input {
height: 2.375rem;
padding: 0 0.625rem;
}
.panel.minor .row > .btn.ghost {
height: 2.375rem;
padding: 0 0.625rem;
border-radius: 0.375rem;
display: inline-flex;
align-items: center;
justify-content: center;
}

View File

@@ -0,0 +1,292 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.register-container {
position: relative;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 1.25rem 0.625rem;
overflow: hidden;
}
.background-decoration {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
.background-decoration .circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.background-decoration .circle.circle-1 {
width: 6.875rem;
height: 6.875rem;
top: 8%;
left: 12%;
animation: float 7s ease-in-out infinite;
}
.background-decoration .circle.circle-2 {
width: 5.625rem;
height: 5.625rem;
top: 65%;
right: 10%;
animation: float 9s ease-in-out infinite reverse;
}
.background-decoration .circle.circle-3 {
width: 3.75rem;
height: 3.75rem;
bottom: 15%;
left: 25%;
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0%, 100% {
transform: translateY(0px) rotate(0deg);
}
50% {
transform: translateY(-25px) rotate(5deg);
}
}
.register-card {
position: relative;
z-index: 1;
width: 90%;
max-width: 21.25rem;
background: rgba(255, 255, 255, 0.95);
-webkit-backdrop-filter: blur(0.625rem);
backdrop-filter: blur(0.625rem);
border-radius: 1rem;
padding: 1.5625rem 1.25rem 1.40625rem;
box-shadow: 0 0.78125rem 2.1875rem rgba(0, 0, 0, 0.12);
border: 0.03125rem solid rgba(255, 255, 255, 0.3);
}
.header-section {
text-align: center;
margin-bottom: 1.40625rem;
}
.header-section .logo-container {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
margin-bottom: 0.625rem;
}
.header-section .logo-container .logo-icon {
width: 1.875rem;
height: 1.875rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
}
.header-section .logo-container .logo-icon .icon {
width: 1.125rem;
height: 1.125rem;
fill: white;
}
.header-section .logo-container .app-name {
font-size: 1.125rem;
font-weight: 700;
color: #2d3748;
letter-spacing: 0.03125rem;
}
.header-section .welcome-text {
display: block;
font-size: 1.5rem;
font-weight: 700;
color: #2d3748;
margin-bottom: 0.25rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header-section .subtitle {
display: block;
font-size: 0.875rem;
color: #718096;
font-weight: 400;
}
.form-section {
margin-bottom: 1.25rem;
}
.form-section .input-group {
margin-bottom: 0.75rem;
}
.form-section .input-group .input-container {
position: relative;
background: #f7fafc;
border: 0.0625rem solid #e2e8f0;
border-radius: 0.5rem;
display: flex;
align-items: center;
transition: all 0.3s ease;
}
.form-section .input-group .input-container.focused {
border-color: #667eea;
background: #ffffff;
box-shadow: 0 0 0 0.1875rem rgba(102, 126, 234, 0.1);
transform: translateY(-0.0625rem);
}
.form-section .input-group .input-container.filled {
background: #ffffff;
border-color: #cbd5e0;
}
.form-section .input-group .input-container .input-icon {
display: flex;
align-items: center;
justify-content: center;
width: 1.5625rem;
margin-left: 0.625rem;
}
.form-section .input-group .input-container .input-icon .icon {
width: 1rem;
height: 1rem;
fill: #a0aec0;
transition: fill 0.3s ease;
}
.form-section .input-group .input-container.focused .input-icon .icon {
fill: #667eea;
}
.form-section .input-group .input-container .input-field {
flex: 1;
background: transparent;
border: none;
padding: 0.75rem 0.625rem 0.75rem 0.375rem;
font-size: 1rem;
color: #2d3748;
}
.form-section .input-group .input-container .input-field::-webkit-input-placeholder {
color: #a0aec0;
font-size: 0.875rem;
}
.form-section .input-group .input-container .input-field::placeholder {
color: #a0aec0;
font-size: 0.875rem;
}
.actions-section {
margin-bottom: 0.9375rem;
}
.actions-section .register-button {
width: 100%;
height: 3rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 0.5rem;
margin-bottom: 0.625rem;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0.25rem 0.75rem rgba(102, 126, 234, 0.3);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.actions-section .register-button:active {
transform: translateY(0.0625rem);
box-shadow: 0 0.125rem 0.5rem rgba(102, 126, 234, 0.3);
}
.actions-section .register-button::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, transparent 50%);
opacity: 0;
transition: opacity 0.3s ease;
}
.actions-section .register-button:active::before {
opacity: 1;
}
.actions-section .register-button .button-text {
font-size: 1rem;
font-weight: 600;
color: white;
letter-spacing: 0.03125rem;
}
.actions-section .login-button {
width: 100%;
height: 2.6875rem;
background: transparent;
border: 0.0625rem solid #e2e8f0;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.actions-section .login-button:active {
background: #f7fafc;
border-color: #cbd5e0;
transform: translateY(0.03125rem);
}
.actions-section .login-button .button-text {
font-size: 0.875rem;
font-weight: 500;
color: #718096;
}
.footer-section {
text-align: center;
}
.footer-section .hint-text {
display: block;
font-size: 0.75rem;
color: #a0aec0;
line-height: 1.6;
margin-bottom: 0.375rem;
}
.footer-section .static-hint {
display: block;
font-size: 0.6875rem;
color: #a0aec0;
line-height: 1.5;
background: rgba(160, 174, 192, 0.1);
padding: 0.375rem 0.5rem;
border-radius: 0.3125rem;
border: 0.03125rem solid rgba(160, 174, 192, 0.2);
}
@media (max-width: 750rpx) {
.register-card {
margin: 0.625rem;
padding: 1.25rem 0.9375rem 1.09375rem;
}
.header-section .welcome-text {
font-size: 1.3125rem;
}
.form-section .input-group {
margin-bottom: 0.625rem;
}
}

View File

@@ -1,23 +1,88 @@
.page { padding-bottom: 4.375rem;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding-bottom: 4.375rem;
}
.card { background:#fff; margin: 0.5rem; padding: 0.375rem 0.5rem; border-radius: 0.5rem;
.card {
background: #ffffff;
margin: 0.5rem;
padding: 0.375rem 0.5rem;
border-radius: 0.5rem;
}
.row { display:flex; justify-content: space-between; padding: 0.5625rem 0.25rem; border-bottom: 0.03125rem solid #f3f3f3;
.row {
display: flex;
justify-content: space-between;
padding: 0.5625rem 0.25rem;
border-bottom: 0.03125rem solid #e5e7eb;
}
.row:last-child { border-bottom: 0;
.row:last-child {
border-bottom: 0;
}
.label { color:#666;
.label {
color: #444;
}
.value { color:#333; max-width: 60%; text-align: right;
.value {
color: #111;
max-width: 60%;
text-align: right;
}
.value-input { color:#333; text-align: right; flex: 1;
.value-input {
color: #111;
text-align: right;
flex: 1;
}
.emp { color:#107e9b; font-weight: 700;
.emp {
color: #4C8DFF;
font-weight: 700;
}
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem); box-shadow: 0 -0.125rem 0.375rem rgba(0,0,0,0.06); display:flex; gap: 0.375rem;
.bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem);
box-shadow: 0 -0.125rem 0.375rem rgba(0, 0, 0, 0.1);
display: flex;
gap: 0.375rem;
}
.primary { flex:1; background: linear-gradient(135deg, #A0E4FF 0%, #17A2C4 100%); color:#fff; border-radius: 31.21875rem; padding: 0.625rem 0;
}
.ghost { flex:1; background:#fff; color:#107e9b; border: 0.0625rem solid #A0E4FF; border-radius: 31.21875rem; padding: 0.5625rem 0;
.primary {
flex: 1;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.625rem 0;
}
.ghost {
flex: 1;
background: #ffffff;
color: #4C8DFF;
border: 0.0625rem solid rgba(76, 141, 255, 0.35);
border-radius: 31.21875rem;
padding: 0.5625rem 0;
}

View File

@@ -1,15 +1,66 @@
.page { padding-bottom: 4.375rem;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding-bottom: 4.375rem;
}
.field { display:flex; justify-content: space-between; padding: 0.6875rem 0.75rem; background:#fff; border-bottom:0.03125rem solid #eee;
.field {
display: flex;
justify-content: space-between;
padding: 0.6875rem 0.75rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.label { color:#666;
.label {
color: #444;
}
.value { color:#333; text-align: right; flex: 1;
.value {
color: #111;
text-align: right;
flex: 1;
}
.textarea { padding: 0.5rem 0.75rem; background:#fff; margin-top: 0.375rem;
.textarea {
padding: 0.5rem 0.75rem;
background: #ffffff;
margin-top: 0.375rem;
}
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem); box-shadow: 0 -0.125rem 0.375rem rgba(0,0,0,0.06);
}
.primary { width: 100%; background: linear-gradient(135deg, #A0E4FF 0%, #17A2C4 100%); color:#fff; border-radius: 31.21875rem; padding: 0.625rem 0;
.bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem);
box-shadow: 0 -0.125rem 0.375rem rgba(0, 0, 0, 0.1);
}
.primary {
width: 100%;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.625rem 0;
}

View File

@@ -1,19 +1,78 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.search { display:flex; gap: 0.375rem; padding: 0.5rem; background:#fff; align-items:center;
.search {
display: flex;
gap: 0.375rem;
padding: 0.5rem;
background: #ffffff;
align-items: center;
}
.search uni-input { flex:1; background:#f6f6f6; border-radius: 0.375rem; padding: 0.375rem;
.search uni-input {
flex: 1;
background: #f1f1f1;
border-radius: 0.375rem;
padding: 0.375rem;
color: #111;
}
.list { flex:1;
.list {
flex: 1;
}
.item { padding: 0.625rem 0.75rem; background:#fff; border-bottom: 0.03125rem solid #f1f1f1;
.item {
padding: 0.625rem 0.75rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.name { color:#333; margin-bottom: 0.1875rem;
.name {
color: #111;
margin-bottom: 0.1875rem;
}
.meta { color:#888; font-size: 0.75rem;
.meta {
color: #444;
font-size: 0.75rem;
}
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem); box-shadow: 0 -0.125rem 0.375rem rgba(0,0,0,0.06);
}
.primary { width: 100%; background: linear-gradient(135deg, #A0E4FF 0%, #17A2C4 100%); color:#fff; border-radius: 31.21875rem; padding: 0.625rem 0;
.bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem);
box-shadow: 0 -0.125rem 0.375rem rgba(0, 0, 0, 0.1);
}
.primary {
width: 100%;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.625rem 0;
}

View File

@@ -1,49 +1,220 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.page { display:flex; flex-direction: column; height: 100vh;
/* 顶部分段(如需保留,可以隐藏或后续扩展) */
.seg {
display: none;
}
.seg { display:flex; background:#fff;
.content {
display: flex;
flex: 1;
min-height: 0;
}
.seg-item { flex:1; padding: 0.6875rem 0; text-align:center; color:#666;
.biz-tabs {
width: 4.375rem;
background: #fff;
border-right: 0.0625rem solid #e5e7eb;
display: flex;
flex-direction: column;
}
.seg-item.active { color:#18b566; font-weight: 600;
.biz {
flex: 0 0 3.75rem;
display: flex;
align-items: center;
justify-content: center;
color: #4C8DFF;
}
.content { display:flex; flex:1; min-height: 0;
.biz.active {
background: rgba(76, 141, 255, 0.1);
color: #4C8DFF;
font-weight: 700;
}
.biz-tabs { width: 3.75rem; background:#eef6ff; display:flex; flex-direction: column;
.panel {
flex: 1;
display: flex;
flex-direction: column;
background: #fff;
margin: 0.5rem;
border-radius: 0.5rem;
padding: 0.375rem;
}
.biz { flex:0 0 3.75rem; display:flex; align-items:center; justify-content:center; color:#4aa3d6;
.toolbar {
display: flex;
flex-direction: column;
gap: 0.3125rem;
padding: 0.3125rem 0.1875rem 0.1875rem;
border-bottom: 0.0625rem solid #e5e7eb;
}
.biz.active { background:#3ac1c9; color:#fff; border-radius: 0 0.5rem 0.5rem 0;
.period-group {
display: flex;
align-items: center;
gap: 0.25rem;
background: #f6f8fb;
border-radius: 0.3125rem;
padding: 0.25rem 0.3125rem;
}
.panel { flex:1; display:flex; flex-direction: column; background:#fff; margin: 0.5rem; border-radius: 0.5rem; padding: 0.375rem;
.period-label {
color: #6b778c;
}
.toolbar { display:flex; align-items: center; gap: 0.375rem; padding: 0.25rem 0.1875rem;
.date-chip {
padding: 0.25rem 0.375rem;
background: #fff;
border: 0.0625rem solid #e6ebf2;
border-radius: 0.25rem;
}
.search { flex:1;
.sep {
color: #99a2b3;
padding: 0 0.1875rem;
}
.search-input { width:100%; background:#f6f6f6; border-radius: 0.375rem; padding: 0.375rem;
.search-row {
display: flex;
align-items: center;
gap: 0.5rem;
}
.period { color:#999; font-size: 0.75rem; padding: 0 0.1875rem;
.search {
flex: 1;
min-width: 0;
display: flex;
}
.total { color:#18b566; font-weight: 700; padding: 0.1875rem 0.1875rem 0.375rem;
.search-input {
flex: 1;
height: 2.25rem;
line-height: 2.25rem;
padding: 0 0.75rem;
box-sizing: border-box;
background: #fff;
border-radius: 0.375rem;
color: #111;
border: 0.0625rem solid #e6ebf2;
font-size: 0.8125rem;
}
.list { flex:1;
.btn {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
height: 2.25rem;
padding: 0 1rem;
margin-left: 0.125rem;
border-radius: 0.375rem;
background: #4C8DFF;
color: #fff;
border: none;
font-size: 0.8125rem;
box-sizing: border-box;
}
.item { display:flex; align-items:center; padding: 0.625rem 0.3125rem; border-bottom: 0.03125rem solid #f1f1f1;
.btn::after {
border: none;
}
.item-left { flex:1;
.total {
color: #4C8DFF;
font-weight: 700;
padding: 0.3125rem 0.1875rem 0.375rem;
background: #fff;
}
.date { color:#999; font-size: 0.75rem;
.list {
flex: 1;
}
.name { color:#333; margin: 0.125rem 0; font-weight: 600;
.loading {
text-align: center;
padding: 0.625rem 0;
color: #444;
}
.no { color:#bbb; font-size: 0.6875rem;
.finished {
text-align: center;
padding: 0.625rem 0;
color: #444;
}
.amount { color:#333; font-weight: 700;
.item {
display: grid;
grid-template-columns: 1fr auto auto;
align-items: center;
gap: 0.25rem;
padding: 0.5625rem 0.375rem;
border-bottom: 0.03125rem solid #e5e7eb;
}
.arrow { color:#ccc; font-size: 1.25rem; margin-left: 0.25rem;
.item-left {
display: flex;
flex-direction: column;
}
.empty { height: 50vh; display:flex; align-items:center; justify-content:center; color:#999;
.date {
color: #444;
font-size: 0.75rem;
}
.fab { position: fixed; right: 0.9375rem; bottom: 3.75rem; width: 3.125rem; height: 3.125rem; background:#18b566; color:#fff; border-radius: 1.5625rem; text-align:center; line-height: 3.125rem; font-size: 1.5rem; box-shadow: 0 0.25rem 0.625rem rgba(0,0,0,0.15);
.name {
color: #111;
margin: 0.125rem 0;
font-weight: 600;
}
.no {
color: #99a2b3;
font-size: 0.6875rem;
}
.amount {
color: #111;
font-weight: 700;
text-align: right;
}
.amount.in {
color: #16a34a;
}
.amount.out {
color: #dc2626;
}
.arrow {
color: #8c99b0;
font-size: 1.25rem;
margin-left: 0.25rem;
}
.empty {
height: 50vh;
display: flex;
align-items: center;
justify-content: center;
color: #444;
}
.fab {
position: fixed;
right: 0.9375rem;
bottom: 3.75rem;
width: 3.125rem;
height: 3.125rem;
background: #fff;
color: #4C8DFF;
border: 0.0625rem solid #4C8DFF;
border-radius: 1.5625rem;
text-align: center;
line-height: 3.125rem;
font-size: 1.5rem;
box-shadow: 0 0.25rem 0.625rem rgba(76, 141, 255, 0.18);
}

View File

@@ -1,185 +1,418 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
body {
height: 100%;
overflow: hidden;
background: linear-gradient(180deg, #f8fbff 0%, #ffffff 60%);
}
.home {
padding-bottom: 4.375rem;
position: relative;
/* 明亮奢华背景:金属拉丝纹理覆盖层 + 柔和浅色渐变 */
background:
repeating-linear-gradient(0deg, rgba(180,180,180,0.12) 0, rgba(180,180,180,0.12) 0.0625rem, rgba(255,255,255,0.0) 0.0625rem, rgba(255,255,255,0.0) 0.3125rem),
linear-gradient(180deg, rgba(255, 255, 255, 0.75) 0%, rgba(255, 255, 255, 0.55) 40%, rgba(255, 255, 255, 0.35) 100%);
min-height: 100vh;
}
.home-bg {
position: fixed;
left: 0; top: 0; right: 0; bottom: 0;
width: 100%; height: 100%;
pointer-events: none;
z-index: -1;
height: 100vh;
display: flex;
flex-direction: column;
padding-bottom: calc(env(safe-area-inset-bottom) + 1rem);
position: relative;
/* 渐变背景:顶部淡蓝过渡到白色 */
background: linear-gradient(180deg, #f8fbff 0%, #ffffff 60%);
overflow: hidden;
box-sizing: border-box;
}
/* 公告栏 */
/* 首页横幅(移除) */
/* 公告栏 */
.notice {
margin: 0 0.75rem 0.75rem;
padding: 0.625rem 0.6875rem;
border-radius: 0.625rem;
background: rgba(255,255,255,0.78);
-webkit-backdrop-filter: blur(0.375rem);
backdrop-filter: blur(0.375rem);
border: 0.0625rem solid rgba(203, 166, 61, 0.28);
display: flex;
align-items: center;
gap: 0.5rem;
margin: 0 0.75rem 0.75rem;
padding: 0.625rem 0.6875rem;
border-radius: 0.625rem;
background: #ffffff;
border: 0.0625rem solid #e5e7eb;
display: flex;
align-items: center;
gap: 0.5rem;
}
.notice-left {
flex: 0 0 auto;
display: inline-flex; align-items: center; justify-content: center;
min-width: 3rem; height: 1.375rem;
padding: 0 0.5rem;
border-radius: 31.21875rem;
background: linear-gradient(135deg, #FFE69A, #F4CF62);
color: #3f320f;
font-size: 0.75rem;
font-weight: 800;
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 3.125rem;
height: 1.625rem;
padding: 0 0.5rem;
border-radius: 31.21875rem;
background: #4C8DFF;
color: #fff;
font-size: 0.875rem;
font-weight: 800;
}
.notice-swiper { height: 2.25rem; flex: 1;
.notice-swiper {
height: 2.25rem;
flex: 1;
}
.notice-item { display: flex; align-items: center; gap: 0.375rem; min-height: 2.25rem;
.notice-item {
display: flex;
align-items: center;
gap: 0.375rem;
min-height: 2.25rem;
}
.notice-text { color: #4b3e19; font-size: 0.875rem; line-height: 1.125rem; font-weight: 600; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
.notice-text {
color: #111;
font-size: 0.875rem;
line-height: 1.125rem;
font-weight: 600;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.notice-tag { color: #B4880F; font-size: 0.6875rem; padding: 0.125rem 0.3125rem; border-radius: 31.21875rem; background: rgba(215,167,46,0.18);
.notice-tag {
color: #4C8DFF;
font-size: 0.6875rem;
padding: 0.125rem 0.3125rem;
border-radius: 31.21875rem;
background: rgba(76, 141, 255, 0.18);
}
/* 分割标题 */
.section-title { display: flex; align-items: center; gap: 0.5rem; padding: 0.3125rem 0.875rem 0;
/* 分割标题 */
.section-title {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.3125rem 0.875rem 0;
flex: 0 0 auto;
}
.section-title::before { content: ''; display: block; width: 0.25rem; height: 0.875rem; border-radius: 0.25rem; background: linear-gradient(180deg, #FFE69A, #D7A72E);
.section-title::before {
content: "";
display: block;
width: 0.25rem;
height: 0.875rem;
border-radius: 0.25rem;
background: #4C8DFF;
}
.section-text { color: #6b5a2a; font-size: 0.875rem; font-weight: 700; letter-spacing: 0.03125rem;
.section-text {
color: #111;
font-size: 0.9375rem;
font-weight: 700;
letter-spacing: 0.03125rem;
}
/* 顶部英雄区:浅色玻璃卡片,带金色描边与柔和阴影 */
/* 顶部英雄区:浅色玻璃卡片,带金色描边与柔和阴影 */
.hero {
margin: 0.75rem;
padding: 1rem;
border-radius: 0.875rem;
background: rgba(255, 255, 255, 0.65);
-webkit-backdrop-filter: blur(0.4375rem);
backdrop-filter: blur(0.4375rem);
border: 0.0625rem solid rgba(203, 166, 61, 0.35);
box-shadow: 0 0.375rem 0.875rem rgba(0, 0, 0, 0.10), 0 0 0 0.0625rem rgba(255,255,255,0.60) inset;
color: #473c22;
margin: 0.5rem 0.625rem;
padding: 0.5625rem 0.5625rem 0.375rem;
border-radius: 0.625rem;
background: #ffffff;
border: 0.0625rem solid #e5e7eb;
box-shadow: none;
color: #111;
flex: 0 0 auto;
}
.hero-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.625rem;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.625rem;
}
.hero-sub {
display: flex;
gap: 0.375rem;
margin-bottom: 0.6875rem;
flex-wrap: wrap;
}
.chip {
padding: 0.25rem 0.5rem;
border-radius: 31.21875rem;
background: rgba(76, 141, 255, 0.1);
color: #4C8DFF;
font-size: 0.75rem;
font-weight: 700;
border: 0.0625rem solid rgba(76, 141, 255, 0.25);
}
.brand {
font-size: 1.3125rem;
font-weight: 700;
letter-spacing: 0.0625rem;
color: #B4880F; /* 金色标题 */
font-size: 1.125rem;
font-weight: 700;
letter-spacing: 0.03125rem;
color: #4C8DFF;
}
.cta {
padding: 0.3125rem 0.6875rem;
border-radius: 31.21875rem;
background: linear-gradient(135deg, rgba(255, 220, 128, 0.65), rgba(255, 240, 190, 0.65));
border: 0.0625rem solid rgba(203, 166, 61, 0.45);
box-shadow: 0 0.1875rem 0.4375rem rgba(203, 166, 61, 0.25);
padding: 0.25rem 0.5625rem;
border-radius: 31.21875rem;
background: #4C8DFF;
border: 0.0625rem solid #4C8DFF;
box-shadow: none;
}
.cta-text { color: #5a4712; font-size: 0.8125rem;
}
.kpi { display: flex;
}
.kpi-item { flex: 1;
}
.kpi-label { opacity: 0.9; font-size: 0.75rem; color: #6b5a2a;
}
.kpi-value { display: block; margin-top: 0.375rem; font-size: 1.4375rem; font-weight: 800; color: #B4880F;
.cta-text {
color: #fff;
font-size: 0.9375rem;
font-weight: 700;
letter-spacing: 0.03125rem;
}
/* 功能容器:整体玻璃面板,增强融入感 */
.grid-wrap {
margin: 0 0.625rem 1rem;
padding: 0.875rem 0.625rem 0.375rem;
border-radius: 0.75rem;
background: rgba(255,255,255,0.55);
-webkit-backdrop-filter: blur(0.3125rem);
backdrop-filter: blur(0.3125rem);
border: 0.0625rem solid rgba(203,166,61,0.22);
box-shadow: 0 0.25rem 0.5625rem rgba(0,0,0,0.06);
/* 简易弹层样式 */
.dialog-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
}
.dialog {
width: 82vw;
background: #fff;
border-radius: 0.5rem;
padding: 0.625rem;
border: 0.0625rem solid #eef2f6;
}
.dialog-title {
font-size: 1rem;
font-weight: 800;
color: #111;
margin-bottom: 0.5rem;
}
.dialog-textarea {
width: 100%;
min-height: 5.625rem;
border: 0.0625rem solid #e8eef8;
border-radius: 0.375rem;
padding: 0.375rem;
box-sizing: border-box;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 0.5625rem;
margin-top: 0.5rem;
}
.btn {
padding: 0.3125rem 0.6875rem;
border-radius: 31.21875rem;
background: #f3f6fb;
color: #334155;
border: 0.0625rem solid #e2e8f0;
font-weight: 700;
}
.btn.primary {
background: #4C8DFF;
color: #fff;
border-color: #4C8DFF;
}
/* 功能九宫格 */
/* KPI 卡片化布局:横向铺满 */
.kpi {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.375rem;
}
.kpi-item {
text-align: center;
background: #ffffff;
border: 0.0625rem solid #e5e7eb;
border-radius: 0.5rem;
padding: 0.5rem 0.25rem;
}
/* KPI 卡片(更扁平,降低高度) */
.kpi-grid {
gap: 0.375rem;
}
.kpi-card {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: 0.25rem;
text-align: left;
padding: 0.375rem 0.4375rem;
border-radius: 0.4375rem;
background: #fff;
border: 0.0625rem solid #eef2f6;
box-shadow: 0 0.0625rem 0.25rem rgba(0, 0, 0, 0.04);
min-height: 3.75rem;
}
.kpi-icon {
width: 1.375rem;
height: 1.375rem;
opacity: 0.9;
}
.kpi-content {
display: flex;
flex-direction: column;
}
.kpi-label {
color: #6b778c;
font-weight: 700;
font-size: 0.75rem;
line-height: 0.9375rem;
}
.kpi-value {
color: #4C8DFF;
font-size: 1.0625rem;
line-height: 1.1875rem;
margin-top: 0;
font-weight: 800;
}
/* 常用功能:胶囊+阴影卡片样式的图标栅格(旧风格保留以防回退) */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 2rem;
grid-column-gap: 1.125rem;
padding: 1.25rem 0.875rem 0.875rem;
grid-row-gap: 1.125rem;
grid-column-gap: 0.8125rem;
padding: 1rem 0.75rem 0.875rem;
}
.grid-item { display: flex; flex-direction: column; align-items: center; text-align: center;
}
.icon { display: flex; align-items: center; justify-content: center; color: #6b5a2a; position: relative;
.grid-item {
position: relative;
}
.icon-squircle {
width: 4.125rem; height: 4.125rem;
border-radius: 0.875rem;
background: linear-gradient(145deg, rgba(255,255,255,0.92), rgba(255,255,255,0.70));
-webkit-backdrop-filter: blur(0.375rem);
backdrop-filter: blur(0.375rem);
border: 0.0625rem solid rgba(203,166,61,0.22);
box-shadow: 0 0.3125rem 0.75rem rgba(0,0,0,0.10), 0 0 0 0.0625rem rgba(255,255,255,0.65) inset;
overflow: hidden;
width: 4.375rem;
height: 4.375rem;
border-radius: 0.875rem;
background: #fff;
border: 0.0625rem solid #e5e7eb;
box-shadow: 0 0.3125rem 0.625rem rgba(0, 0, 0, 0.06);
}
.icon-squircle::before { content: ''; position: absolute; left: -30%; top: -40%; width: 160%; height: 70%; background: linear-gradient( to bottom, rgba(255,255,255,0.9), rgba(255,255,255,0.0) ); transform: rotate(12deg);
}
.icon-img { width: 3rem; height: 3rem;
}
.icon-emoji { font-size: 1.875rem; line-height: 1;
}
.icon-placeholder { width: 2.625rem; height: 2.625rem; border-radius: 0.5625rem; background:
linear-gradient(135deg, rgba(212,175,55,0.18), rgba(255,255,255,0.0)),
repeating-linear-gradient(90deg, rgba(180,150,60,0.35) 0, rgba(180,150,60,0.35) 0.25rem, transparent 0.25rem, transparent 0.5rem),
repeating-linear-gradient(0deg, rgba(180,150,60,0.20) 0, rgba(180,150,60,0.20) 0.25rem, transparent 0.25rem, transparent 0.5rem);
box-shadow: inset 0 0 0 0.0625rem rgba(203,166,61,0.28);
}
.icon-text { font-size: 1.4375rem; font-weight: 700;
}
.grid-title { display: none;
}
.grid-chip { margin-top: 0.4375rem; padding: 0.1875rem 0.4375rem; border-radius: 31.21875rem; background: rgba(215,167,46,0.16); color: #5a4a1f; font-size: 0.6875rem;
.grid-chip {
margin-top: 0.375rem;
padding: 0.1875rem 0.4375rem;
border-radius: 31.21875rem;
background: rgba(76, 141, 255, 0.12);
color: #4C8DFF;
font-size: 0.8125rem;
font-weight: 700;
}
/* 底部操作条:浅色半透明 + 金色主按钮 */
/* 功能容器:更轻的留白 */
.grid-wrap {
flex: 1 1 auto;
display: flex;
align-items: stretch;
justify-content: center;
margin: 0.5rem 0.625rem 0.875rem;
padding: 1rem 0.9375rem;
border-radius: 0.8125rem;
background: rgba(255, 255, 255, 0.96);
border: 0.0625rem solid #edf2f9;
box-shadow: 0 0.375rem 0.875rem rgba(32, 75, 143, 0.1);
box-sizing: border-box;
}
/* 功能卡片宫格:方形竖排,图标在上文字在下(与截图一致) */
.feature-grid {
flex: 1 1 auto;
width: 100%;
height: 100%;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-auto-rows: 1fr;
gap: 1rem 0.875rem;
align-content: space-evenly;
justify-items: center;
}
.feature-card {
width: 5.25rem;
height: 5.5rem;
background: #fff;
border: 0.0625rem solid #eef2f6;
border-radius: 0.625rem;
box-shadow: 0 0.3125rem 0.75rem rgba(0, 0, 0, 0.05);
padding: 0.5625rem 0.5rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.fc-icon {
width: 2.4375rem;
height: 2.4375rem;
border-radius: 0.5625rem;
background: #f7faff;
display: flex;
align-items: center;
justify-content: center;
}
.fc-img {
width: 1.6875rem;
height: 1.6875rem;
opacity: 0.95;
}
.fc-emoji {
font-size: 1.5rem;
}
.fc-placeholder {
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
background: #f1f1f1;
border: 0.0625rem solid #e8eef8;
}
.fc-title {
margin-top: 0.375rem;
font-size: 0.875rem;
font-weight: 700;
color: #111;
letter-spacing: 0.03125rem;
}
/* 底部操作条:浅色半透明 + 金色主按钮 */
.bottom-bar {
position: fixed;
left: 0; right: 0; bottom: 0;
display: flex;
align-items: center;
justify-content: space-around;
padding: 0.4375rem 0.5625rem calc(env(safe-area-inset-bottom) + 0.4375rem);
background: rgba(255,255,255,0.85);
box-shadow: 0 -0.1875rem 0.5625rem rgba(0,0,0,0.08);
-webkit-backdrop-filter: blur(0.3125rem);
backdrop-filter: blur(0.3125rem);
z-index: 9999;
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: space-around;
padding: 0.4375rem 0.5625rem calc(env(safe-area-inset-bottom) + 0.4375rem);
background: rgba(255, 255, 255, 0.85);
box-shadow: 0 -0.1875rem 0.5625rem rgba(0, 0, 0, 0.08);
-webkit-backdrop-filter: blur(0.3125rem);
backdrop-filter: blur(0.3125rem);
z-index: 9999;
}
.tab { flex: 1; text-align: center; color: #8a7535; font-size: 0.8125rem;
.tab {
flex: 1;
text-align: center;
color: #8a7535;
font-size: 0.8125rem;
}
.tab.active { color: #B4880F;
.tab.active {
color: #B4880F;
}
.tab.primary {
flex: 0 0 auto;
min-width: 5.625rem;
margin: 0 0.5625rem;
padding: 0.5625rem 1rem;
background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%);
color: #493c1b;
border-radius: 31.21875rem;
font-size: 0.9375rem;
font-weight: 800;
box-shadow: 0 0.3125rem 0.6875rem rgba(215,167,46,0.25), 0 0 0 0.0625rem rgba(255,255,255,0.70) inset;
}
flex: 0 0 auto;
min-width: 5.625rem;
margin: 0 0.5625rem;
padding: 0.5625rem 1rem;
background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%);
color: #493c1b;
border-radius: 31.21875rem;
font-size: 0.9375rem;
font-weight: 800;
box-shadow: 0 0.3125rem 0.6875rem rgba(215, 167, 46, 0.25), 0 0 0 0.0625rem rgba(255, 255, 255, 0.7) inset;
}

View File

@@ -1,21 +1,75 @@
.about { padding: 0.75rem;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.about {
padding: 0.75rem;
}
.hero { padding: 1rem 0.75rem; display: flex; flex-direction: column; align-items: center; gap: 0.3125rem;
.hero {
padding: 1rem 0.75rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3125rem;
}
.logo { width: 5rem; height: 5rem; border-radius: 1rem;
.logo {
width: 5rem;
height: 5rem;
border-radius: 1rem;
}
.title { margin-top: 0.25rem; font-size: 1.125rem; font-weight: 800; color: #333;
.title {
margin-top: 0.25rem;
font-size: 1.125rem;
font-weight: 800;
color: #111;
}
.subtitle { font-size: 0.8125rem; color: #888;
.subtitle {
font-size: 0.8125rem;
color: #444;
}
.card { margin-top: 0.5625rem; background: #fff; border-radius: 0.5rem; overflow: hidden;
.card {
margin-top: 0.5625rem;
background: #ffffff;
border-radius: 0.5rem;
overflow: hidden;
}
.row { display: flex; align-items: center; padding: 0.75rem; border-top: 0.03125rem solid #f2f2f2;
.row {
display: flex;
align-items: center;
padding: 0.75rem;
border-top: 0.03125rem solid #e5e7eb;
}
.label { color: #666;
.label {
color: #444;
}
.value { margin-left: auto; color: #333;
}
.link { margin-left: auto; color: #1aad19;
.value {
margin-left: auto;
color: #111;
}
.link {
margin-left: auto;
color: #4C8DFF;
}

View File

@@ -1,27 +1,254 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.me {
padding: 0.75rem;
}
.card.login {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 0.6875rem;
background: #ffffff;
border-radius: 0.5rem;
margin-bottom: 0.75rem;
}
.login-title {
font-size: 0.875rem;
font-weight: 700;
}
.login-btn.minor {
background: #f1f1f1;
color: #111;
}
.hint {
font-size: 0.6875rem;
color: #444;
}
.card.user {
display: flex;
gap: 0.5625rem;
padding: 0.6875rem;
background: #ffffff;
border-radius: 0.5rem;
box-shadow: 0 0.1875rem 0.5rem rgba(0, 0, 0, 0.16);
align-items: center;
}
.card.user.guest {
justify-content: space-between;
}
.card.user.guest .meta {
flex: 1;
}
.card.user.guest .login-entry {
padding: 0.375rem 0.9375rem;
border-radius: 31.21875rem;
background: #4C8DFF;
color: #fff;
font-size: 0.875rem;
font-weight: 600;
}
.avatar {
width: 3.75rem;
height: 3.75rem;
border-radius: 1.875rem;
background: #f1f1f1;
}
.meta {
display: flex;
flex-direction: column;
gap: 0.1875rem;
}
.name {
font-size: 1.0625rem;
font-weight: 700;
color: #111;
}
.phone {
font-size: 0.8125rem;
color: #444;
}
.role {
font-size: 0.6875rem;
color: #444;
}
.me { padding: 0.75rem;
/* VIP 卡片样式 */
.card.vip {
margin-top: 0.75rem;
padding: 0.6875rem;
background: #ffffff;
border-radius: 0.5rem;
box-shadow: 0 0.1875rem 0.5rem rgba(0, 0, 0, 0.12);
}
.card.user { display: flex; gap: 0.5625rem; padding: 0.6875rem; background: #fff; border-radius: 0.5rem; box-shadow: 0 0.1875rem 0.5rem rgba(0,0,0,0.06); align-items: center;
.card.vip.active {
border: 0.03125rem solid rgba(255, 208, 0, 0.6);
background-image: radial-gradient(60% 60% at 80% 0%, rgba(255, 214, 0, 0.08), transparent 60%);
}
.avatar { width: 3.75rem; height: 3.75rem; border-radius: 1.875rem; background: #f5f5f5;
.vip-row {
display: flex;
align-items: center;
gap: 0.375rem;
margin-bottom: 0.3125rem;
}
.meta { display: flex; flex-direction: column; gap: 0.1875rem;
.vip-badge {
background: #f1c40f;
color: #111;
font-weight: 800;
padding: 0.0625rem 0.3125rem;
border-radius: 0.25rem;
font-size: 0.6875rem;
}
.name { font-size: 1.0625rem; font-weight: 700; color: #333;
.vip-title {
font-size: 0.875rem;
font-weight: 700;
color: #111;
}
.phone { font-size: 0.8125rem; color: #888;
.vip-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.25rem 0.5rem;
}
.role { font-size: 0.6875rem; color: #999;
.vip-meta .item {
display: flex;
align-items: center;
gap: 0.3125rem;
}
.group { margin-top: 0.75rem; background: #fff; border-radius: 0.5rem; overflow: hidden;
.vip-meta .label {
width: 2.5rem;
color: #444;
font-size: 0.75rem;
}
.group-title { padding: 0.5625rem 0.6875rem; font-size: 0.8125rem; color: #999; background: #fafafa;
.vip-meta .value {
color: #111;
font-size: 0.8125rem;
word-break: break-all;
}
.cell { display: flex; align-items: center; padding: 0.8125rem 0.6875rem; border-top: 0.03125rem solid #f0f0f0; color: #333;
.group {
margin-top: 0.75rem;
background: #ffffff;
border-radius: 0.5rem;
overflow: hidden;
}
.cell .desc { margin-left: auto; margin-right: 0.25rem; font-size: 0.6875rem; color: #999;
.group-title {
padding: 0.5625rem 0.6875rem;
font-size: 0.8125rem;
color: #444;
background: #f1f1f1;
}
.cell .arrow { margin-left: auto; color: #bbb;
.cell {
display: flex;
align-items: center;
padding: 0.8125rem 0.6875rem;
border-top: 0.03125rem solid #e5e7eb;
color: #111;
gap: 0.5625rem;
}
.cell.danger { color: #dd524d; justify-content: center; font-weight: 700;
.cell-left {
display: flex;
align-items: center;
gap: 0.4375rem;
}
.vip-tag {
padding: 0.125rem 0.375rem;
border-radius: 31.21875rem;
background: rgba(76, 141, 255, 0.15);
color: #4C8DFF;
font-size: 0.6875rem;
}
.vip-tag.pending {
background: rgba(76, 141, 255, 0.06);
color: #99a2b3;
}
.cell .desc {
margin-left: auto;
margin-right: 0.25rem;
font-size: 0.6875rem;
color: #444;
}
.cell .arrow {
margin-left: auto;
color: #99a2b3;
}
.cell.danger {
color: #dd524d;
justify-content: center;
font-weight: 700;
}
/* 简易对话框样式 */
.dialog-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
.dialog {
width: 18.75rem;
background: #fff;
border-radius: 0.5rem;
padding: 0.75rem;
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.2);
}
.dialog-title {
font-size: 0.9375rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.dialog-input {
width: 100%;
height: 2.25rem;
padding: 0 0.5rem;
border: 0.03125rem solid #e5e7eb;
border-radius: 0.3125rem;
background: #fff;
color: #111;
}
.dialog-actions {
display: flex;
gap: 0.5rem;
margin-top: 0.5625rem;
justify-content: flex-end;
}
.dialog-btn {
padding: 0.5rem 0.6875rem;
border-radius: 0.3125rem;
}
.dialog-btn.cancel {
background: #f1f1f1;
color: #111;
}
.dialog-btn.confirm {
background: #2979ff;
color: #fff;
}

View File

@@ -0,0 +1,73 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.orders {
padding: 0.5rem 0.5rem calc(env(safe-area-inset-bottom) + 0.5rem);
}
.hint {
color: #444;
padding: 0.75rem;
text-align: center;
}
.item {
background: #fff;
border: 0.03125rem solid #e5e7eb;
border-radius: 0.5rem;
padding: 0.5625rem;
margin: 0.375rem 0;
}
.row1 {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.1875rem;
}
.price {
color: #111;
font-weight: 800;
font-size: 1.0625rem;
}
.channel {
color: #666;
font-size: 0.75rem;
}
.row2 {
display: flex;
justify-content: space-between;
color: #666;
font-size: 0.75rem;
}
.row3 {
margin-top: 0.1875rem;
color: #4C8DFF;
font-size: 0.75rem;
}
.empty {
text-align: center;
color: #999;
padding: 1.25rem 0;
}

View File

@@ -0,0 +1,99 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.security {
padding: 0.75rem;
}
.card {
background: #ffffff;
border-radius: 0.5rem;
padding: 0.6875rem;
margin-bottom: 0.75rem;
box-shadow: 0 0.1875rem 0.5rem rgba(0, 0, 0, 0.08);
}
.cell {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.625rem 0;
border-bottom: 0.03125rem solid #e5e7eb;
}
.cell:last-of-type {
border-bottom: none;
}
.cell-label {
flex: 1;
font-size: 0.875rem;
color: #111;
}
.cell-input {
flex: 2;
height: 2.25rem;
padding: 0 0.5rem;
border: 0.03125rem solid #e5e7eb;
border-radius: 0.3125rem;
background: #fff;
color: #111;
}
.avatar-preview {
width: 3.125rem;
height: 3.125rem;
border-radius: 0.5rem;
background: #f1f1f1;
}
.arrow {
margin-left: 0.375rem;
color: #99a2b3;
font-size: 1rem;
}
.row {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.label {
width: 5rem;
color: #111;
font-size: 0.875rem;
}
.input {
flex: 1;
height: 2.25rem;
padding: 0 0.5rem;
border: 0.03125rem solid #e5e7eb;
border-radius: 0.3125rem;
background: #fff;
color: #111;
}
.btn {
margin-top: 0.25rem;
}
.btn.minor {
background: #f1f1f1;
color: #111;
}

View File

@@ -0,0 +1,289 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
body {
background: linear-gradient(180deg, #f8fbff 0%, #ffffff 60%) !important;
}
.vip-page {
min-height: 100vh;
padding: 1rem 0.75rem 3.75rem;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 0.875rem;
}
.vip-hero {
display: flex;
align-items: center;
gap: 0.625rem;
padding: 0.8125rem 0.875rem;
border-radius: 0.75rem;
background: rgba(255, 255, 255, 0.98);
border: 0.0625rem solid #edf2f9;
box-shadow: 0 0.3125rem 0.9375rem rgba(76, 141, 255, 0.12);
}
.hero-icon {
width: 2.75rem;
height: 2.75rem;
border-radius: 0.75rem;
background: #f0f6ff;
padding: 0.375rem;
}
.hero-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.hero-title {
font-size: 1.125rem;
font-weight: 800;
color: #4C8DFF;
letter-spacing: 0.03125rem;
}
.hero-subtitle {
font-size: 0.8125rem;
color: #5175b5;
line-height: 1.125rem;
}
.status-pill {
flex: 0 0 auto;
padding: 0.375rem 0.625rem;
border-radius: 31.21875rem;
background: #e6edfb;
color: #4463a6;
font-size: 0.75rem;
font-weight: 700;
border: 0.0625rem solid rgba(76, 141, 255, 0.2);
}
.status-pill.active {
background: #4c8dff;
color: #fff;
border-color: #4c8dff;
}
/* 指定 hero 内激活态徽标文本为黑色 */
.vip-hero .status-pill.active uni-text {
color: #000 !important;
}
.vip-summary {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5rem;
background: rgba(255, 255, 255, 0.98);
padding: 0.75rem;
border-radius: 0.75rem;
border: 0.0625rem solid #eef3fb;
box-shadow: 0 0.25rem 0.75rem rgba(99, 132, 191, 0.1);
}
.summary-item {
background: #f6f9ff;
border-radius: 0.5625rem;
padding: 0.6875rem 0.75rem;
display: flex;
flex-direction: column;
gap: 0.375rem;
border: 0.0625rem solid rgba(76, 141, 255, 0.12);
}
.summary-label {
font-size: 0.75rem;
color: #5f7394;
}
.summary-value {
font-size: 0.9375rem;
font-weight: 700;
color: #1f2c3d;
}
.summary-value.success {
color: #1ead91;
}
.summary-value.highlight {
color: #2f58d1;
}
.benefit-section {
background: rgba(255, 255, 255, 0.98);
border-radius: 0.75rem;
padding: 0.875rem;
border: 0.0625rem solid #edf2f9;
box-shadow: 0 0.375rem 0.875rem rgba(32, 75, 143, 0.1);
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.section-header {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.section-title {
font-size: 1.0625rem;
font-weight: 800;
color: #111;
}
.section-subtitle {
font-size: 0.75rem;
color: #5f7394;
line-height: 1.0625rem;
}
.benefit-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.625rem;
}
.benefit-card {
background: #f7faff;
border-radius: 0.625rem;
padding: 0.75rem 0.625rem;
border: 0.0625rem solid rgba(76, 141, 255, 0.12);
box-shadow: 0 0.25rem 0.625rem rgba(0, 0, 0, 0.04);
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.4375rem;
}
.benefit-icon {
width: 1.5rem;
height: 1.5rem;
}
.benefit-title {
font-size: 0.875rem;
font-weight: 700;
color: #111;
}
.benefit-desc {
font-size: 0.75rem;
line-height: 1.0625rem;
color: #5f7394;
}
.purchase-card {
margin-top: auto;
background: linear-gradient(135deg, rgba(76, 141, 255, 0.14) 0%, rgba(76, 141, 255, 0.06) 100%);
border-radius: 0.875rem;
padding: 0.9375rem 0.875rem;
display: flex;
align-items: center;
gap: 0.75rem;
border: 0.0625rem solid rgba(76, 141, 255, 0.18);
box-shadow: 0 0.3125rem 0.75rem rgba(76, 141, 255, 0.15);
}
.purchase-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.3125rem;
}
.purchase-title {
font-size: 1rem;
font-weight: 800;
color: #4C8DFF;
}
.purchase-desc {
font-size: 0.75rem;
color: #4463a6;
line-height: 1.0625rem;
}
.purchase-btn {
flex: 0 0 auto;
padding: 0.625rem 1.125rem;
border-radius: 31.21875rem;
border: none;
background: linear-gradient(135deg, #4788ff 0%, #2d6be6 100%);
color: #fff;
font-size: 0.875rem;
font-weight: 700;
box-shadow: 0 0.3125rem 0.6875rem rgba(45, 107, 230, 0.2);
}
.purchase-btn:active {
opacity: 0.88;
}
.apply-card {
margin-top: 0;
background: linear-gradient(135deg, rgba(30, 173, 145, 0.14) 0%, rgba(30, 173, 145, 0.06) 100%);
border-radius: 0.875rem;
padding: 0.9375rem 0.875rem;
display: flex;
align-items: center;
gap: 0.75rem;
border: 0.0625rem solid rgba(30, 173, 145, 0.18);
box-shadow: 0 0.3125rem 0.75rem rgba(30, 173, 145, 0.15);
}
.apply-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.3125rem;
}
.apply-title {
font-size: 1rem;
font-weight: 800;
color: #1ead91;
}
.apply-desc {
font-size: 0.75rem;
color: #247a66;
line-height: 1.0625rem;
}
.apply-btn {
flex: 0 0 auto;
padding: 0.625rem 1.125rem;
border-radius: 31.21875rem;
border: none;
background-color: transparent;
background: linear-gradient(135deg, #1ead91 0%, #159b7e 100%);
color: #fff;
font-size: 0.875rem;
font-weight: 700;
box-shadow: 0 0.3125rem 0.6875rem rgba(21, 155, 126, 0.2);
}
.apply-btn::after {
border: none;
}
.apply-btn:active {
opacity: 0.9;
}
.apply-btn.disabled {
opacity: 0.5;
background: #c7e8df;
color: #fff;
box-shadow: none;
pointer-events: none;
}
@media (max-width: 375px) {
.vip-summary {
grid-template-columns: 1fr;
}
.benefit-grid {
grid-template-columns: 1fr;
}
.purchase-card {
flex-direction: column;
align-items: stretch;
}
.status-pill {
display: none;
}
}

View File

@@ -1,59 +1,281 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.order {
padding-bottom: 4.375rem;
}
.tabs {
display: flex;
justify-content: space-around;
padding: 0.5rem 0.75rem;
}
.tabs uni-text {
color: #444;
}
.tabs uni-text.active {
color: #111;
font-weight: 700;
}
.order { padding-bottom: 4.375rem;
/* 三段式胶囊切换 */
.seg3 {
display: flex;
gap: 0;
margin: 0.375rem 0.5rem;
padding: 0.1875rem;
background: #fff;
border-radius: 31.21875rem;
box-shadow: 0 0.125rem 0.375rem rgba(0, 0, 0, 0.04);
}
.tabs { display: flex; justify-content: space-around; padding: 0.5rem 0.75rem;
.seg3-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 0.25rem;
padding: 0.375rem 0;
color: #111;
border-radius: 31.21875rem;
transition: box-shadow 0.2s ease, background 0.2s ease;
}
.tabs uni-text { color: #666;
/* 间隔通过内边距处理,避免空选择器 */
.seg3-item.active {
background: #fff;
color: #4C8DFF;
box-shadow: 0 0.09375rem 0.3125rem rgba(76, 141, 255, 0.16);
}
.tabs uni-text.active { color: #333; font-weight: 700;
.seg3-icon {
width: 0.875rem;
height: 0.875rem;
opacity: 0.9;
}
.subtabs { display: flex; gap: 0.5rem; padding: 0 0.75rem 0.5rem;
.field {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 0.6875rem 0.75rem;
background: #f8faff;
gap: 0.5rem;
}
.subbtn { padding: 0.3125rem 0.625rem; border-radius: 31.21875rem; background: #f4f4f4; color: #666;
.label {
width: 5rem;
color: #444;
}
.subbtn.active { background: #ffe69a; color: #3f320f;
.value {
flex: 1;
color: #111;
text-align: right;
}
.field { display:flex; justify-content: space-between; padding: 0.6875rem 0.75rem; background: #fff; border-bottom: 0.03125rem solid #eee;
/* 汇总卡片:白底卡片+主色按钮 */
.summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5625rem 0.625rem;
margin: 0.5rem 0.5625rem 0.3125rem;
background: none;
border-radius: 0.5625rem;
color: #111;
}
.label { color:#666;
/* 加号改为图标按钮 */
.add {
margin: 0.75rem auto 0.5625rem;
width: 3.75rem;
height: 3.75rem;
border-radius: 0.875rem;
background: none;
border: 0;
color: #4C8DFF;
font-size: 2.25rem;
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
}
.value { color:#333;
.empty {
display: flex;
flex-direction: column;
align-items: center;
padding: 1.875rem 0;
color: #444;
}
.summary { display:flex; justify-content: space-between; padding: 0.6875rem 0.75rem; color:#333;
.empty-img {
width: 5rem;
margin-bottom: 0.5rem;
}
.add { margin: 0.75rem auto; width: 3.75rem; height: 3.75rem; border-radius: 0.625rem; background: #c7eef7; color:#16a1c4; font-size: 2.25rem; display:flex; align-items:center; justify-content:center;
.empty-text {
margin-bottom: 0.25rem;
}
.empty { display:flex; flex-direction: column; align-items:center; padding: 1.875rem 0; color:#888;
.list {
background: #fff;
margin: 0 0.5625rem 0.625rem;
border-radius: 0.5625rem;
overflow: hidden;
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.06);
}
.empty-img { width: 6.875rem; margin-bottom: 0.625rem;
.row {
display: grid;
grid-template-columns: 1.5fr 1fr 1fr 1fr;
gap: 0.375rem;
padding: 0.5625rem 0.5rem;
align-items: center;
}
.empty-text { margin-bottom: 0.25rem;
.col.name {
padding-left: 0.375rem;
}
.list { background:#fff;
.col.amount {
text-align: right;
padding-right: 0.375rem;
color: #111;
}
.row { display:grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 0.375rem; padding: 0.5rem 0.375rem; align-items:center; border-bottom: 0.03125rem solid #f3f3f3;
.bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 0.1875rem 0.5625rem calc(env(safe-area-inset-bottom) + 0.0625rem);
box-shadow: 0 -0.125rem 0.375rem rgba(0, 0, 0, 0.16);
}
.col.name { padding-left: 0.375rem;
.order .bottom uni-button {
margin: 0;
}
.col.amount { text-align:right; padding-right: 0.375rem; color:#333;
/* 仅限开单页底部按钮样式(缩小高度) */
.order .bottom .primary {
width: 100%;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.4375rem 0;
font-weight: 700;
font-size: 0.875rem;
}
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem); box-shadow: 0 -0.125rem 0.375rem rgba(0,0,0,0.06);
.order .bottom .ghost {
background: transparent;
color: #4C8DFF;
border: 0;
border-radius: 31.21875rem;
padding: 0.375rem 0;
font-size: 0.875rem;
}
.primary { width: 100%; background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%); color:#493c1b; border-radius: 31.21875rem; padding: 0.625rem 0; font-weight:800;
/* 收款/付款页样式 */
.pay-row .pay-input {
text-align: right;
color: #111;
}
/* 收款/付款页样式 */
.pay-row .pay-input { text-align: right; color:#333;
.textarea {
position: relative;
padding: 0.5rem 0.75rem;
background: #f8faff;
}
.textarea { position: relative; padding: 0.5rem 0.75rem; background:#fff; border-top: 0.03125rem solid #eee;
.amount-badge {
position: absolute;
right: 0.75rem;
top: -1rem;
background: #4C8DFF;
color: #fff;
padding: 0.3125rem 0.625rem;
border-radius: 0.4375rem;
font-size: 0.75rem;
}
.amount-badge { position: absolute; right: 0.75rem; top: -1.125rem; background: #d1f0ff; color:#107e9b; padding: 0.25rem 0.5rem; border-radius: 0.375rem; font-size: 0.75rem;
.date-mini {
position: absolute;
right: 0.75rem;
bottom: 0.625rem;
color: #444;
font-size: 0.75rem;
}
.date-mini { position: absolute; right: 0.75rem; bottom: 0.625rem; color:#666; font-size: 0.75rem;
/* 分类chips样式选中后文字变红 */
.chips {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.375rem 0.5rem;
padding: 0.375rem 0.75rem;
}
/* 分类chips样式选中后文字变红 */
.chips { display:flex; flex-wrap: wrap; gap: 0.375rem; padding: 0.375rem 0.75rem;
.chip {
padding: 0.375rem 0.625rem;
border-radius: 31.21875rem;
background: #f1f1f1;
color: #444;
text-align: center;
}
.chip { padding: 0.3125rem 0.625rem; border-radius: 31.21875rem; background: #f4f4f4; color:#666;
.chip.active {
background: rgba(76, 141, 255, 0.15);
color: #4C8DFF;
}
.chip.active { color: #e54d42;
/* 顶部业务 Tabs 显示 */
/* 快捷操作宫格 */
/* 信息卡片式表达(更稳重) */
.info-card {
display: grid;
grid-template-columns: 1fr 1fr auto;
gap: 0.3125rem;
margin: 0.3125rem 0.375rem 0;
background: transparent;
padding: 0;
align-items: center;
}
.info-field {
background: #fff;
border: 0;
border-radius: 0.4375rem;
padding: 0.375rem 0.4375rem;
box-shadow: 0 0.1875rem 0.5rem rgba(0, 0, 0, 0.06);
}
.info-label {
color: #444;
font-size: 0.75rem;
margin-right: 0.25rem;
}
.info-value {
color: #111;
font-weight: 700;
}
/* 缩小“加商品”按钮尺寸,仅在本页卡片内 */
.order .info-card .info-action {
display: flex;
align-items: center;
gap: 0.1875rem;
background: #4C8DFF;
color: #fff;
border-radius: 0.375rem;
padding: 0.25rem 0.375rem;
box-shadow: 0 0.15625rem 0.375rem rgba(76, 141, 255, 0.18);
font-size: 0.8125rem;
}
.order .info-card .info-icon {
width: 0.75rem;
height: 0.75rem;
}

View File

@@ -9,25 +9,169 @@
}
.thumb[data-v-7bd1ddd2] { width: 100%; height: 100%;
}
.remove[data-v-7bd1ddd2] { position: absolute; right: 0.1875rem; top: 0.1875rem; background: rgba(0,0,0,0.45); color: #fff; width: 1.25rem; height: 1.25rem; text-align: center; line-height: 1.25rem; border-radius: 0.625rem; font-size: 0.875rem;
.remove[data-v-7bd1ddd2] { position: absolute; right: 0.1875rem; top: 0.1875rem; width: 1.3125rem; height: 1.3125rem;
}
.adder[data-v-7bd1ddd2] { width: 6.5625rem; height: 6.5625rem; border: 0.0625rem dashed #ccc; border-radius: 0.375rem; display: flex; align-items: center; justify-content: center; color: #999; position: absolute; left: 0; top: 0;
}
.page { background:#f6f6f6; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
background: #ffffff;
min-height: 100vh;
padding-bottom: 5rem;
box-sizing: border-box;
}
.card { background:#fff; margin: 0.5rem; padding: 0.5rem; border-radius: 0.375rem;
.hero.small {
margin: 0.6875rem 0.75rem 0.375rem;
padding: 0 0.125rem 0.5625rem;
color: #111;
border-bottom: 0.0625rem solid rgba(94, 124, 174, 0.12);
}
.row { display:flex; gap: 0.375rem; align-items: center; margin-bottom: 0.375rem;
.hero.small .title {
font-size: 1.0625rem;
font-weight: 800;
}
.label { width: 5.625rem; color:#666;
.hero.small .sub {
display: block;
margin-top: 0.1875rem;
color: #444;
font-size: 0.75rem;
}
.row uni-input { flex:1; background:#f7f7f7; border-radius: 0.3125rem; padding: 0.375rem;
.section {
margin: 0 0.75rem 0.875rem;
padding-bottom: 0.1875rem;
border-bottom: 0.0625rem solid rgba(94, 124, 174, 0.1);
}
.picker { padding: 0.25rem 0.375rem; background:#f0f0f0; border-radius: 0.3125rem; color:#666; margin-left: 0.25rem;
.section:last-of-type {
border-bottom: 0;
margin-bottom: 0;
}
.prices uni-input { width: 30%;
.section .row:first-child .label {
font-weight: 700;
color: #111;
}
.fixed { position: fixed; left: 0; right: 0; bottom: 0; background:#fff; padding: 0.375rem 0.5rem; display:flex; gap: 0.5rem;
.row {
display: flex;
gap: 0.25rem;
align-items: center;
margin-top: 0.5625rem;
}
.row .input-long {
flex: 1.2;
}
.row:first-child {
margin-top: 0;
}
.label {
width: 4.6875rem;
color: #444;
font-size: 0.8125rem;
}
.row uni-input {
flex: 1;
background: #f7f9fc;
border-radius: 0.4375rem;
padding: 0.5625rem 0.625rem;
color: #111;
border: 0;
box-shadow: inset 0 0 0 0.0625rem rgba(134, 155, 191, 0.06);
}
.picker-btn {
background: #ffffff;
border: 0.0625rem solid rgba(76, 141, 255, 0.45);
color: #4C8DFF;
padding: 0 0.75rem;
border-radius: 31.21875rem;
font-size: 0.75rem;
}
.picker {
padding: 0.5rem 0.6875rem;
background: #f7f9fc;
border-radius: 0.4375rem;
color: #444;
margin-left: 0.25rem;
border: 0;
box-shadow: inset 0 0 0 0.0625rem rgba(134, 155, 191, 0.06);
}
.prices uni-input {
width: 30%;
}
.section uni-textarea {
width: 100%;
min-height: 5rem;
background: #f7f9fc;
border-radius: 0.4375rem;
padding: 0.625rem 0.6875rem;
box-sizing: border-box;
color: #111;
border: 0;
box-shadow: inset 0 0 0 0.0625rem rgba(134, 155, 191, 0.06);
}
.fixed {
position: fixed;
left: 0;
right: 0;
bottom: env(safe-area-inset-bottom);
background: #ffffff;
padding: 0.5rem 0.5rem calc(0.5rem + constant(safe-area-inset-bottom)) 0.5rem;
display: flex;
gap: 0.5rem;
box-shadow: 0 -0.1875rem 0.5625rem rgba(24, 55, 105, 0.08);
z-index: 999;
}
.fixed .primary {
flex: 1;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.5625rem 0;
font-weight: 700;
}
.fixed .ghost {
flex: 1;
background: #ffffff;
color: #4C8DFF;
border: 0.0625rem solid rgba(76, 141, 255, 0.45);
border-radius: 31.21875rem;
padding: 0.5625rem 0;
}
.tip {
margin: 0 0.9375rem 0.625rem;
padding: 0.5rem 0.625rem;
border-radius: 0.5rem;
font-size: 0.75rem;
}
.tip.platform {
background: rgba(45, 140, 240, 0.12);
color: #2d8cf0;
}
.tip.custom {
background: rgba(103, 194, 58, 0.12);
color: #67c23a;
}

View File

@@ -1,33 +1,163 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.tabs { display:flex; background:#fff;
.tabs {
display: flex;
background: #ffffff;
}
.tab { flex:1; text-align:center; padding: 0.625rem 0; color:#666;
.tab {
flex: 1;
text-align: center;
padding: 0.625rem 0;
color: #444;
}
.tab.active { color:#18b566; font-weight: 600;
.tab.active {
color: #4C8DFF;
font-weight: 600;
}
.search { display:flex; gap: 0.375rem; padding: 0.5rem; background:#fff; align-items: center;
.tab.extra {
flex: 0 0 5.625rem;
color: #4C8DFF;
font-weight: 600;
}
.search uni-input { flex:1; background:#f6f6f6; border-radius: 0.375rem; padding: 0.375rem;
.search {
display: flex;
gap: 0.375rem;
padding: 0.5rem;
background: #ffffff;
align-items: center;
}
.picker { padding: 0.25rem 0.375rem; background:#f0f0f0; border-radius: 0.3125rem; color:#666;
.search uni-input {
flex: 1;
background: #f1f1f1;
border-radius: 0.375rem;
padding: 0.375rem;
color: #111;
}
.list { flex:1;
.picker {
padding: 0.25rem 0.375rem;
background: #f1f1f1;
border-radius: 0.3125rem;
color: #444;
}
.item { display:flex; padding: 0.625rem; background:#fff; border-bottom: 0.03125rem solid #f1f1f1;
.template-mode {
flex-direction: column;
align-items: stretch;
gap: 0.25rem;
}
.thumb { width: 3.75rem; height: 3.75rem; border-radius: 0.375rem; margin-right: 0.5rem; background:#fafafa;
.picker-row {
display: flex;
gap: 0.375rem;
}
.content { flex:1;
.params-wrap {
margin-top: 0.1875rem;
background: #ffffff;
border-radius: 0.375rem;
padding: 0.25rem 0.25rem;
}
.name { color:#333; margin-bottom: 0.1875rem; font-weight: 600;
.list {
flex: 1;
}
.meta { color:#888; font-size: 0.75rem;
.item {
display: flex;
padding: 0.625rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.price { margin-left: 0.625rem; color:#f60;
.thumb {
width: 3.75rem;
height: 3.75rem;
border-radius: 0.375rem;
margin-right: 0.5rem;
background: #f1f1f1;
}
.empty { height: 60vh; display:flex; align-items:center; justify-content:center; color:#999;
.content {
flex: 1;
}
.fab { position: fixed; right: 0.9375rem; bottom: 3.75rem; width: 3.125rem; height: 3.125rem; background:#18b566; color:#fff; border-radius: 1.5625rem; text-align:center; line-height: 3.125rem; font-size: 1.5rem; box-shadow: 0 0.25rem 0.625rem rgba(0,0,0,0.15);
.name {
color: #111;
margin-bottom: 0.1875rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.375rem;
}
.tag-platform {
font-size: 0.6875rem;
color: #fff;
background: #2d8cf0;
padding: 0.125rem 0.3125rem;
border-radius: 0.25rem;
}
.tag-custom {
font-size: 0.6875rem;
color: #fff;
background: #67c23a;
padding: 0.125rem 0.3125rem;
border-radius: 0.25rem;
}
.tag-deleted {
font-size: 0.6875rem;
color: #fff;
background: #909399;
padding: 0.125rem 0.3125rem;
border-radius: 0.25rem;
}
.meta {
color: #444;
font-size: 0.75rem;
}
.price {
margin-left: 0.625rem;
color: #4C8DFF;
}
.empty {
height: 60vh;
display: flex;
align-items: center;
justify-content: center;
color: #444;
}
.fab {
position: fixed;
right: 0.9375rem;
bottom: 3.75rem;
width: 3.125rem;
height: 3.125rem;
background: #4C8DFF;
color: #fff;
border-radius: 1.5625rem;
text-align: center;
line-height: 3.125rem;
font-size: 1.5rem;
box-shadow: 0 0.25rem 0.625rem rgba(0, 0, 0, 0.15);
}

View File

@@ -0,0 +1,124 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding: 0.75rem 0.75rem 5rem;
background: #f6f7fb;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.625rem;
}
.model {
font-size: 1.125rem;
font-weight: 700;
color: #2d3a4a;
}
.status.deleted {
font-size: 0.75rem;
padding: 0.1875rem 0.5625rem;
border-radius: 31.21875rem;
background: #c0c4cc;
color: #fff;
}
.section {
background: #fff;
border-radius: 0.5rem;
padding: 0.625rem 0.6875rem;
margin-bottom: 0.75rem;
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.04);
}
.row {
display: flex;
justify-content: space-between;
padding: 0.375rem 0;
border-bottom: 0.03125rem solid #f1f2f5;
}
.row:last-child {
border-bottom: none;
}
.label {
width: 5rem;
font-size: 0.8125rem;
color: #7a8899;
}
.value {
flex: 1;
text-align: right;
font-size: 0.8125rem;
color: #2d3a4a;
word-break: break-all;
}
.block-title {
font-size: 0.875rem;
font-weight: 600;
color: #2d3a4a;
margin-bottom: 0.375rem;
}
.placeholder {
font-size: 0.8125rem;
color: #7a8899;
}
.params {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.param {
display: flex;
justify-content: space-between;
font-size: 0.8125rem;
color: #2d3a4a;
}
.param-key {
color: #7a8899;
}
.images {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.375rem;
}
.image {
width: 100%;
height: 6.25rem;
border-radius: 0.5rem;
background: #f0f2f5;
}
.footer {
display: flex;
justify-content: flex-end;
gap: 0.625rem;
}
.loading {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: #7a8899;
}

View File

@@ -1,15 +1,61 @@
.page { display:flex; flex-direction: column; height: 100vh;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.search { display:flex; gap: 0.375rem; padding: 0.5rem; background:#fff;
.search {
display: flex;
gap: 0.375rem;
padding: 0.5rem;
background: #ffffff;
}
.search uni-input { flex:1; background:#f6f6f6; border-radius: 0.375rem; padding: 0.375rem;
.search uni-input {
flex: 1;
background: #f1f1f1;
border-radius: 0.375rem;
padding: 0.375rem;
color: #111;
}
.list { flex:1;
.list {
flex: 1;
}
.item { padding: 0.625rem 0.75rem; background:#fff; border-bottom: 0.03125rem solid #f1f1f1;
.item {
padding: 0.625rem 0.75rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.name { color:#333; margin-bottom: 0.1875rem;
}
.meta { color:#888; font-size: 0.75rem;
.name {
color: #111;
margin-bottom: 0.1875rem;
}
.meta {
color: #444;
font-size: 0.75rem;
}

View File

@@ -0,0 +1,134 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding: 0.75rem 0.75rem 5rem;
background: #f6f7fb;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.625rem;
}
.model {
font-size: 1.125rem;
font-weight: 700;
color: #2d3a4a;
}
.status {
font-size: 0.8125rem;
padding: 0.1875rem 0.5625rem;
border-radius: 31.21875rem;
}
.status.pending {
background: rgba(246, 190, 0, 0.15);
color: #c47f00;
}
.status.approved {
background: rgba(103, 194, 58, 0.15);
color: #409eff;
}
.status.rejected {
background: rgba(255, 87, 115, 0.18);
color: #f56c6c;
}
.section {
background: #fff;
border-radius: 0.5rem;
padding: 0.625rem 0.6875rem;
margin-bottom: 0.75rem;
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.04);
}
.row {
display: flex;
justify-content: space-between;
padding: 0.375rem 0;
border-bottom: 0.03125rem solid #f1f2f5;
}
.row:last-child {
border-bottom: none;
}
.label {
width: 5rem;
font-size: 0.8125rem;
color: #7a8899;
}
.value {
flex: 1;
text-align: right;
font-size: 0.8125rem;
color: #2d3a4a;
word-break: break-all;
}
.block-title {
font-size: 0.875rem;
font-weight: 600;
color: #2d3a4a;
margin-bottom: 0.375rem;
}
.placeholder {
font-size: 0.8125rem;
color: #7a8899;
}
.params {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.param {
display: flex;
justify-content: space-between;
font-size: 0.8125rem;
color: #2d3a4a;
}
.param-key {
color: #7a8899;
}
.images {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.375rem;
}
.image {
width: 100%;
height: 6.25rem;
border-radius: 0.5rem;
background: #f0f2f5;
}
.footer {
display: flex;
justify-content: flex-end;
gap: 0.625rem;
}
.loading {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: #7a8899;
}

View File

@@ -0,0 +1,164 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;
height: 100vh;
background: #f6f7fb;
padding-bottom: 4.375rem;
}
.hero {
padding: 0.75rem;
background: #fff;
box-shadow: 0 0.3125rem 0.9375rem rgba(0, 0, 0, 0.04);
}
.title {
font-size: 1.0625rem;
font-weight: 700;
color: #2d3a4a;
}
.desc {
font-size: 0.75rem;
color: #7a8899;
margin-top: 0.25rem;
}
.tabs {
display: flex;
background: #fff;
margin: 0.5rem;
border-radius: 31.21875rem;
overflow: hidden;
box-shadow: inset 0 0 0 0.03125rem rgba(76, 141, 255, 0.1);
}
.tab {
flex: 1;
text-align: center;
padding: 0.625rem 0;
font-size: 0.875rem;
color: #7a8899;
}
.tab.active {
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
color: #fff;
font-weight: 600;
}
.list {
flex: 1;
padding: 0 0.625rem;
}
.cards {
display: flex;
flex-direction: column;
gap: 0.625rem;
padding-bottom: 1.25rem;
}
.card {
background: #fff;
border-radius: 0.5625rem;
padding: 0.6875rem;
box-shadow: 0 0.3125rem 0.9375rem rgba(0, 0, 0, 0.05);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.375rem;
}
.model {
font-size: 0.9375rem;
font-weight: 700;
color: #2d3a4a;
}
.status {
font-size: 0.75rem;
padding: 0.1875rem 0.5625rem;
border-radius: 31.21875rem;
}
.status.pending {
background: rgba(246, 190, 0, 0.15);
color: #c47f00;
}
.status.approved {
background: rgba(103, 194, 58, 0.15);
color: #409eff;
}
.status.rejected {
background: rgba(255, 87, 115, 0.18);
color: #f56c6c;
}
.card-body {
display: flex;
flex-direction: column;
gap: 0.1875rem;
color: #4f5969;
font-size: 0.8125rem;
}
.name {
font-weight: 600;
color: #2d3a4a;
}
.card-footer {
display: flex;
gap: 0.375rem;
margin-top: 0.5rem;
}
.empty {
height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #8894a3;
gap: 0.625rem;
}
.empty .primary {
background: #4c8dff;
color: #fff;
border-radius: 31.21875rem;
padding: 0.375rem 0.9375rem;
}
.loading, .finished {
text-align: center;
padding: 0.625rem 0;
color: #7a8899;
}
.fab {
position: fixed;
right: 0.9375rem;
bottom: 3.75rem;
width: 3.125rem;
height: 3.125rem;
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
color: #fff;
border-radius: 1.5625rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
box-shadow: 0 0.625rem 1.25rem rgba(0, 0, 0, 0.2);
}

View File

@@ -0,0 +1,142 @@
.uploader[data-v-7bd1ddd2] { padding: 0.375rem; background: #fff;
}
.grid[data-v-7bd1ddd2] { position: relative;
}
.area[data-v-7bd1ddd2] { width: 100%; position: relative;
}
.cell[data-v-7bd1ddd2] { position: absolute; border-radius: 0.375rem; overflow: hidden; box-shadow: 0 0 0.03125rem rgba(0,0,0,0.08);
}
.thumb[data-v-7bd1ddd2] { width: 100%; height: 100%;
}
.remove[data-v-7bd1ddd2] { position: absolute; right: 0.1875rem; top: 0.1875rem; width: 1.3125rem; height: 1.3125rem;
}
.adder[data-v-7bd1ddd2] { width: 6.5625rem; height: 6.5625rem; border: 0.0625rem dashed #ccc; border-radius: 0.375rem; display: flex; align-items: center; justify-content: center; color: #999; position: absolute; left: 0; top: 0;
}
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding: 0.75rem 0.75rem 3.75rem;
background: #f6f7fb;
}
.hero {
padding: 0.75rem;
background: linear-gradient(135deg, #4c8dff, #6ab7ff);
border-radius: 0.625rem;
color: #fff;
margin-bottom: 0.75rem;
}
.title {
font-size: 1.125rem;
font-weight: 700;
}
.desc {
font-size: 0.8125rem;
margin-top: 0.25rem;
opacity: 0.9;
}
.section {
background: #fff;
border-radius: 0.5rem;
padding: 0.625rem 0.6875rem;
margin-bottom: 0.75rem;
box-shadow: 0 0.3125rem 0.9375rem rgba(0, 0, 0, 0.04);
}
.row {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0;
border-bottom: 0.03125rem solid #f1f2f5;
}
.row:last-child {
border-bottom: none;
}
.row.required .label::after {
content: "*";
color: #ff5b5b;
margin-left: 0.1875rem;
}
.label {
width: 4.0625rem;
font-size: 0.875rem;
color: #2d3a4a;
}
uni-input {
flex: 1;
background: #f8f9fb;
border-radius: 0.375rem;
padding: 0.5rem 0.5625rem;
font-size: 0.875rem;
color: #222;
}
.textarea {
width: 100%;
min-height: 5rem;
background: #f8f9fb;
border-radius: 0.375rem;
padding: 0.5625rem;
font-size: 0.875rem;
color: #222;
}
.picker {
flex: 1;
background: #f8f9fb;
border-radius: 0.375rem;
padding: 0.5625rem;
font-size: 0.875rem;
color: #222;
}
.picker-btn {
background: #4c8dff;
color: #fff;
border-radius: 31.21875rem;
padding: 0.3125rem 0.6875rem;
}
.triple uni-input {
flex: 1;
}
.fixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 0.625rem 0.75rem 1.25rem;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 -0.1875rem 0.625rem rgba(0, 0, 0, 0.08);
}
.primary {
width: 100%;
height: 2.75rem;
border-radius: 31.21875rem;
background: #4c8dff;
color: #fff;
font-size: 1rem;
font-weight: 600;
}

View File

@@ -1,37 +1,158 @@
.report { padding: 0.625rem;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.report {
padding: 0.75rem 0.625rem 1.125rem;
display: flex;
flex-direction: column;
gap: 0.5625rem;
}
.modes { display: flex; gap: 0.375rem; margin-bottom: 0.4375rem;
.header {
font-size: 1.0625rem;
font-weight: 700;
color: #1f2a44;
padding-left: 0.25rem;
}
.mode-tab { flex: 1; text-align: center; padding: 0.5rem 0; border-radius: 31.21875rem; background: #f4f4f4; color: #666; border: 0.03125rem solid #e9e9e9;
.toolbar {
display: flex;
align-items: center;
justify-content: center;
gap: 0.375rem;
background: #f7f9fc;
border-radius: 0.5rem;
padding: 0.5625rem;
}
.mode-tab.active { background: #1aad19; color: #fff; border-color: #1aad19; font-weight: 700;
.date {
min-width: 6.25rem;
padding: 0.375rem 0.5625rem;
border-radius: 0.375rem;
background: #fff;
border: 0.03125rem solid rgba(91, 107, 139, 0.16);
text-align: center;
color: #32445b;
}
.toolbar { display: flex; align-items: center; gap: 0.25rem; background: #fff; padding: 0.4375rem 0.5rem; border-radius: 0.375rem;
.tabs {
display: flex;
gap: 0.375rem;
justify-content: center;
}
.date { padding: 0.3125rem 0.5rem; border: 0.03125rem solid #eee; border-radius: 0.25rem;
.tab {
padding: 0.3125rem 0.625rem;
border-radius: 31.21875rem;
background: #f0f4ff;
color: #5b6b8b;
transition: all 0.2s ease;
}
.tabs { display: flex; gap: 0.5rem; margin-top: 0.4375rem;
.tab.active {
background: rgba(76, 141, 255, 0.18);
color: #3467d6;
box-shadow: inset 0 0 0 0.0625rem rgba(76, 141, 255, 0.45);
}
.tab { padding: 0.375rem 0.5625rem; border-radius: 31.21875rem; background: #f4f4f4; color: #666;
.summary {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
gap: 0.375rem;
}
.tab.active { background: #1aad19; color: #fff;
.summary-item {
background: #f7f9fc;
border-radius: 0.5rem;
padding: 0.625rem;
display: flex;
flex-direction: column;
gap: 0.3125rem;
}
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.25rem; margin-top: 0.4375rem;
.summary-item .label {
font-size: 0.75rem;
color: #6e7a96;
}
.summary .item { background: #fff; border-radius: 0.375rem; padding: 0.5rem;
.summary-item .value {
font-size: 1rem;
font-weight: 700;
color: #1f2a44;
}
.summary .label { font-size: 0.6875rem; color: #888;
.card {
background: #fff;
border-radius: 0.5625rem;
padding: 0.625rem;
box-shadow: 0 0.25rem 0.625rem rgba(31, 42, 68, 0.08);
display: flex;
flex-direction: column;
gap: 0.4375rem;
}
.summary .value { display: block; margin-top: 0.25rem; font-weight: 700; color: #333;
.row-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.card { margin-top: 0.5rem; background: #fff; border-radius: 0.375rem; padding: 0.5rem;
.row-title {
display: flex;
flex-direction: column;
gap: 0.1875rem;
}
.row-head { display: flex; align-items: center; gap: 0.375rem;
.title {
font-size: 0.9375rem;
font-weight: 700;
color: #1f2a44;
}
.thumb { width: 2.25rem; height: 2.25rem; border-radius: 0.25rem; background: #f2f2f2;
.subtitle {
font-size: 0.75rem;
color: #6e7a96;
}
.title { font-size: 0.875rem; font-weight: 700;
.row-body {
display: flex;
flex-wrap: wrap;
gap: 0.375rem 0.75rem;
}
.row-body { margin-top: 0.3125rem; color: #666;
.metric {
display: flex;
gap: 0.25rem;
align-items: center;
background: #f4f6fb;
border-radius: 0.375rem;
padding: 0.3125rem 0.5rem;
}
.metric-label {
font-size: 0.75rem;
color: #6e7a96;
}
.metric-value {
font-size: 0.875rem;
color: #1f2a44;
font-weight: 600;
}
.empty {
text-align: center;
padding: 2.5rem 0;
color: #9aa4be;
font-size: 0.8125rem;
}
.loading {
text-align: center;
padding: 1.25rem 0;
color: #5b6b8b;
font-size: 0.75rem;
}

View File

@@ -1,15 +1,66 @@
.page { padding-bottom: 4.375rem;
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding-bottom: 4.375rem;
}
.field { display:flex; justify-content: space-between; padding: 0.6875rem 0.75rem; background:#fff; border-bottom:0.03125rem solid #eee;
.field {
display: flex;
justify-content: space-between;
padding: 0.6875rem 0.75rem;
background: #ffffff;
border-bottom: 0.03125rem solid #e5e7eb;
}
.label { color:#666;
.label {
color: #444;
}
.value { color:#333; text-align: right; flex: 1;
.value {
color: #111;
text-align: right;
flex: 1;
}
.textarea { padding: 0.5rem 0.75rem; background:#fff; margin-top: 0.375rem;
.textarea {
padding: 0.5rem 0.75rem;
background: #ffffff;
margin-top: 0.375rem;
}
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem); box-shadow: 0 -0.125rem 0.375rem rgba(0,0,0,0.06);
}
.primary { width: 100%; background: linear-gradient(135deg, #A0E4FF 0%, #17A2C4 100%); color:#fff; border-radius: 31.21875rem; padding: 0.625rem 0;
.bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 0.5rem 0.75rem calc(env(safe-area-inset-bottom) + 0.5rem);
box-shadow: 0 -0.125rem 0.375rem rgba(0, 0, 0, 0.1);
}
.primary {
width: 100%;
background: #4C8DFF;
color: #fff;
border-radius: 31.21875rem;
padding: 0.625rem 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,9 @@ if (!Math) {
"./pages/product/list.js";
"./pages/product/submit.js";
"./pages/product/submissions.js";
"./pages/product/submission-detail.js";
"./pages/product/form.js";
"./pages/product/product-detail.js";
"./pages/product/categories.js";
"./pages/product/units.js";
"./pages/product/settings.js";

View File

@@ -6,7 +6,9 @@
"pages/product/list",
"pages/product/submit",
"pages/product/submissions",
"pages/product/submission-detail",
"pages/product/form",
"pages/product/product-detail",
"pages/product/categories",
"pages/product/units",
"pages/product/settings",

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
/*每个页面公共css */
page {
background-color: #ffffff;

View File

@@ -25,8 +25,12 @@ const KPI_ICONS = {
monthProfit: "/static/icons/icons8-profit-50.png",
stockCount: "/static/icons/product.png"
};
const envAuthLoginImg = typeof process !== "undefined" && process.env && (process.env.VITE_APP_AUTH_LOGIN_TOP_IMAGE || process.env.AUTH_LOGIN_TOP_IMAGE) || "";
const storageAuthLoginImg = typeof common_vendor.index !== "undefined" ? common_vendor.index.getStorageSync("AUTH_LOGIN_TOP_IMAGE") || "" : "";
const AUTH_LOGIN_TOP_IMAGE = String(envAuthLoginImg || storageAuthLoginImg || "/static/icons/undraw_visual-data_1eya.png");
exports.API_BASE_URL = API_BASE_URL;
exports.API_BASE_URL_CANDIDATES = API_BASE_URL_CANDIDATES;
exports.AUTH_LOGIN_TOP_IMAGE = AUTH_LOGIN_TOP_IMAGE;
exports.DEFAULT_USER_ID = DEFAULT_USER_ID;
exports.ENABLE_DEFAULT_USER = ENABLE_DEFAULT_USER;
exports.KPI_ICONS = KPI_ICONS;

View File

@@ -29,7 +29,14 @@ const ROUTES = {
supplierSelect: "/pages/supplier/select",
accountSelect: "/pages/account/select"
};
const KPI_LABELS = {
todaySales: "今日销售额",
monthSales: "本月销售额",
monthProfit: "本月利润",
stockCount: "库存量"
};
exports.EXPENSE_CATEGORIES = EXPENSE_CATEGORIES;
exports.INCOME_CATEGORIES = INCOME_CATEGORIES;
exports.KPI_LABELS = KPI_LABELS;
exports.ROUTES = ROUTES;
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/constants.js.map

View File

@@ -7074,7 +7074,7 @@ function isConsoleWritable() {
function initRuntimeSocketService() {
const hosts = "198.18.0.1,192.168.31.192,127.0.0.1";
const port = "8090";
const id = "mp-weixin_t4IBTG";
const id = "mp-weixin_kiZSAl";
const lazy = typeof swan !== "undefined";
let restoreError = lazy ? () => {
} : initOnError();

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
display: flex;
flex-direction: column;

View File

@@ -1,11 +1,13 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_http = require("../../common/http.js");
const common_config = require("../../common/config.js");
const _sfc_main = {
data() {
return {
loading: false,
tab: "login",
authLoginTopImage: common_config.AUTH_LOGIN_TOP_IMAGE,
loginForm: { email: "", password: "" },
regForm: { name: "", email: "", code: "", password: "", password2: "" },
resetForm: { email: "", code: "", password: "", password2: "" },
@@ -18,6 +20,12 @@ const _sfc_main = {
this._timers.forEach((t) => clearInterval(t));
},
methods: {
gotoRegister() {
this.tab = "register";
},
gotoReset() {
this.tab = "reset";
},
toast(msg) {
try {
common_vendor.index.showToast({ title: String(msg || "操作失败"), icon: "none" });
@@ -154,65 +162,64 @@ const _sfc_main = {
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return common_vendor.e({
a: common_vendor.n($data.tab === "login" ? "active" : ""),
b: common_vendor.o(($event) => $data.tab = "login"),
c: common_vendor.n($data.tab === "register" ? "active" : ""),
d: common_vendor.o(($event) => $data.tab = "register"),
e: common_vendor.n($data.tab === "reset" ? "active" : ""),
f: common_vendor.o(($event) => $data.tab = "reset"),
g: $data.tab === "login"
a: $data.authLoginTopImage,
b: $data.tab === "login"
}, $data.tab === "login" ? {
h: $data.loginForm.email,
i: common_vendor.o(common_vendor.m(($event) => $data.loginForm.email = $event.detail.value, {
c: $data.loginForm.email,
d: common_vendor.o(common_vendor.m(($event) => $data.loginForm.email = $event.detail.value, {
trim: true
})),
j: $data.loginForm.password,
k: common_vendor.o(($event) => $data.loginForm.password = $event.detail.value),
l: $data.loading,
m: common_vendor.o((...args) => $options.onLogin && $options.onLogin(...args))
} : $data.tab === "register" ? {
o: $data.regForm.name,
p: common_vendor.o(common_vendor.m(($event) => $data.regForm.name = $event.detail.value, {
e: $data.loginForm.password,
f: common_vendor.o(($event) => $data.loginForm.password = $event.detail.value),
g: $data.loading,
h: common_vendor.o((...args) => $options.onLogin && $options.onLogin(...args)),
i: common_vendor.o((...args) => $options.gotoRegister && $options.gotoRegister(...args)),
j: common_vendor.o((...args) => $options.gotoReset && $options.gotoReset(...args))
} : {}, {
k: $data.tab === "register"
}, $data.tab === "register" ? {
l: $data.regForm.name,
m: common_vendor.o(common_vendor.m(($event) => $data.regForm.name = $event.detail.value, {
trim: true
})),
q: $data.regForm.email,
r: common_vendor.o(common_vendor.m(($event) => $data.regForm.email = $event.detail.value, {
n: $data.regForm.email,
o: common_vendor.o(common_vendor.m(($event) => $data.regForm.email = $event.detail.value, {
trim: true
})),
s: $data.regForm.code,
t: common_vendor.o(common_vendor.m(($event) => $data.regForm.code = $event.detail.value, {
p: $data.regForm.code,
q: common_vendor.o(common_vendor.m(($event) => $data.regForm.code = $event.detail.value, {
trim: true
})),
v: common_vendor.t($data.regCountdown > 0 ? $data.regCountdown + "s" : "获取验证码"),
w: $data.regCountdown > 0 || $data.loading,
x: common_vendor.o((...args) => $options.sendRegCode && $options.sendRegCode(...args)),
y: $data.regForm.password,
z: common_vendor.o(($event) => $data.regForm.password = $event.detail.value),
A: $data.regForm.password2,
B: common_vendor.o(($event) => $data.regForm.password2 = $event.detail.value),
C: $data.loading,
D: common_vendor.o((...args) => $options.onRegister && $options.onRegister(...args))
} : {
E: $data.resetForm.email,
F: common_vendor.o(common_vendor.m(($event) => $data.resetForm.email = $event.detail.value, {
r: common_vendor.t($data.regCountdown > 0 ? $data.regCountdown + "s" : "获取验证码"),
s: $data.regCountdown > 0 || $data.loading,
t: common_vendor.o((...args) => $options.sendRegCode && $options.sendRegCode(...args)),
v: $data.regForm.password,
w: common_vendor.o(($event) => $data.regForm.password = $event.detail.value),
x: $data.regForm.password2,
y: common_vendor.o(($event) => $data.regForm.password2 = $event.detail.value),
z: $data.loading,
A: common_vendor.o((...args) => $options.onRegister && $options.onRegister(...args))
} : {}, {
B: $data.tab === "reset"
}, $data.tab === "reset" ? {
C: $data.resetForm.email,
D: common_vendor.o(common_vendor.m(($event) => $data.resetForm.email = $event.detail.value, {
trim: true
})),
G: $data.resetForm.code,
H: common_vendor.o(common_vendor.m(($event) => $data.resetForm.code = $event.detail.value, {
E: $data.resetForm.code,
F: common_vendor.o(common_vendor.m(($event) => $data.resetForm.code = $event.detail.value, {
trim: true
})),
I: common_vendor.t($data.resetCountdown > 0 ? $data.resetCountdown + "s" : "获取验证码"),
J: $data.resetCountdown > 0 || $data.loading,
K: common_vendor.o((...args) => $options.sendResetCode && $options.sendResetCode(...args)),
L: $data.resetForm.password,
M: common_vendor.o(($event) => $data.resetForm.password = $event.detail.value),
N: $data.resetForm.password2,
O: common_vendor.o(($event) => $data.resetForm.password2 = $event.detail.value),
P: $data.loading,
Q: common_vendor.o((...args) => $options.onReset && $options.onReset(...args))
}, {
n: $data.tab === "register"
});
G: common_vendor.t($data.resetCountdown > 0 ? $data.resetCountdown + "s" : "获取验证码"),
H: $data.resetCountdown > 0 || $data.loading,
I: common_vendor.o((...args) => $options.sendResetCode && $options.sendResetCode(...args)),
J: $data.resetForm.password,
K: common_vendor.o(($event) => $data.resetForm.password = $event.detail.value),
L: $data.resetForm.password2,
M: common_vendor.o(($event) => $data.resetForm.password2 = $event.detail.value),
N: $data.loading,
O: common_vendor.o((...args) => $options.onReset && $options.onReset(...args))
} : {});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createPage(MiniProgramPage);

View File

@@ -1 +1 @@
<view class="auth-page"><view class="tabs"><view class="{{['tab', a]}}" bindtap="{{b}}">登录</view><view class="{{['tab', c]}}" bindtap="{{d}}">注册</view><view class="{{['tab', e]}}" bindtap="{{f}}">忘记密码</view></view><view wx:if="{{g}}" class="panel"><input class="input" type="text" placeholder="输入邮箱" value="{{h}}" bindinput="{{i}}"/><input class="input" type="password" placeholder="输入密码" value="{{j}}" bindinput="{{k}}"/><button class="btn primary" disabled="{{l}}" bindtap="{{m}}">登录</button></view><view wx:elif="{{n}}" class="panel"><input class="input" type="text" placeholder="输入用户名" value="{{o}}" bindinput="{{p}}"/><input class="input" type="text" placeholder="输入邮箱" value="{{q}}" bindinput="{{r}}"/><view class="row"><input class="input flex1" type="text" placeholder="邮箱验证码" value="{{s}}" bindinput="{{t}}"/><button class="btn ghost" disabled="{{w}}" bindtap="{{x}}">{{v}}</button></view><input class="input" type="password" placeholder="输入密码(≥6位)" value="{{y}}" bindinput="{{z}}"/><input class="input" type="password" placeholder="再次输入密码" value="{{A}}" bindinput="{{B}}"/><button class="btn primary" disabled="{{C}}" bindtap="{{D}}">注册新用户</button></view><view wx:else class="panel"><input class="input" type="text" placeholder="输入邮箱" value="{{E}}" bindinput="{{F}}"/><view class="row"><input class="input flex1" type="text" placeholder="邮箱验证码" value="{{G}}" bindinput="{{H}}"/><button class="btn ghost" disabled="{{J}}" bindtap="{{K}}">{{I}}</button></view><input class="input" type="password" placeholder="新密码(≥6位)" value="{{L}}" bindinput="{{M}}"/><input class="input" type="password" placeholder="再次输入新密码" value="{{N}}" bindinput="{{O}}"/><button class="btn primary" disabled="{{P}}" bindtap="{{Q}}">重置密码</button></view></view>
<view class="auth-page"><view class="login-hero"><image class="login-hero-img" src="{{a}}" mode="widthFix"/></view><view class="header"><text class="title">邮箱密码登录</text></view><view wx:if="{{b}}" class="panel"><input class="input" type="text" placeholder="输入邮箱" value="{{c}}" bindinput="{{d}}"/><input class="input" type="password" placeholder="输入密码" value="{{e}}" bindinput="{{f}}"/><button class="btn primary" disabled="{{g}}" bindtap="{{h}}">登录</button><view class="quick-inline"><button class="quick-link" bindtap="{{i}}">注册</button><button class="quick-link" bindtap="{{j}}">忘记密码</button></view></view><view wx:if="{{k}}" class="panel minor"><input class="input" type="text" placeholder="输入用户名" value="{{l}}" bindinput="{{m}}"/><input class="input" type="text" placeholder="输入邮箱" value="{{n}}" bindinput="{{o}}"/><view class="row"><input class="input flex1" type="text" placeholder="邮箱验证码" value="{{p}}" bindinput="{{q}}"/><button class="btn ghost" disabled="{{s}}" bindtap="{{t}}">{{r}}</button></view><input class="input" type="password" placeholder="输入密码(≥6位)" value="{{v}}" bindinput="{{w}}"/><input class="input" type="password" placeholder="再次输入密码" value="{{x}}" bindinput="{{y}}"/><button class="btn primary" disabled="{{z}}" bindtap="{{A}}">注册新用户</button></view><view wx:if="{{B}}" class="panel minor"><input class="input" type="text" placeholder="输入邮箱" value="{{C}}" bindinput="{{D}}"/><view class="row"><input class="input flex1" type="text" placeholder="邮箱验证码" value="{{E}}" bindinput="{{F}}"/><button class="btn ghost" disabled="{{H}}" bindtap="{{I}}">{{G}}</button></view><input class="input" type="password" placeholder="新密码(≥6位)" value="{{J}}" bindinput="{{K}}"/><input class="input" type="password" placeholder="再次输入新密码" value="{{L}}" bindinput="{{M}}"/><button class="btn primary" disabled="{{N}}" bindtap="{{O}}">重置密码</button></view></view>

View File

@@ -24,39 +24,78 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 藏青系主色(高亮) */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.auth-page {
padding: 32rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
position: relative;
min-height: 100vh;
}
.tabs {
.header {
display: flex;
gap: 24rpx;
align-items: center;
justify-content: center;
padding: 8rpx 0 0;
}
.tab {
padding: 12rpx 20rpx;
border-radius: 999rpx;
background: #f2f4f8;
color: #5b6b80;
font-weight: 700;
.title {
font-size: 34rpx;
font-weight: 800;
color: #111;
}
.tab.active {
background: #2d6be6;
color: #fff;
.login-hero {
display: flex;
justify-content: center;
padding: 16rpx 0 0;
}
.login-hero-img {
width: 72%;
max-width: 560rpx;
border-radius: 8rpx;
}
.panel {
display: flex;
flex-direction: column;
gap: 16rpx;
background: #fff;
padding: 24rpx;
border-radius: 16rpx;
border: 2rpx solid #eef2f9;
background: transparent;
padding: 0;
border-radius: 0;
border: none;
}
.panel.minor {
margin-top: 12rpx;
}
.input {
background: #f7f9ff;
border: 2rpx solid rgba(45, 107, 230, 0.12);
background: #ffffff;
border: 2rpx solid #e5e7eb;
border-radius: 12rpx;
padding: 22rpx 20rpx;
font-size: 28rpx;
@@ -78,8 +117,47 @@
.btn.primary {
background: linear-gradient(135deg, #4788ff 0%, #2d6be6 100%);
color: #fff;
border: 1rpx solid rgba(45, 107, 230, 0.25);
width: 72%;
margin: 0 auto;
padding: 14rpx 16rpx;
}
.btn.ghost {
background: #eef3ff;
color: #2d6be6;
}
/* 右下角快捷入口:贴着登录功能,无边框、无背景 */
.quick-inline {
display: flex;
gap: 28rpx;
justify-content: flex-end;
align-items: center;
margin-top: 10rpx;
}
.quick-link {
background: transparent !important;
color: #2d6be6;
border: none !important;
outline: none;
padding: 0;
font-size: 26rpx;
font-weight: 700;
box-shadow: none;
line-height: 1.2;
}
.quick-link::after {
border: none !important;
}
/* 注册/重置页:验证码按钮与左侧输入框等高,且更紧凑 */
.panel.minor .row > .input {
height: 76rpx;
padding: 0 20rpx;
}
.panel.minor .row > .btn.ghost {
height: 76rpx;
padding: 0 20rpx;
border-radius: 12rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.register-container {
position: relative;
min-height: 100vh;

View File

@@ -24,6 +24,7 @@
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 表单控件尺寸(统一配置,避免页面内硬编码) */
.page {
padding-bottom: 140rpx;
}

Some files were not shown because too many files have changed in this diff Show More