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

@ -16,5 +16,7 @@ export default {
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

@ -12,12 +12,16 @@ export default {
}, },
list(params) { list(params) {
return fetch('/library/list', params,'post','json') return fetch('/library/page', params, 'post', 'json')
}, },
setImg(params) { 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 * @param params

View File

@ -10,13 +10,16 @@
@success="upload" @success="upload"
> >
<template #upload-button> <template #upload-button>
<a-button size="small" type="text"> <a-button size="small" type="text" v-if="type === 'btn'">
<template #icon> <template #icon>
<icon-loading v-if="loading" /> <icon-loading v-if="loading" />
<icon-upload v-else /> <icon-upload v-else />
</template> </template>
<template #default>{{title}}</template> <template #default>{{title}}</template>
</a-button> </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> </template>
</a-upload> </a-upload>
</div> </div>
@ -33,6 +36,10 @@ export default {
type: String, type: String,
default: '/api/oss/upload' default: '/api/oss/upload'
}, },
type : {
type:String,
default:'btn'
},
headers: { headers: {
type:Object, type:Object,
default(){ 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

@ -7,31 +7,18 @@
<div class="flex flex-center flex-justify-start"> <div class="flex flex-center flex-justify-start">
<edit @ok="fetchList" /> <edit @ok="fetchList" />
</div> </div>
<a-table <a-table class="mt-20" :columns="columns" :data="list" :pagination="page" @pageChange="change">
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"> <div class="flex flex-center flex-justify-start">
<a-image <a-image v-if="record.imgList.length > 0" width="60" height="60" :src="record.imgList[0].url"
v-if="record.imgList.length > 0" :alt="record.id" />
width="60"
height="60"
:src="record.imgList[0].url"
:alt="record.id"
/>
<div class="ml-10">{{ record.name }}</div> <div class="ml-10">{{ record.name }}</div>
</div> </div>
</template> </template>
<template #menu="{ record }"> <template #menu="{ record }">
<div class="flex flex-center"> <div class="flex flex-center">
<edit type="edit" :info="record" @ok="fetchList" /> <edit type="edit" :info="record" @ok="fetchList" />
<a-button type="text" @click="changeHot(record)">{{ <baike :id="record.id" @ok="fetchList" />
record.isHot === 0 ? '设置热门' : '取消热门'
}}</a-button>
</div> </div>
</template> </template>
</a-table> </a-table>
@ -41,12 +28,14 @@
<script> <script>
import navbar from '@/components/navbar/index.vue' import navbar from '@/components/navbar/index.vue'
import baike from '../claim/components/baike.vue'
import edit from '../claim/components/edit.vue' import edit from '../claim/components/edit.vue'
import upload from '../../../components/upload/index.vue' import upload from '../../../components/upload/index.vue'
export default { export default {
components: { components: {
upload, upload,
edit, edit,
baike,
navbar navbar
}, },
data() { data() {

View File

@ -2,7 +2,17 @@
<div> <div>
<a-button type="text" @click="show = true">{{ title }}</a-button> <a-button type="text" @click="show = true">{{ title }}</a-button>
<a-modal v-model:visible="show" @before-ok="submit" @close="reset"> <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> </a-modal>
</div> </div>
</template> </template>
@ -23,7 +33,17 @@ export default {
show: { show: {
handler(val) { handler(val) {
if (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.remark = this.info.Remark
this.from.circleDays = this.info.CircleDays this.from.circleDays = this.info.CircleDays
this.from.isCircle = this.info.isCircle this.from.isCircle = this.info.isCircle
this.tmp = JSON.stringify(this.from, null, 4) this.from = JSON.stringify(this.from, null, 4)
} }
}, },
immediate: true immediate: true
@ -49,6 +69,7 @@ export default {
tmp: null, tmp: null,
show: false, show: false,
title: '新增', title: '新增',
list: [],
from: { from: {
"name": "蝴蝶兰", "name": "蝴蝶兰",
"latinName": "Phalaenopsis aphrodite Rchb. f.", "latinName": "Phalaenopsis aphrodite Rchb. f.",
@ -71,7 +92,8 @@ export default {
"floweringPeriod": "自然花期4-6月人工栽培可全年开花盛花期12-3月", "floweringPeriod": "自然花期4-6月人工栽培可全年开花盛花期12-3月",
"floweringColor": "白、粉、黄、紫红等,常具斑纹或条纹", "floweringColor": "白、粉、黄、紫红等,常具斑纹或条纹",
"floweringShape": "花姿如蝶唇瓣3裂具卷须", "floweringShape": "花姿如蝶唇瓣3裂具卷须",
"flowerDiameter": 90 "flowerDiameter": 90,
classificationId: ''
} }
} }
@ -82,9 +104,47 @@ export default {
name: '请输入名称', 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) { 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') { if (this.type === 'add') {
// id
if (data.classificationId === '') {
this.$message.error('请设置分类')
done(false)
return
}
this.$api.flower.save(data).then(res => { this.$api.flower.save(data).then(res => {
if (res.code === 200) { if (res.code === 200) {
this.$message.success(res.msg) 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

@ -9,15 +9,24 @@
<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 }"> <template #name="{ record }">
<div class="flex flex-center flex-justify-start"> <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" fit="cover"
:alt="record.id" />
<div v-else>
<upload @ok="upload(record, $event)" type="image" />
</div>
<div class="ml-10">{{ record.name }}</div> <div class="ml-10">{{ record.name }}</div>
</div> </div>
</template> </template>
<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 }"> <template #menu="{ record }">
<div class="flex flex-center"> <div class="flex flex-center">
<edit type="edit" :info="record" @ok="fetchList" /> <edit type="edit" :info="record" @ok="fetchList" />
<a-button type="text" @click="changeHot(record)">{{record.isHot === 0 ?'设置热门':'取消热门'}}</a-button> <linkLibrary :id="record.id" />
<upload @ok="upload(record,$event)"/>
<a-popconfirm content="确认删除该条数据" @ok="remove(record.id)"> <a-popconfirm content="确认删除该条数据" @ok="remove(record.id)">
<a-button type="text">删除</a-button> <a-button type="text">删除</a-button>
</a-popconfirm> </a-popconfirm>
@ -32,13 +41,15 @@
import navbar from '@/components/navbar/index.vue' import navbar from '@/components/navbar/index.vue'
import upload from "../../../components/upload/index.vue"; import upload from "../../../components/upload/index.vue";
import edit from './components/edit.vue' import edit from './components/edit.vue'
import linkLibrary from './components/link.vue'
import category from './components/category.vue' import category from './components/category.vue'
export default { export default {
components: { components: {
navbar, navbar,
edit, edit,
category, category,
upload upload,
linkLibrary
}, },
data() { data() {
return { return {
@ -65,6 +76,10 @@ export default {
title: '科/属', title: '科/属',
dataIndex: 'genus', dataIndex: 'genus',
}, },
{
title: '是否推荐',
slotName: 'hot',
},
{ {
title: "操作", title: "操作",
slotName: 'menu' slotName: 'menu'
@ -125,6 +140,4 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</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>