wip(freight): migration 0017 + model/column-list groundwork for add-freight-templates

This commit is contained in:
Chengdong Zhang
2026-09-23 17:39:45 +08:00
parent a83e857bdf
commit 5b426486ac
105 changed files with 6193 additions and 1566 deletions
+53 -18
View File
@@ -181,28 +181,53 @@ onMounted(async () => {
<template>
<VPage :title="$t('shop.couponList')">
<div v-if="error" class="my-2 text-sm text-danger" role="alert">{{ error }}</div>
<div v-if="message" class="my-2 text-sm text-muted" role="status">{{ message }}</div>
<div v-if="error" class="text-danger my-2 text-sm" role="alert">{{ error }}</div>
<div v-if="message" class="text-muted my-2 text-sm" role="status">{{ message }}</div>
<VCard class="mb-5">
<h2 class="mb-4 text-base font-semibold">{{ editingId ? $t("shop.editCoupon") : $t("shop.newCoupon") }}</h2>
<div class="my-3 grid gap-3 [grid-template-columns:repeat(auto-fit,minmax(220px,1fr))]">
<VField :label="$t('shop.couponTitleEn')"><VInput v-model="form.titleEn" type="text" /></VField>
<VField :label="$t('shop.couponTitleZh')"><VInput v-model="form.titleZh" type="text" /></VField>
<VField :label="$t('shop.couponAmount')"><VInput v-model.number="form.amountMinor" type="number" min="1" step="1" /></VField>
<VField :label="$t('shop.couponThreshold')"><VInput v-model.number="form.thresholdMinor" type="number" min="0" step="1" /></VField>
<h2 class="mb-4 text-base font-semibold">
{{ editingId ? $t("shop.editCoupon") : $t("shop.newCoupon") }}
</h2>
<div class="my-3 grid [grid-template-columns:repeat(auto-fit,minmax(220px,1fr))] gap-3">
<VField :label="$t('shop.couponTitleEn')"
><VInput v-model="form.titleEn" type="text"
/></VField>
<VField :label="$t('shop.couponTitleZh')"
><VInput v-model="form.titleZh" type="text"
/></VField>
<VField :label="$t('shop.couponAmount')"
><VInput v-model.number="form.amountMinor" type="number" min="1" step="1"
/></VField>
<VField :label="$t('shop.couponThreshold')"
><VInput v-model.number="form.thresholdMinor" type="number" min="0" step="1"
/></VField>
<VField :label="$t('shop.couponCurrency')">
<select v-model="form.currency" class="w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-text focus:border-primary focus:outline-2 focus:outline-primary/30">
<select
v-model="form.currency"
class="border-border bg-surface text-text focus:border-primary focus:outline-primary/30 w-full rounded-md border px-3 py-2 text-sm focus:outline-2"
>
<option v-for="c in currencies" :key="c.code" :value="c.code">{{ c.code }}</option>
</select>
</VField>
<VField :label="$t('shop.couponStock')"><VInput v-model.number="form.stock" type="number" min="0" step="1" /></VField>
<VField :label="$t('shop.couponStartsAt')"><VInput v-model="form.startsAt" type="datetime-local" /></VField>
<VField :label="$t('shop.couponEndsAt')"><VInput v-model="form.endsAt" type="datetime-local" /></VField>
<label class="flex items-center gap-2 text-sm font-medium text-text"><input v-model="form.enabled" type="checkbox" class="h-4 w-4 accent-primary" /><span>{{ $t("shop.couponEnabled") }}</span></label>
<VField :label="$t('shop.couponStock')"
><VInput v-model.number="form.stock" type="number" min="0" step="1"
/></VField>
<VField :label="$t('shop.couponStartsAt')"
><VInput v-model="form.startsAt" type="datetime-local"
/></VField>
<VField :label="$t('shop.couponEndsAt')"
><VInput v-model="form.endsAt" type="datetime-local"
/></VField>
<label class="text-text flex items-center gap-2 text-sm font-medium"
><input v-model="form.enabled" type="checkbox" class="accent-primary h-4 w-4" /><span>{{
$t("shop.couponEnabled")
}}</span></label
>
</div>
<div class="flex gap-2">
<VBtn variant="primary" :disabled="saving" @click="submit">{{ editingId ? $t("shop.updateCoupon") : $t("shop.createCoupon") }}</VBtn>
<VBtn variant="primary" :disabled="saving" @click="submit">{{
editingId ? $t("shop.updateCoupon") : $t("shop.createCoupon")
}}</VBtn>
<VBtn v-if="editingId" type="button" @click="resetForm">{{ $t("common.cancel") }}</VBtn>
</div>
</VCard>
@@ -230,11 +255,21 @@ onMounted(async () => {
<td>{{ template.stock }}</td>
<td>{{ template.starts_at.slice(0, 10) }}</td>
<td>{{ template.ends_at.slice(0, 10) }}</td>
<td><VBadge :tone="template.enabled ? 'green' : 'red'">{{ template.enabled ? $t("shop.enabledOn") : $t("shop.enabledOff") }}</VBadge></td>
<td>
<VBadge :tone="template.enabled ? 'green' : 'red'">{{
template.enabled ? $t("shop.enabledOn") : $t("shop.enabledOff")
}}</VBadge>
</td>
<td class="flex flex-wrap gap-1.5">
<VBtn size="sm" :disabled="actionId === template.id" @click="edit(template)">{{ $t("shop.edit") }}</VBtn>
<VBtn size="sm" :disabled="actionId === template.id" @click="toggleEnabled(template)">{{ template.enabled ? $t("shop.enabledOff") : $t("shop.enabledOn") }}</VBtn>
<VBtn size="sm" :disabled="actionId === template.id" @click="remove(template)">{{ $t("common.delete") }}</VBtn>
<VBtn size="sm" :disabled="actionId === template.id" @click="edit(template)">{{
$t("shop.edit")
}}</VBtn>
<VBtn size="sm" :disabled="actionId === template.id" @click="toggleEnabled(template)">{{
template.enabled ? $t("shop.enabledOff") : $t("shop.enabledOn")
}}</VBtn>
<VBtn size="sm" :disabled="actionId === template.id" @click="remove(template)">{{
$t("common.delete")
}}</VBtn>
</td>
</tr>
</tbody>