This commit is contained in:
sdaduanbilei-d1581 2025-12-29 14:59:52 +08:00
parent c198aa6643
commit 8bb2f8e221
11 changed files with 860 additions and 221 deletions

View File

@ -2,19 +2,21 @@ import fetch from '../fetch.js'
export default {
save(params) {
return fetch('/claim/add', params,'post','json')
return fetch('/claim/add', params, 'post', 'json')
},
update(params) {
return fetch('/claim/update', params,'post','json')
return fetch('/claim/update', params, 'post', 'json')
},
list(params) {
return fetch('/claim/list', params,'post','json')
return fetch('/claim/list', params, 'post', 'json')
},
setImg(params) {
return fetch('/claim/uploadImg',params,'post','json')
return fetch('/claim/uploadImg', params, 'post', 'json')
},
linkLibrary(parasm) {
return fetch('/claim/unionLibrary', parasm, 'post', 'json')
}
}

View File

@ -2,56 +2,60 @@ import fetch from '../fetch.js'
export default {
save(params) {
return fetch('/library/add', params,'post','json')
return fetch('/library/add', params, 'post', 'json')
},
update(params) {
return fetch('/library/update', params,'post','json')
return fetch('/library/update', params, 'post', 'json')
},
remove(params) {
return fetch('/library/delete', params,'post','json')
return fetch('/library/delete', params, 'post', 'json')
},
list(params) {
return fetch('/library/list', params,'post','json')
return fetch('/library/page', params, 'post', 'json')
},
setImg(params) {
return fetch('/library/uploadImg',params,'post','json')
return fetch('/library/uploadImg', params, 'post', 'json')
},
linkClass(params) {
return fetch('/library/relateLibrary', params, 'post', 'json')
},
/**
* 热门
* @param params
* @returns {Promise | Promise<unknown>}
*/
changeHot(params){
return fetch('/library/hot',params,'post','json')
changeHot(params) {
return fetch('/library/hot', params, 'post', 'json')
},
inviteList(params){
return fetch('/personal/inviteCode/records',params,'post','json')
inviteList(params) {
return fetch('/personal/inviteCode/records', params, 'post', 'json')
},
wechat(params){
return fetch('/config/qrcode/add',params,'post','json')
wechat(params) {
return fetch('/config/qrcode/add', params, 'post', 'json')
},
wechatUpdate(params){
return fetch('/config/qrcode/update',params,'post','json')
wechatUpdate(params) {
return fetch('/config/qrcode/update', params, 'post', 'json')
},
wechatList(params){
return fetch('/config/qrcode/list',params,'post','json')
wechatList(params) {
return fetch('/config/qrcode/list', params, 'post', 'json')
},
saveCategory(params){
return fetch('/class/add',params, 'post','json')
saveCategory(params) {
return fetch('/class/add', params, 'post', 'json')
},
updateCategory(params){
return fetch('/class/update',params, 'post','json')
updateCategory(params) {
return fetch('/class/update', params, 'post', 'json')
},
listCategory(params){
return fetch('/class/list',params, 'post','json')
listCategory(params) {
return fetch('/class/list', params, 'post', 'json')
}
}

View File

@ -10,13 +10,16 @@
@success="upload"
>
<template #upload-button>
<a-button size="small" type="text">
<a-button size="small" type="text" v-if="type === 'btn'">
<template #icon>
<icon-loading v-if="loading" />
<icon-upload v-else />
</template>
<template #default>{{title}}</template>
</a-button>
<div v-else style="width: 60px; height: 60px; border: 1px solid #ccc" class="flex flex-center flex-justify-center" >
<icon-upload />
</div>
</template>
</a-upload>
</div>
@ -33,6 +36,10 @@ export default {
type: String,
default: '/api/oss/upload'
},
type : {
type:String,
default:'btn'
},
headers: {
type:Object,
default(){

View File

@ -0,0 +1,79 @@
<template>
<div>
<a-button type="text" @click="show = true">百科</a-button>
<a-modal v-model:visible="show" @before-ok="submit">
<div class="flex flex-center flex-justify-start mb-20">
<a-input placeholder="请输入植物名称" v-model="name" @input="search"></a-input>
</div>
<div style="min-height: 400px; overflow-y: auto">
<div v-if="list.length === 0" class="flex flex-center flex-justify-center " style="min-height: 400px;">
<a-empty></a-empty>
</div>
<a-list v-for="item in list" :key="item.id">
<a-list-item>
<div class="flex flex-center flex-justify-between">
<div>{{ item.name }}</div>
<div>
<a-button @click="select(item)" type="text">选择</a-button>
</div>
</div>
</a-list-item>
</a-list>
</div>
</a-modal>
</div>
</template>
<script>
import upload from '@/components/upload/index.vue'
export default {
components: {
upload
},
props: {
id: {
type: String,
default: ''
}
},
data() {
return {
list: [],
show: false,
timer: null,
name: ''
}
},
methods: {
search() {
if (this.timer) clearTimeout(this.timer)
this.timer = setTimeout(() => {
const data = { name: this.name, keyword: this.name, current: 1, pageSize: 999 }
this.$api.flower.list(data).then(res => {
if (res.code === 200) {
this.list = res.data.list
}
})
}, 500)
},
select(item) {
const data = { id: this.id, libraryId: item.id }
this.$api.claim.linkLibrary(data).then(res => {
if (res.code === 200) {
this.$message.success(res.msg)
this.show = false
this.$emit('ok')
}
})
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -5,33 +5,20 @@
<a-card>
<div class="flex flex-center flex-justify-start">
<edit @ok="fetchList"/>
<edit @ok="fetchList" />
</div>
<a-table
class="mt-20"
:columns="columns"
:data="list"
:pagination="page"
@pageChange="change"
>
<a-table class="mt-20" :columns="columns" :data="list" :pagination="page" @pageChange="change">
<template #name="{ record }">
<div class="flex flex-center flex-justify-start">
<a-image
v-if="record.imgList.length > 0"
width="60"
height="60"
:src="record.imgList[0].url"
:alt="record.id"
/>
<a-image v-if="record.imgList.length > 0" width="60" height="60" :src="record.imgList[0].url"
:alt="record.id" />
<div class="ml-10">{{ record.name }}</div>
</div>
</template>
<template #menu="{ record }">
<div class="flex flex-center">
<edit type="edit" :info="record" @ok="fetchList" />
<a-button type="text" @click="changeHot(record)">{{
record.isHot === 0 ? '设置热门' : '取消热门'
}}</a-button>
<baike :id="record.id" @ok="fetchList" />
</div>
</template>
</a-table>
@ -41,12 +28,14 @@
<script>
import navbar from '@/components/navbar/index.vue'
import baike from '../claim/components/baike.vue'
import edit from '../claim/components/edit.vue'
import upload from '../../../components/upload/index.vue'
export default {
components: {
upload,
edit,
baike,
navbar
},
data() {
@ -55,24 +44,24 @@ export default {
current: 0,
pageSize: 10
},
list:[],
columns :[
list: [],
columns: [
{
title:'名称',
title: '名称',
slotName: 'name',
},
{
title:'标签',
title: '标签',
dataIndex: 'tag',
},
{
title:'档案',
dataIndex:'content'
title: '档案',
dataIndex: 'content'
},
{
title:"操作",
slotName:'menu'
title: "操作",
slotName: 'menu'
}
]
}
@ -82,7 +71,7 @@ export default {
},
methods: {
fetchList() {
const data = { keyword: '',name:'', ...this.page }
const data = { keyword: '', name: '', ...this.page }
this.$api.claim.list(data).then(res => {
if (res.code === 200) {
console.log(res)

View File

@ -2,7 +2,17 @@
<div>
<a-button type="text" @click="show = true">{{ title }}</a-button>
<a-modal v-model:visible="show" @before-ok="submit" @close="reset">
<a-textarea v-model="tmp" :auto-size="{ miniRows: 6 }"></a-textarea>
<div class="bold mb-20">请输入花卉信息</div>
<a-textarea v-model="from" :auto-size="{ miniRows: 6 }"></a-textarea>
<div>
<div class="bold mt-20">请选择分类</div>
<div class="mt-20">
<a-tag v-for="item in list" type="primary" class="mr-15" :color="item.checked ? 'green' : ''"
@click="check(item)">
{{ item.tag }}
</a-tag>
</div>
</div>
</a-modal>
</div>
</template>
@ -15,15 +25,25 @@ export default {
default: 'add'
},
info: {
type:Object,
default:null
type: Object,
default: null
}
},
watch: {
show: {
handler(val) {
if (val) {
this.tmp = JSON.stringify(this.from, null, 4)
if (this.info) {
this.from = JSON.parse(JSON.stringify(this.info))
const keysToRemove = ['careSchedules', 'relatedLibrary', 'classification', 'ralatedLibrary', 'imgList']
Object.keys(this.from).forEach(k => {
if (keysToRemove.some(t => t.toLowerCase() === k.toLowerCase())) {
delete this.from[k]
}
})
}
this.from = JSON.stringify(this.from, null, 4)
this.fetchList()
}
}
},
@ -38,7 +58,7 @@ export default {
this.from.remark = this.info.Remark
this.from.circleDays = this.info.CircleDays
this.from.isCircle = this.info.isCircle
this.tmp = JSON.stringify(this.from, null, 4)
this.from = JSON.stringify(this.from, null, 4)
}
},
immediate: true
@ -49,6 +69,7 @@ export default {
tmp: null,
show: false,
title: '新增',
list: [],
from: {
"name": "蝴蝶兰",
"latinName": "Phalaenopsis aphrodite Rchb. f.",
@ -71,20 +92,59 @@ export default {
"floweringPeriod": "自然花期4-6月人工栽培可全年开花盛花期12-3月",
"floweringColor": "白、粉、黄、紫红等,常具斑纹或条纹",
"floweringShape": "花姿如蝶唇瓣3裂具卷须",
"flowerDiameter": 90
"flowerDiameter": 90,
classificationId: ''
}
}
},
methods: {
reset(){
reset() {
this.from = {
name: '请输入名称',
}
},
fetchList() {
const data = { current: 1, pageSize: 999, }
this.$api.flower.listCategory(data).then((res) => {
if (res.code === 200) {
this.list = res.data.list.map(e => {
e.checked = false
return e
})
}
})
},
check(item) {
this.list.forEach(e => {
e.checked = false
})
item.checked = true
try {
const obj = JSON.parse(this.from)
obj.classificationId = item.id
this.from = JSON.stringify(obj, null, 4)
} catch (e) {
this.$message.error('JSON 格式错误,无法选择分类')
}
},
submit(done) {
const data = JSON.parse(this.tmp)
let data
try {
data = JSON.parse(this.from)
} catch (e) {
this.$message.error('JSON 格式错误')
done(false)
return
}
if (this.type === 'add') {
// id
if (data.classificationId === '') {
this.$message.error('请设置分类')
done(false)
return
}
this.$api.flower.save(data).then(res => {
if (res.code === 200) {
this.$message.success(res.msg)

View File

@ -0,0 +1,78 @@
<template>
<div>
<a-button type="text" @click="show = true">分类</a-button>
<a-modal v-model:visible="show" @before-ok="submit">
<div>
<a-tag v-for="item in list" type="primary" class="mr-15" @click="select(item)">
{{ item.tag }}
</a-tag>
</div>
</a-modal>
</div>
</template>
<script>
export default {
props: {
id: {
type: String,
default: ''
}
},
watch: {
show: {
handler(val) {
if (val) {
this.fetchList()
}
},
immediate: true
}
},
data() {
return {
list: [],
show: false,
timer: null,
name: ''
}
},
methods: {
fetchList() {
const data = { current: 1, pageSize: 999, }
this.$api.flower.listCategory(data).then((res) => {
if (res.code === 200) {
this.list = res.data.list.map(e => {
e.checked = false
return e
})
}
})
},
select(item) {
const data = { id: this.id, ids: [item.id] }
this.$api.flower.linkClass(data).then(res => {
if (res.code === 200) {
this.$message.success(res.msg)
this.show = false
this.$emit('ok')
} else {
this.$message.error(res.msg)
}
})
},
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,23 +1,32 @@
<template>
<div>
<navbar title="花卉百科"/>
<navbar title="花卉百科" />
<a-card>
<div class="flex flex-center flex-justify-start">
<edit @ok="fetchList"/>
<category/>
<edit @ok="fetchList" />
<category />
</div>
<a-table class="mt-20" :columns="columns" :data="list" :pagination="page" @pageChange="change">
<template #name="{record}">
<template #name="{ record }">
<div class="flex flex-center flex-justify-start">
<a-image v-if="record.imgList.length > 0" width="60" height="60" :src="record.imgList[0].url" :alt="record.id"/>
<div class="ml-10">{{record.name}}</div>
<a-image v-if="record.imgList.length > 0" width="60" height="60" :src="record.imgList[0].url" fit="cover"
:alt="record.id" />
<div v-else>
<upload @ok="upload(record, $event)" type="image" />
</div>
<div class="ml-10">{{ record.name }}</div>
</div>
</template>
<template #menu="{record}">
<template #hot="{ record }">
<div @click="changeHot(record)">
<a-tag color="red" size="small" v-if="record.isHot === 1">热门</a-tag>
<a-tag size="small" v-else>未推荐</a-tag>
</div>
</template>
<template #menu="{ record }">
<div class="flex flex-center">
<edit type="edit" :info="record" @ok="fetchList"/>
<a-button type="text" @click="changeHot(record)">{{record.isHot === 0 ?'设置热门':'取消热门'}}</a-button>
<upload @ok="upload(record,$event)"/>
<edit type="edit" :info="record" @ok="fetchList" />
<linkLibrary :id="record.id" />
<a-popconfirm content="确认删除该条数据" @ok="remove(record.id)">
<a-button type="text">删除</a-button>
</a-popconfirm>
@ -32,42 +41,48 @@
import navbar from '@/components/navbar/index.vue'
import upload from "../../../components/upload/index.vue";
import edit from './components/edit.vue'
import linkLibrary from './components/link.vue'
import category from './components/category.vue'
export default {
components: {
navbar,
edit,
category,
upload
upload,
linkLibrary
},
data() {
return {
list: [],
page:{
current:1,
pageSize:10,
total:0
page: {
current: 1,
pageSize: 10,
total: 0
},
columns :[
columns: [
{
title:'名称',
title: '名称',
slotName: 'name',
},
{
title:'别名',
title: '别名',
dataIndex: 'aliases',
},
{
title:'latinName',
dataIndex:'latinName'
title: 'latinName',
dataIndex: 'latinName'
},
{
title:'科/属',
title: '科/属',
dataIndex: 'genus',
},
{
title:"操作",
slotName:'menu'
title: '是否推荐',
slotName: 'hot',
},
{
title: "操作",
slotName: 'menu'
}
]
}
@ -76,14 +91,14 @@ export default {
this.fetchList()
},
methods: {
change(page){
change(page) {
this.page.current = page
this.fetchList()
},
fetchList() {
const data ={...this.page}
const data = { ...this.page }
this.$api.flower.list(data).then(res => {
if (res.code === 200){
if (res.code === 200) {
this.list = res.data.list
this.page.total = res.data.total
} else {
@ -91,30 +106,30 @@ export default {
}
})
},
changeHot(item){
const ids = {ids:[item.id],isHot: item.isHot === 0 ? 1 :0}
changeHot(item) {
const ids = { ids: [item.id], isHot: item.isHot === 0 ? 1 : 0 }
this.$api.flower.changeHot(ids).then(res => {
if(res.code === 200){
if (res.code === 200) {
this.$message.success(res.msg)
this.fetchList()
}else {
} else {
this.$message.error(res.msg);
}
})
},
upload(item,file){
const data = {id:item.id,ossIds:[file.id]}
upload(item, file) {
const data = { id: item.id, ossIds: [file.id] }
this.$api.flower.setImg(data).then(res => {
if(res.code === 200){
if (res.code === 200) {
this.fetchList()
} else {
this.$message.error(res.msg)
}
})
},
remove(id){
this.$api.flower.remove({ids:[id]}).then(res => {
if(res.code === 200){
remove(id) {
this.$api.flower.remove({ ids: [id] }).then(res => {
if (res.code === 200) {
this.fetchList()
} else {
this.$message.error(res.msg)
@ -125,6 +140,4 @@ export default {
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,125 @@
<template>
<div>
<Button type="tertiary" theme="borderless" @click="show = true">{{ type === 'edit'? '编辑' : type === 'addSub' ? '新增子项':'新增'}}</Button>
<Modal
v-model:visible="show"
width="640px"
@ok="handleOk"
:maskClosable="false"
@cancel="handleCancel"
>
<Form
:labelPosition="'top'"
:initValues="form"
:getFormApi="bindFormApi"
ref="formRef"
>
<Form.Input
field="name"
label="名称"
:rules="[{ required: true, message: '请填写名称' }]"
placeholder="请输入名称"
/>
</Form>
</Modal>
</div>
</template>
<script>
import { Modal, Button, Form, Toast, Notification } from '@kousum/semi-ui-vue'
export default {
components: {
Modal,
Button,
Form,
'Form.Input': Form.Input
},
props: {
type: {
type: String,
default: 'new'
},
info:{
type: Object,
default:null
}
},
data() {
return {
show: false,
form: {
id:'',
name: '',
sort: 1,
},
formApi: null
}
},
watch: {
info: {
handler(val) {
if (val) {
this.form = { ...val }
this.$nextTick(() => {
if (this.formApi) {
if (this.type === 'addSub'){
this.formApi.setValues({ parentId: val.id })
} else if (this.type === 'edit'){
this.formApi.setValues(val)
}
}
})
}
},
immediate: true
}
},
methods: {
bindFormApi(api) {
this.formApi = api
},
handleCancel() {
// Optional
},
handleOk() {
return new Promise((resolve, reject) => {
this.formApi.validate().then(values => {
const formData = { ...this.form, ...values }
if (this.form.id !== "" && this.type !== 'new'){
this.$api.sys.clientUpdate(formData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Notification.error({ content: res.msg })
reject()
}
}).catch(() => reject())
} else {
this.$api.sys.clientSave(formData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Notification.error({ content: res.msg })
reject()
}
}).catch(() => reject())
}
}).catch(errors => {
reject()
})
})
},
submit(done) {
// legacy
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,145 @@
<template>
<div>
<Button type="tertiary" theme="borderless" @click="show = true">{{ type === 'edit'? '编辑' : type === 'addSub' ? '新增子菜单':'新增菜单'}}</Button>
<Modal
v-model:visible="show"
width="640px"
@ok="handleOk"
:maskClosable="false"
@cancel="handleCancel"
>
<Form
:labelPosition="'top'"
:initValues="form"
:getFormApi="bindFormApi"
ref="formRef"
>
<Form.Input
field="name"
label="名称"
:rules="[{ required: true, message: '请填写名称' }]"
placeholder="请输入名称"
/>
<Form.Input
field="permission"
label="路径"
:rules="[{ required: true, message: '请输入路径' }]"
placeholder="请输入路径"
/>
<Form.InputNumber
field="sort"
label="排序"
initValue="1"
placeholder="请输入排序"
style="width: 100%"
/>
</Form>
</Modal>
</div>
</template>
<script>
import { Modal, Button, Form, Toast, Notification } from '@kousum/semi-ui-vue'
export default {
components: {
Modal,
Button,
Form,
'Form.Input': Form.Input,
'Form.InputNumber': Form.InputNumber
},
props: {
type: {
type: String,
default: 'new'
},
info:{
type: Object,
default:null
}
},
data() {
return {
show: false,
form: {
id:'',
name: '',
permission: '',
sort: 1,
category: 0,
parentId: '0',
code:''
},
formApi: null
}
},
watch: {
info: {
handler(val) {
if (val) {
this.form = { ...val }
this.$nextTick(() => {
if (this.formApi) {
if (this.type === 'addSub'){
this.formApi.setValues({ parentId: val.id })
} else if (this.type === 'edit'){
this.formApi.setValues(val)
}
}
})
}
},
immediate: true
}
},
methods: {
bindFormApi(api) {
this.formApi = api
},
handleCancel() {
// Optional
},
handleOk() {
return new Promise((resolve, reject) => {
this.formApi.validate().then(values => {
const formData = { ...this.form, ...values }
formData.code = formData.permission
formData.title = formData.name
if (this.form.id !== "" && this.type !== 'new'){
this.$api.sys.menuUpdate(formData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Notification.error({ content: res.msg })
reject()
}
}).catch(() => reject())
} else {
this.$api.sys.menuSave(formData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Notification.error({ content: res.msg })
reject()
}
}).catch(() => reject())
}
}).catch(errors => {
reject()
})
})
},
submit(done) {
// legacy
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,137 @@
<template>
<div>
<Button type="tertiary" theme="borderless" @click="show = true">{{ type === 'edit'? '编辑' : type === 'addSub' ? '新增子项':'新增'}}</Button>
<Modal
v-model:visible="show"
width="640px"
@ok="handleOk"
:maskClosable="false"
@cancel="handleCancel"
>
<Form
:labelPosition="'top'"
:initValues="form"
:getFormApi="bindFormApi"
ref="formRef"
>
<Form.Input
field="account"
label="账户"
:rules="[{ required: true, message: '请填写账户' }]"
placeholder="请输入账户"
/>
<Form.Input
field="phone"
label="电话"
:rules="[{ required: true, message: '请填写电话' }]"
placeholder="请输入电话"
/>
</Form>
</Modal>
</div>
</template>
<script>
import { Modal, Button, Form, Toast, Notification } from '@kousum/semi-ui-vue'
export default {
components: {
Modal,
Button,
Form,
'Form.Input': Form.Input // Use explicit component mapping if needed, or rely on Form.Input in template
},
props: {
type: {
type: String,
default: 'new'
},
info:{
type: Object,
default:null
}
},
data() {
return {
show: false,
form: {
id:'',
name: '',
phone:'',
account: '' // ensure account is in init values
},
formApi: null
}
},
watch: {
info: {
handler(val) {
if (val) {
this.form = { ...val }
// Update formApi if available immediately or next tick
this.$nextTick(() => {
if (this.formApi) {
if (this.type === 'addSub'){
this.formApi.setValues({ parentId: val.id })
} else if (this.type === 'edit'){
this.formApi.setValues(val)
}
}
})
}
},
immediate: true
}
},
methods: {
bindFormApi(api) {
this.formApi = api
},
handleCancel() {
// Reset form on close
// this.formApi.reset() // Optional
},
handleOk() {
// Return promise for Modal loading state
return new Promise((resolve, reject) => {
this.formApi.validate().then(values => {
// values contains the form data
const submitData = { ...this.form, ...values }
if (this.form.id !== "" && this.type !== 'new'){ // Logic check: type edit implies id exists
this.$api.sys.staffUpdate(submitData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Notification.error({ content: res.msg })
reject()
}
}).catch(() => reject())
} else {
this.$api.sys.staffSave(submitData).then(res => {
if (res.code === 200) {
Toast.success(res.msg)
this.$emit('ok')
resolve()
} else {
Toast.error(res.msg)
reject()
}
}).catch(() => reject())
}
}).catch(errors => {
reject()
})
})
},
// Legacy submit adapter if needed, but handleOk replaces it
submit(done) {
// not used with new Modal logic
}
}
}
</script>
<style lang="scss" scoped></style>