Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de89ccebac |
@@ -355,6 +355,8 @@ def register(body: dict):
|
||||
"INSERT INTO users (username, token, role, display_name, password) VALUES (?, ?, ?, ?, ?)",
|
||||
(username, token, "viewer", display_name or username, hash_password(password))
|
||||
)
|
||||
uid = conn.execute("SELECT id FROM users WHERE username = ?", (username,)).fetchone()
|
||||
log_audit(conn, uid["id"] if uid else None, "register", "user", username, display_name or username, None)
|
||||
conn.commit()
|
||||
except Exception:
|
||||
conn.close()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<span v-for="tag in visibleTags" :key="tag" class="tag" :class="{ 'tag-reviewed': tag === '已审核' }">{{ tag }}</span>
|
||||
</div>
|
||||
<div class="recipe-card-oils">{{ oilNames }}</div>
|
||||
<span v-if="volumeLabel" class="recipe-card-volume">{{ volumeLabel }}</span>
|
||||
<div class="recipe-card-bottom">
|
||||
<div class="recipe-card-price">💰 {{ priceInfo.cost }}</div>
|
||||
<button
|
||||
@@ -41,10 +42,20 @@ const visibleTags = computed(() => {
|
||||
})
|
||||
|
||||
const oilNames = computed(() =>
|
||||
props.recipe.ingredients.map(i => i.oil).join('、')
|
||||
[...props.recipe.ingredients].sort((a, b) => a.oil.localeCompare(b.oil, 'zh')).map(i => i.oil).join('、')
|
||||
)
|
||||
const priceInfo = computed(() => oilsStore.fmtCostWithRetail(props.recipe.ingredients))
|
||||
const isFav = computed(() => recipesStore.isFavorite(props.recipe))
|
||||
|
||||
const volumeLabel = computed(() => {
|
||||
const ings = props.recipe.ingredients || []
|
||||
const coco = ings.find(i => i.oil === '椰子油')
|
||||
if (!coco || !coco.drops) return ''
|
||||
const totalDrops = ings.reduce((s, i) => s + (i.drops || 0), 0)
|
||||
const ml = totalDrops / 18.6
|
||||
if (ml <= 2) return '单次'
|
||||
return `${Math.round(ml)}ml`
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -98,6 +109,13 @@ const isFav = computed(() => recipesStore.isFavorite(props.recipe))
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.recipe-card-volume {
|
||||
font-size: 10px;
|
||||
color: #b0aab5;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.recipe-card-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -96,6 +96,7 @@ const ACTION_MAP = {
|
||||
reject_business: '拒绝商业认证',
|
||||
grant_business: '开通商业认证',
|
||||
revoke_business: '撤销商业认证',
|
||||
register: '用户注册',
|
||||
}
|
||||
|
||||
const actionTypes = [
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Add/Edit Recipe Overlay -->
|
||||
<div v-if="showAddOverlay" class="overlay" @click.self="closeOverlay">
|
||||
<div v-if="showAddOverlay" class="overlay">
|
||||
<div class="overlay-panel">
|
||||
<div class="overlay-header">
|
||||
<h3>{{ editingRecipe ? '编辑配方' : '添加配方' }}</h3>
|
||||
@@ -1312,12 +1312,10 @@ function diaryMatchesPublic(d) {
|
||||
}
|
||||
|
||||
function getDiaryShareStatus(d) {
|
||||
// Check pending (owned by user in public library, not yet adopted)
|
||||
if (sharedCount.value.pendingNames.includes(d.name)) return 'pending'
|
||||
// Check if public library has same recipe with same content
|
||||
// Admin/senior_editor share directly — check public match first
|
||||
if (diaryMatchesPublic(d)) return 'shared'
|
||||
// Check adopted names from audit log
|
||||
if (sharedCount.value.adoptedNames.includes(d.name) && diaryMatchesPublic(d)) return 'shared'
|
||||
// Non-admin: check pending (owned by user, not yet adopted)
|
||||
if (!auth.isAdmin && !auth.canManage && sharedCount.value.pendingNames.includes(d.name)) return 'pending'
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user