| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <template>
- <div class="foods admin-page">
- <el-card>
- <div slot="header">
- <span>食材管理</span>
- <el-button type="primary" size="mini" style="float:right" @click="openCreate">新建食材</el-button>
- <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
- <el-select
- v-model="categoryFilter"
- placeholder="分类筛选"
- size="mini"
- style="float:right;margin-right:12px"
- clearable
- @change="loadList"
- >
- <el-option label="全部分类" value="" />
- <el-option label="蔬菜" value="蔬菜" />
- <el-option label="水果" value="水果" />
- <el-option label="肉类" value="肉类" />
- <el-option label="水产" value="水产" />
- <el-option label="蛋奶" value="蛋奶" />
- <el-option label="豆类" value="豆类" />
- <el-option label="谷物" value="谷物" />
- <el-option label="坚果" value="坚果" />
- <el-option label="调味品" value="调味品" />
- <el-option label="其他" value="其他" />
- </el-select>
- </div>
- <div style="overflow:auto;max-height:calc(100vh - 300px);">
- <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
- <el-table-column prop="id" label="ID" width="80" />
- <el-table-column prop="name" label="名称" />
- <el-table-column prop="category" label="分类" width="100" />
- <el-table-column prop="calories" label="热量(kcal)" width="100" />
- <el-table-column prop="protein" label="蛋白质(g)" width="100" />
- <el-table-column prop="carbs" label="碳水(g)" width="100" />
- <el-table-column prop="fat" label="脂肪(g)" width="100" />
- <el-table-column prop="fiber" label="膳食纤维(g)" width="100" />
- <el-table-column prop="energyKj" label="能量(kJ)" width="100" />
- <el-table-column prop="starch" label="淀粉(g)" width="100" />
- <el-table-column prop="cholesterol" label="胆固醇(mg)" width="100" />
- <el-table-column label="应季月份" width="180">
- <template slot-scope="{ row }">
- <span v-if="row.months && row.months.length">{{ row.months.map(function(m) { return m + '月' }).join('、') }}</span>
- <span v-else style="color:#999">未设置</span>
- </template>
- </el-table-column>
- <el-table-column prop="status" label="状态" width="80" />
- <el-table-column label="操作" width="200" fixed="right">
- <template slot-scope="{ row }">
- <el-button size="mini" type="primary" @click="editItem(row)">编辑</el-button>
- <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
- <el-button size="mini">
- 更多<i class="el-icon-arrow-down el-icon--right"></i>
- </el-button>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="delete" icon="el-icon-delete">删除</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-card>
- <el-dialog :title="editId ? '编辑食材' : '新建食材'" :visible.sync="dialogVisible" width="600px">
- <el-form label-width="120px">
- <el-form-item label="名称">
- <el-input v-model="form.name" />
- </el-form-item>
- <el-form-item label="分类">
- <el-select v-model="form.category" style="width:100%">
- <el-option label="蔬菜" value="蔬菜" />
- <el-option label="水果" value="水果" />
- <el-option label="肉类" value="肉类" />
- <el-option label="水产" value="水产" />
- <el-option label="蛋奶" value="蛋奶" />
- <el-option label="豆类" value="豆类" />
- <el-option label="谷物" value="谷物" />
- <el-option label="坚果" value="坚果" />
- <el-option label="调味品" value="调味品" />
- <el-option label="其他" value="其他" />
- </el-select>
- </el-form-item>
- <el-form-item label="热量(kcal/100g)">
- <el-input-number v-model="form.calories" :min="0" style="width:100%" />
- </el-form-item>
- <el-form-item label="蛋白质(g)">
- <el-input-number v-model="form.protein" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="碳水(g)">
- <el-input-number v-model="form.carbs" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="脂肪(g)">
- <el-input-number v-model="form.fat" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="膳食纤维(g)">
- <el-input-number v-model="form.fiber" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="能量(kJ/100g)">
- <el-input-number v-model="form.energyKj" :min="0" style="width:100%" />
- </el-form-item>
- <el-form-item label="淀粉(g/100g)">
- <el-input-number v-model="form.starch" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="胆固醇(mg/100g)">
- <el-input-number v-model="form.cholesterol" :min="0" :precision="1" style="width:100%" />
- </el-form-item>
- <el-form-item label="单位">
- <el-input v-model="form.unit" placeholder="如: 克、个、份" />
- </el-form-item>
- <el-form-item label="应季月份">
- <el-checkbox-group v-model="form.months">
- <el-checkbox v-for="m in 12" :key="m" :label="m">{{ m }}月</el-checkbox>
- </el-checkbox-group>
- </el-form-item>
- <el-form-item label="状态">
- <el-select v-model="form.status" style="width:100%">
- <el-option label="启用" value="active" />
- <el-option label="停用" value="inactive" />
- </el-select>
- </el-form-item>
- </el-form>
- <div slot="footer">
- <el-button @click="dialogVisible = false">取消</el-button>
- <el-button type="primary" @click="saveItem">保存</el-button>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- import { getFoodDetail, saveFoodMonths } from '@/api/admin'
- export default {
- name: 'Foods',
- data() {
- return {
- loading: false,
- list: [],
- dialogVisible: false,
- categoryFilter: '',
- keyword: '',
- editId: null,
- form: {
- name: '',
- category: '',
- calories: 0,
- protein: 0,
- carbs: 0,
- fat: 0,
- fiber: 0,
- energyKj: 0,
- starch: 0,
- cholesterol: 0,
- unit: '克',
- status: 'active',
- months: []
- }
- }
- },
- created() {
- this.loadList()
- },
- methods: {
- async loadList() {
- this.loading = true
- try {
- const baseURL = process.env.VUE_APP_BASE_API || ''
- const token = localStorage.getItem('token')
- const axios = this.$axios || (await import('axios')).default
- const res = await axios.post(baseURL + '/api/admin/foods/list', { category: this.categoryFilter || undefined, keyword: this.keyword || undefined }, {
- headers: { Authorization: 'Bearer ' + token }
- })
- this.list = res.data && res.data.data || []
- } catch (e) {
- this.$message && this.$message.error && this.$message.error('加载失败')
- } finally {
- this.loading = false
- }
- },
- handleSearch() {
- this.page = 1
- this.loadList()
- },
- openCreate() {
- this.editId = null
- this.form = { name: '', category: '', calories: 0, protein: 0, carbs: 0, fat: 0, fiber: 0, energyKj: 0, starch: 0, cholesterol: 0, unit: '克', status: 'active', months: [] }
- this.dialogVisible = true
- },
- async editItem(row) {
- this.editId = row.id
- this.form = {
- name: row.name || '',
- category: row.category || '',
- calories: row.calories || 0,
- protein: row.protein || 0,
- carbs: row.carbs || 0,
- fat: row.fat || 0,
- fiber: row.fiber || 0,
- energyKj: row.energyKj || 0,
- starch: row.starch || 0,
- cholesterol: row.cholesterol || 0,
- unit: row.unit || '克',
- status: row.status || 'active',
- months: []
- }
- try {
- const res = await getFoodDetail(row.id)
- if (res.data && res.data.months) {
- this.form.months = res.data.months
- }
- } catch (e) {
- // months stay empty
- }
- this.dialogVisible = true
- },
- async saveItem() {
- try {
- const baseURL = process.env.VUE_APP_BASE_API || ''
- const token = localStorage.getItem('token')
- const axios = this.$axios || (await import('axios')).default
- const data = { ...this.form }
- const months = data.months
- delete data.months
- let foodId = this.editId
- if (foodId) {
- data.id = foodId
- await axios.post(baseURL + '/api/admin/foods/update', data, {
- headers: { Authorization: 'Bearer ' + token }
- })
- this.$message && this.$message.success && this.$message.success('更新成功')
- } else {
- const res = await axios.post(baseURL + '/api/admin/foods/create', data, {
- headers: { Authorization: 'Bearer ' + token }
- })
- foodId = res.data && res.data.data && res.data.data.id
- this.$message && this.$message.success && this.$message.success('创建成功')
- }
- // Save seasonal months
- if (foodId && months && months.length > 0) {
- try {
- await saveFoodMonths(foodId, months)
- } catch (e) {
- this.$message && this.$message.warning && this.$message.warning('应季月份保存失败')
- }
- }
- this.dialogVisible = false
- this.loadList()
- } catch (e) {
- this.$message && this.$message.error && this.$message.error('保存失败')
- }
- },
- async deleteItem(row) {
- this.$confirm('确定删除 "' + row.name + '" 吗?', '提示', { type: 'warning' }).then(async () => {
- try {
- const baseURL = process.env.VUE_APP_BASE_API || ''
- const token = localStorage.getItem('token')
- const axios = this.$axios || (await import('axios')).default
- await axios.post(baseURL + '/api/admin/foods/delete', { id: row.id }, {
- headers: { Authorization: 'Bearer ' + token }
- })
- this.$message && this.$message.success && this.$message.success('删除成功')
- this.loadList()
- } catch (e) {
- this.$message && this.$message.error && this.$message.error('删除失败')
- }
- }).catch(() => {})
- },
- handleActionCmd(row, cmd) {
- switch (cmd) {
- case 'delete':
- this.deleteItem(row)
- break
- }
- }
- }
- }
- </script>
|