Compare commits

...
6 Commits
Author SHA1 Message Date
richjohnrambo 4288782b2b fix: allow two-character member names
Deploy olons-admin production / deploy (push) Successful in 9m10s
2026-10-19 18:12:11 +08:00
dev d35cad4615 Merge remote-tracking branch 'origin/main' into pro
Deploy olons-admin production / deploy (push) Successful in 5m17s
2026-10-19 10:30:26 +08:00
richjohnrambo eead3dd798 feat: add product price range filter 2026-10-19 10:30:14 +08:00
dev 2483d09c39 Merge remote-tracking branch 'origin/main' into pro
Deploy olons-admin production / deploy (push) Successful in 5m27s
2026-10-19 10:15:22 +08:00
richjohnrambo 661486e46e fix: exclude manual products from product list 2026-10-19 10:14:55 +08:00
Your Name 3bc96f5325 test: align deployment contract with production
Deploy olons-admin production / deploy (push) Successful in 32s
2026-10-19 02:54:38 +08:00
8 changed files with 56 additions and 19 deletions
+19 -1
View File
@@ -45,7 +45,7 @@ func (s *sSysProduct) listModel(ctx context.Context) *gdb.Model {
} }
func (s *sSysProduct) List(ctx context.Context, in *sysin.ProductListInp) (list []*sysin.ProductListModel, total int, err error) { func (s *sSysProduct) List(ctx context.Context, in *sysin.ProductListInp) (list []*sysin.ProductListModel, total int, err error) {
pc := dao.Product.Columns() pc := dao.Product.Columns()
mod := s.listModel(ctx) mod := s.listModel(ctx).Where(col("p", pc.ProductType), consts.ProductTypeStandard)
if in.Name != "" { if in.Name != "" {
mod = mod.WhereLike(col("p", pc.Name), "%"+in.Name+"%") mod = mod.WhereLike(col("p", pc.Name), "%"+in.Name+"%")
} }
@@ -55,6 +55,24 @@ func (s *sSysProduct) List(ctx context.Context, in *sysin.ProductListInp) (list
if in.CategoryId > 0 { if in.CategoryId > 0 {
mod = mod.Where(col("p", pc.CategoryId), in.CategoryId) mod = mod.Where(col("p", pc.CategoryId), in.CategoryId)
} }
var minAmount, maxAmount int64
if in.PriceMin != "" {
minAmount, err = parseCents(in.PriceMin)
if err != nil {
return nil, 0, gerror.New("最低价格格式不正确")
}
mod = mod.WhereGTE(col("p", pc.PriceAmount), minAmount)
}
if in.PriceMax != "" {
maxAmount, err = parseCents(in.PriceMax)
if err != nil {
return nil, 0, gerror.New("最高价格格式不正确")
}
mod = mod.WhereLTE(col("p", pc.PriceAmount), maxAmount)
}
if in.PriceMin != "" && in.PriceMax != "" && minAmount > maxAmount {
return nil, 0, gerror.New("最低价格不能高于最高价格")
}
if in.PublishStatus > 0 { if in.PublishStatus > 0 {
mod = mod.Where(col("p", pc.PublishStatus), in.PublishStatus) mod = mod.Where(col("p", pc.PublishStatus), in.PublishStatus)
} }
@@ -75,7 +75,7 @@ type AppMemberViewModel struct {
type AppMemberEditInp struct { type AppMemberEditInp struct {
Id uint64 `json:"id"` Id uint64 `json:"id"`
Username string `json:"username" v:"required|length:3,64#用户名不能为空|用户名长度为3到64个字符"` Username string `json:"username" v:"required|length:2,64#用户名不能为空|用户名长度为2到64个字符"`
Mobile string `json:"mobile" v:"phone-loose#手机号格式不正确"` Mobile string `json:"mobile" v:"phone-loose#手机号格式不正确"`
Password string `json:"password"` Password string `json:"password"`
TradePassword string `json:"tradePassword"` TradePassword string `json:"tradePassword"`
@@ -9,7 +9,7 @@ import (
) )
type AppMemberRegisterInp struct { type AppMemberRegisterInp struct {
Username string `json:"username" v:"required|length:3,64#用户名不能为空|用户名长度为3到64个字符"` Username string `json:"username" v:"required|length:2,64#用户名不能为空|用户名长度为2到64个字符"`
Mobile string `json:"mobile" v:"required|phone-loose#手机号不能为空|手机号格式不正确"` Mobile string `json:"mobile" v:"required|phone-loose#手机号不能为空|手机号格式不正确"`
Password string `json:"password" v:"required|length:6,64#密码不能为空|密码长度为6到64个字符"` Password string `json:"password" v:"required|length:6,64#密码不能为空|密码长度为6到64个字符"`
InviteCode string `json:"inviteCode" v:"required#请输入邀请码"` InviteCode string `json:"inviteCode" v:"required#请输入邀请码"`
@@ -45,6 +45,8 @@ type ProductListInp struct {
Name string `json:"name"` Name string `json:"name"`
PaymentType string `json:"paymentType"` PaymentType string `json:"paymentType"`
CategoryId uint64 `json:"categoryId"` CategoryId uint64 `json:"categoryId"`
PriceMin string `json:"priceMin" dc:"最低价格"`
PriceMax string `json:"priceMax" dc:"最高价格"`
PublishStatus int `json:"publishStatus"` PublishStatus int `json:"publishStatus"`
} }
+4 -4
View File
@@ -20,12 +20,12 @@ class DeploymentContract(unittest.TestCase):
for ignored in (".git", "web/node_modules", "web/dist", "server/temp"): for ignored in (".git", "web/node_modules", "web/dist", "server/temp"):
self.assertIn(ignored, dockerignore) self.assertIn(ignored, dockerignore)
def test_manual_workflow_builds_and_rolls_out_test_image(self): def test_manual_workflow_builds_and_rolls_out_pro_image(self):
workflow = (ROOT / ".gitea/workflows/deploy.yml").read_text() workflow = (ROOT / ".gitea/workflows/deploy.yml").read_text()
self.assertIn("workflow_dispatch:", workflow) self.assertIn("workflow_dispatch:", workflow)
self.assertIn("git.118im.com/im_team/olons-admin", workflow) self.assertIn("git.olns.shop/pro/olons_admin", workflow)
self.assertIn("deployment/olons-admin", workflow) self.assertIn("docker compose pull olons-admin", workflow)
self.assertIn("-n olons-admin-system", workflow) self.assertIn("docker compose up -d --no-deps --wait olons-admin", workflow)
if __name__ == "__main__": if __name__ == "__main__":
+1 -1
View File
@@ -479,7 +479,7 @@
const editRules = { const editRules = {
username: [ username: [
{ required: true, message: '请输入用户名称', trigger: ['input', 'blur'] }, { required: true, message: '请输入用户名称', trigger: ['input', 'blur'] },
{ min: 3, max: 64, message: '用户名长度为3到64个字符', trigger: ['input', 'blur'] }, { min: 2, max: 64, message: '用户名长度为2到64个字符', trigger: ['input', 'blur'] },
], ],
mobile: { mobile: {
validator: () => true, validator: () => true,
+23 -1
View File
@@ -1,7 +1,29 @@
<template> <template>
<div> <div>
<n-card :bordered="false" class="proCard"> <n-card :bordered="false" class="proCard">
<BasicForm ref="searchRef" @register="register" @submit="reload" @keyup.enter="reload" /> <BasicForm ref="searchRef" @register="register" @submit="reload" @keyup.enter="reload">
<template #priceRangeSlot="{ model }">
<n-space :wrap="false" align="center">
<n-input-number
v-model:value="model.priceMin"
:min="0"
:precision="2"
:show-button="false"
clearable
placeholder="最低价"
/>
<span>-</span>
<n-input-number
v-model:value="model.priceMax"
:min="0"
:precision="2"
:show-button="false"
clearable
placeholder="最高价"
/>
</n-space>
</template>
</BasicForm>
<BasicTable <BasicTable
ref="tableRef" ref="tableRef"
openChecked openChecked
+5 -10
View File
@@ -1,4 +1,4 @@
import { computed, h, ref } from 'vue'; import { h, ref } from 'vue';
import { NImage, NTag } from 'naive-ui'; import { NImage, NTag } from 'naive-ui';
import { FormSchema } from '@/components/Form'; import { FormSchema } from '@/components/Form';
import { useDictStore } from '@/store/modules/dict'; import { useDictStore } from '@/store/modules/dict';
@@ -13,14 +13,9 @@ export const schemas = ref<FormSchema[]>([
componentProps: { clearable: true }, componentProps: { clearable: true },
}, },
{ {
field: 'categoryId', field: 'priceRange',
component: 'NSelect', label: '价格范围',
label: '商品分类', slot: 'priceRangeSlot',
componentProps: {
options: computed(() => dict.getOptionUnRef('productCategoryOption')),
clearable: true,
placeholder: '请选择',
},
}, },
]); ]);
@@ -62,4 +57,4 @@ export const columns = [
}, },
]; ];
export const loadOptions = () => dict.loadOptions(['productCategoryOption', 'bizPublishStatus']); export const loadOptions = () => dict.loadOptions(['bizPublishStatus']);