feat(data-input): 新增输入指标管理

- 输入指标改为数据库管理并绑定到药品数据
This commit is contained in:
LittleBoy 2025-07-20 14:56:11 +08:00
parent 6252553aee
commit 8632c1c606
17 changed files with 545 additions and 350 deletions

View File

@ -16,7 +16,7 @@
"@tiptap/vue-3": "^2.10.4",
"ant-design-vue": "^4.2.6",
"autoprefixer": "^10.4.20",
"axios": "^1.7.9",
"axios": "^1.8.2",
"dayjs": "^1.11.13",
"js-md5": "^0.8.3",
"pinia": "^2.3.0",

View File

@ -1,179 +1,194 @@
<template>
<div class="calc-container">
<div class="setting-container">
<div class="grid list-container grid-cols-2 gap-4 py-2">
<div class="input-item">
<div class="title">体重</div>
<div class="input">
<input type="number" v-model="commonValues.weight" placeholder="单位(kg)"/>
</div>
</div>
<div class="input-item">
<div class="title">24h尿素</div>
<div class="input">
<input type="number" v-model="commonValues.niaosu" placeholder="单位(mmol)"/>
</div>
</div>
<div class="calc-container">
<div class="setting-container">
<div class="grid list-container grid-cols-2 gap-4 py-2">
<div class="input-item">
<div class="title">体重</div>
<div class="input">
<input type="number" v-model="commonValues.weight" placeholder="单位(kg)"/>
</div>
</div>
<div class="input-item">
<div class="title">24h尿素</div>
<div class="input">
<input type="number" v-model="commonValues.niaosu" placeholder="单位(mmol)"/>
</div>
</div>
</div>
<Tabs>
<TabPane key="gut" tab="肠内制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='gut')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
<Tabs>
<TabPane key="gut" tab="肠内制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='gut')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
<TabPane key="vein" tab="静脉制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='vein')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
</Tabs>
</div>
<div class="text-center py-4">
<Button type="primary" @click="calcResult">测试计算</Button>
</div>
<ResultModal v-model:result="testResultValue" />
</div>
</TabPane>
<TabPane key="vein" tab="静脉制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='vein')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
</Tabs>
</div>
<div class="text-center py-4">
<Button type="primary" @click="calcResult">测试计算</Button>
</div>
<ResultModal v-model:result="testResultValue"/>
</div>
</template>
<script setup lang="ts">
import {onMounted,defineComponent, ref} from "vue";
import {onMounted, defineComponent, ref} from "vue";
import {TabPane, Tabs, Button, Modal} from "ant-design-vue";
import {inputProducts} from "@/pages/result/test/data-input.ts";
// import {inputProducts} from "@/pages/result/test/data-input.ts";
import ResultModal from "@/pages/result/components/result-modal.vue";
import {expressionList} from "@/service/api/result.ts";
import {parseExpression} from "@/core/string.ts";
import {getAllProduct} from "@/service/use-result-vars.ts";
import {getAllProductInput} from "@/service/api/product.ts";
const commonValues = ref({
weight: '',
niaosu: '',
weight: '',
niaosu: '',
})
defineComponent({
name: 'Calculation'
name: 'Calculation'
})
const ResultExpressionList = ref<ResultExpression[]>([]);
const settingList = ref<SettingItem[]>([])
const testResultValue = ref<ResultItem[]>([])
const productValues = getAllProduct();
onMounted(()=>{
expressionList().then((res) => {
ResultExpressionList.value = res.list;
});
const setting: SettingItem[] = []
inputProducts.forEach(it => {
setting.push({
title: it.name,
key: it.key,
value: '',
placeholder: it.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.unit,
})
if (it.addition) {
setting.push({
title: it.name,
key: it.addition.key,
value: '',
placeholder: it.addition.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.addition.unit,
})
}
})
settingList.value = setting
onMounted(() => {
expressionList().then((res) => {
ResultExpressionList.value = res.list;
});
initInputList().then(() => {
console.log("init input setting success")
})
})
function runCode(expression: string, vars: any) {
return new Function('vars', `with(vars) { return ${expression};}`)(vars)
}
function getResultValues(){
//
const result:{
[key: string]: number
} = {};
const {niaosu,weight} = commonValues.value
const inputs: { [key: string]: number }= {
niaosu: niaosu ?Number(niaosu): 0,
weight: weight ?Number(weight): 0,
async function initInputList() {
const setting: SettingItem[] = []
const inputProducts = await getAllProductInput();
inputProducts.forEach(it => {
setting.push({
title: it.name,
key: it.key,
value: '',
placeholder: it.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.unit,
})
if (it.addition) {
setting.push({
title: it.name,
key: it.addition.key,
value: '',
placeholder: it.addition.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.addition.unit,
})
}
settingList.value.forEach(it=>{
inputs[it.key] = it.value ? Number(it.value) : 0
})
ResultExpressionList.value.forEach(it=>{
const expression = parseExpression(it.expression);
if(expression.length == 0) return;
try{
const value = runCode(expression, {
...(productValues.value),
...result,
input: inputs,
})
result[it.key] = value;
}catch (e) {
Modal.warning({
title: '提示',
content: `计算出错:${(e as Error).message}`
})
console.error('getResultValues',e,expression)
}
})
return result;
})
settingList.value = setting
}
function calcResult(){
const result = getResultValues();
console.log('result',result)
const resultList:ResultItem[] = [];
ResultExpressionList.value.forEach(it=>{
resultList.push({
title:it.title,
key:it.key,
value: result[it.key] || 0
})
function runCode(expression: string, vars: any) {
return new Function('vars', `with(vars) { return ${expression};}`)(vars)
}
function getResultValues() {
//
const result: {
[key: string]: number
} = {};
const {niaosu, weight} = commonValues.value
const inputs: { [key: string]: number } = {
niaosu: niaosu ? Number(niaosu) : 0,
weight: weight ? Number(weight) : 0,
}
settingList.value.forEach(it => {
inputs[it.key] = it.value ? Number(it.value) : 0
})
ResultExpressionList.value.forEach(it => {
const expression = parseExpression(it.expression);
if (expression.length == 0) return;
try {
const value = runCode(expression, {
...(productValues.value),
...result,
input: inputs,
})
result[it.key] = value;
} catch (e) {
Modal.warning({
title: '提示',
content: `计算出错:${(e as Error).message}`
})
console.error('getResultValues', e, expression)
}
})
return result;
}
function calcResult() {
const result = getResultValues();
console.log('result', result)
const resultList: ResultItem[] = [];
ResultExpressionList.value.forEach(it => {
resultList.push({
title: it.title,
key: it.key,
value: result[it.key] || 0
})
console.log(resultList);
testResultValue.value = resultList;
})
console.log(resultList);
testResultValue.value = resultList;
}
</script>
<style scoped lang="scss">
.calc-container{
max-width: 90%;
margin: auto;
width: 600px;
.calc-container {
max-width: 90%;
margin: auto;
width: 600px;
}
.list-container {
margin-right: -4px;
padding-right: 4px;
margin-right: -4px;
padding-right: 4px;
}
.setting-input-scroller {
max-height: calc(100vh - 200px);
overflow: auto;
max-height: calc(100vh - 200px);
overflow: auto;
}
.setting-container {
.input {
@apply w-full relative border rounded mt-1 flex items-center bg-white overflow-hidden;
}
.input {
@apply w-full relative border rounded mt-1 flex items-center bg-white overflow-hidden;
}
input {
@apply flex-1 outline-0 block ml-2 py-1 mr-1;
}
input {
@apply flex-1 outline-0 block ml-2 py-1 mr-1;
}
.unit {
@apply absolute inset-y-0 right-0 px-2 py-1 bg-gray-100 block h-full text-center;
min-width: 34px;
}
.unit {
@apply absolute inset-y-0 right-0 px-2 py-1 bg-gray-100 block h-full text-center;
min-width: 34px;
}
}
</style>

View File

@ -65,7 +65,7 @@ onUnmounted(() => {
editor.destroy()
})
</script>
<style>
<style lang="scss">
.tiptap {
}
.tiptap{

View File

@ -204,7 +204,7 @@ function handleHideModal() {
.menu-item {}
.menu-icon {
font-size: 26px;
font-size: 30px;
}
.app-main-container {

13
src/pages/input/index.vue Normal file
View File

@ -0,0 +1,13 @@
<template>
<div>
<h1>Hello World</h1>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
h1 {
}
</style>

View File

@ -13,9 +13,11 @@ import { ProductCols } from "@/service/api/product";
import { getList, deleteProduct } from "@/service/api/product";
import useRequest from "@/service/useRequest";
import EditModal from "./edit-modal.vue"
import ProductInputModal from "./input/index.vue"
const editProduct = ref<Partial<ProductInfoModel>>();
const productInput = ref<Partial<ProductInfoModel>>();
// const formState = ref<{name?:string;category?:string}>({
// })
const searchParams = ref<ProductSearchParam>({
@ -90,14 +92,16 @@ function handleSearch(){
<th>制剂别名</th>
<th>类型</th>
<th v-for="th in ProductCols">{{ th.name }}</th>
<th width="100" class="text-center">计量单位</th>
<th width="150" class="text-center">操作</th>
<th width="100">计量单位</th>
<th width="180">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(tr, rowIndex) in allDataList?.list" :key="rowIndex">
<td>{{ tr.name }}</td>
<td>{{ tr.alias }}</td>
<td>
<span :title="tr.alias">{{ tr.alias }}</span>
</td>
<td>{{ tr.category == 'gut'?'肠内制剂':'静脉制剂' }}</td>
<td v-for="th in ProductCols">{{ (tr as any)[th.alias] || 'NULL' }}</td>
@ -105,6 +109,7 @@ function handleSearch(){
<td>
<Space :size="20">
<a @click="editProduct = tr">编辑</a>
<a @click="productInput = tr">输入指标</a>
<a @click="handleDelete(tr.id)">删除</a>
</Space>
</td>
@ -122,6 +127,7 @@ function handleSearch(){
</div>
</div>
<EditModal v-if="!!editProduct" v-model="editProduct" @saved="refresh" />
<ProductInputModal v-if="!!productInput" v-model="productInput" />
</div>
</template>
<style lang="scss"></style>

View File

@ -0,0 +1,161 @@
<template>
<Modal
:width="640" :open="!saveData" :footer="null" @cancel="handleCancel" :mask-closable="false"
:destroy-on-close="true" title="营养制剂输入指标"
>
<div class="result-table mt-4">
<Spin :spinning="loading">
<table class="table border">
<thead>
<tr>
<th>指标名称</th>
<th>指标Key</th>
<th width="120">输入提示</th>
<th>单位</th>
<th width="120">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(tr, rowIndex) in allDataList?.list" :key="rowIndex">
<td>{{ tr.name }}</td>
<td>{{ tr.key }}</td>
<td>{{ tr.placeholder }}</td>
<td>{{ tr.unit }}</td>
<td>
<Space :size="20">
<a @click="saveData = tr">编辑</a>
<a @click="handleDelete(tr.id)">删除</a>
</Space>
</td>
</tr>
</tbody>
</table>
<div v-if="!allDataList || allDataList?.total == 0" style="padding:30px;">
<Empty description="暂无数据"/>
</div>
</Spin>
<div class="text-center mt-4">
<Button type="primary" @click="handleCreateNew">添加指标</Button>
</div>
</div>
</Modal>
<Modal
:open="!!saveData" :width="640" :footer="null" :destroy-on-close="true" title="营养制剂输入指标"
:mask-closable="false" @cancel="saveData=undefined">
<div>
<Form
@finish="handleSave"
autocomplete="off"
:model="saveData"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 16 }"
>
<div class="py-8 px-10">
<div class="form-item-container">
<Form.Item label="指标名称" name="name"
:rules="[{ required: true, message: '请输入指标名称' }]">
<Input placeholder="请输入指标名称" v-model:value="saveData.name"/>
</Form.Item>
<Form.Item label="指标Key" name="key" :rules="[{ required: true, message: '请输入指标Key' }]">
<Input placeholder="请输入指标Key" v-model:value="saveData.key"/>
</Form.Item>
<Form.Item label="输入提示" name="placeholder">
<Input placeholder="请输入指标提示,留空默认使用:入液量(ml)" v-model:value="saveData.placeholder"/>
</Form.Item>
<Form.Item label="单位" name="unit">
<Input placeholder="请输入指标单位留空默认使用ml" v-model:value="saveData.unit"/>
</Form.Item>
</div>
</div>
<div class="text-center">
<Space :size="20">
<Button type="default" @click="saveData = undefined">取消</Button>
<Button :loading="saveLoading" type="primary" html-type="submit">保存</Button>
</Space>
</div>
</Form>
</div>
</Modal>
</template>
<script lang="ts" setup>
import {Empty, Modal, Space, Spin, Button, Form, Input, message} from "ant-design-vue";
import {onMounted, ref} from "vue";
import {
getProductDataInput,
saveProductDataInput,
deleteProductDataInput,
} from "@/service/api/product.ts";
import useRequest from "@/service/useRequest.ts";
const editData = defineModel<Partial<ProductInfoModel>>();
const saveData = ref<Partial<ProductDataInputModel>>()
const { loading:saveLoading, runAsync, error } = useRequest(saveProductDataInput, {
manual: true
})
const {
data: allDataList,
loading,
run,
refresh
} = useRequest(() => getProductDataInput(editData.value!.id), {manual: true})
function handleCancel() {
editData.value = undefined;
}
function handleCreateNew() {
saveData.value = {
product_id: editData.value!.id,
key: '',
name: '',
placeholder: '',
unit: '',
}
}
function deleteById(id: number) {
deleteProductDataInput(id).then(() => {
message.success('删除成功')
refresh()
})
}
function handleDelete(id: number) {
Modal.confirm({
title: '删除营养制剂数据',
content:'删除此数据后可能导致系统无法正常计算结果或导致系统异常,请确定要删除该数据吗?',
cancelText: '再想想',
okText: '删除',
okType: 'danger',
onOk: () => {
deleteById(id)
}
})
}
function handleSave() {
saveData.value = {
...saveData.value,
created_at: undefined,
updated_at: undefined,
status: undefined,
};
if(!saveData.value.placeholder){
saveData.value.placeholder = '入液量(ml)'
}
if(!saveData.value.unit){
saveData.value.unit = 'ml'
}
runAsync(saveData.value).then(() => {
refresh()
saveData.value = undefined;
})
}
onMounted(() => {
run()
})
</script>
<style scoped lang="scss">
</style>

View File

@ -1,157 +1,164 @@
<template>
<Modal :open="visible" width="600px" @cancel="visible = false" :maskClosable="false" :closable="false"
title="设置测试数据">
<div class="setting-container">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item">
<div class="title">体重</div>
<div class="input">
<input type="number" v-model="commonValues.weight" placeholder="单位(kg)"/>
</div>
</div>
<div class="input-item">
<div class="title">24h尿素</div>
<div class="input">
<input type="number" v-model="commonValues.niaosu" placeholder="单位(mmol)"/>
</div>
</div>
</div>
<Tabs>
<TabPane key="gut" tab="肠内制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='gut')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
<TabPane key="vein" tab="静脉制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='vein')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
</Tabs>
<Modal :open="visible" width="600px" @cancel="visible = false" :maskClosable="false" :closable="false"
title="设置测试数据">
<div class="setting-container">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item">
<div class="title">体重</div>
<div class="input">
<input type="number" v-model="commonValues.weight" placeholder="单位(kg)"/>
</div>
</div>
<template #footer>
<div class="flex justify-center mt-8">
<Button key="submit" type="primary" @click="handleOk">确定</Button>
<div class="input-item">
<div class="title">24h尿素</div>
<div class="input">
<input type="number" v-model="commonValues.niaosu" placeholder="单位(mmol)"/>
</div>
</div>
</div>
<Tabs>
<TabPane key="gut" tab="肠内制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='gut')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</template>
</Modal>
</div>
</TabPane>
<TabPane key="vein" tab="静脉制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 max-h-[400px] overflow-auto">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='vein')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
</Tabs>
</div>
<template #footer>
<div class="flex justify-center mt-8">
<Button key="submit" type="primary" @click="handleOk">确定</Button>
</div>
</template>
</Modal>
</template>
<script setup lang="ts">
import {Modal, Button, Tabs, TabPane} from 'ant-design-vue'
import {defineComponent, onMounted, ref} from "vue";
import {inputProducts} from "@/pages/result/test/data-input.ts";
import {defineComponent, onMounted, ref} from "vue";
// import {inputProducts} from "@/pages/result/test/data-input.ts";
import {getAllProductInput} from "@/service/api/product.ts";
type InputValuesType = {
[key: string]: number;
[key: string]: number;
}
const inputValues = defineModel('inputValues')
const commonValues = ref({
weight: '',
niaosu: '',
weight: '',
niaosu: '',
})
const visible = defineModel('visible', {type: Boolean})
defineComponent({
name: 'InputSetting'
name: 'InputSetting'
})
const settingList = ref<SettingItem[]>([])
onMounted(() => {
const storeValues = (() => {
const content = localStorage.getItem('yy_input_setting')
try {
if (!content) {
return null;
}
return JSON.parse(content)
} catch (e) {
}
return null;
})();
if (storeValues && Object.keys(storeValues).length > 0) {
inputValues.value = storeValues
commonValues.value = {
weight: storeValues['weight'] && storeValues['weight'] !== 0 ? storeValues['weight'] : '',
niaosu: storeValues['niaosu'] && storeValues['niaosu'] !== 0 ? storeValues['niaosu'] : '',
}
}
const setting: SettingItem[] = []
inputProducts.forEach(it => {
setting.push({
title: it.name,
key: it.key,
value: storeValues && storeValues[it.key] !== 0 ? storeValues[it.key] : '',
placeholder: it.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.unit,
})
if (it.addition) {
setting.push({
title: it.name,
key: it.addition.key,
value: storeValues && storeValues[it.addition.key] !== 0 ? storeValues[it.addition.key] : '',
placeholder: it.addition.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.addition.unit,
})
}
})
const lines:string[] = []
lines.push(`weight体重`)
lines.push(`niaosu24h尿素`)
setting.forEach(it => {
lines.push(`${it.key}${it.title}`)
})
console.log(lines.join("\n"));
settingList.value = setting
initInputList().then(() => {
console.log('init input setting success')
})
})
function handleOk() {
const values: InputValuesType = {
weight: Number(commonValues.value.weight || '0'),
niaosu: Number(commonValues.value.niaosu || '0'),
async function initInputList() {
const storeValues = (() => {
const content = localStorage.getItem('yy_input_setting')
try {
if (!content) {
return null;
}
return JSON.parse(content)
} catch (e) {
}
settingList.value.forEach(it => {
values[it.key] = it.value ? Number(it.value) : 0
return null;
})();
if (storeValues && Object.keys(storeValues).length > 0) {
inputValues.value = storeValues
commonValues.value = {
weight: storeValues['weight'] && storeValues['weight'] !== 0 ? storeValues['weight'] : '',
niaosu: storeValues['niaosu'] && storeValues['niaosu'] !== 0 ? storeValues['niaosu'] : '',
}
}
const inputProducts = await getAllProductInput();
const setting: SettingItem[] = []
inputProducts.forEach(it => {
setting.push({
title: it.name,
key: it.key,
value: storeValues && storeValues[it.key] !== 0 ? storeValues[it.key] : '',
placeholder: it.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.unit,
})
localStorage.setItem('yy_input_setting', JSON.stringify(values))
visible.value = false
inputValues.value = values;
// if (it.addition) {
// setting.push({
// title: it.name,
// key: it.addition.key,
// value: storeValues && storeValues[it.addition.key] !== 0 ? storeValues[it.addition.key] : '',
// placeholder: it.addition.placeholder, // + (it.unit?`(${it.unit})`:'')
// type: it.type,
// unit: it.addition.unit,
// })
// }
})
const lines: string[] = []
lines.push(`weight体重`)
lines.push(`niaosu24h尿素`)
setting.forEach(it => {
lines.push(`${it.key}${it.title}`)
})
// console.log(lines.join("\n"));
settingList.value = setting
}
function handleOk() {
const values: InputValuesType = {
weight: Number(commonValues.value.weight || '0'),
niaosu: Number(commonValues.value.niaosu || '0'),
}
settingList.value.forEach(it => {
values[it.key] = it.value ? Number(it.value) : 0
})
localStorage.setItem('yy_input_setting', JSON.stringify(values))
visible.value = false
inputValues.value = values;
}
</script>
<style scoped>
.list-container {
margin-right: -4px;
padding-right: 4px;
margin-right: -4px;
padding-right: 4px;
}
.setting-container {
.input {
@apply w-full border rounded mt-1 flex items-center;
}
.input {
@apply w-full border rounded mt-1 flex items-center;
}
input {
@apply flex-1 outline-0 block ml-2 py-1 mr-1;
}
input {
@apply flex-1 outline-0 block ml-2 py-1 mr-1;
}
.unit {
@apply px-2 py-1 bg-gray-200 block h-full text-center;
min-width: 34px;
}
.unit {
@apply px-2 py-1 bg-gray-200 block h-full text-center;
min-width: 34px;
}
}
</style>

View File

@ -59,28 +59,28 @@ function handleSearch() {
<div class="data-fields-container">
<PageHeader title="登录账号管理" description="* 超级管理员: 拥有最高权限,可使用全部管理功能。管理员:普通管理权限,不可新建、删除、编辑账号。" />
<div class="search-form">
<Space :size="20">
<Space class="form-item">
<div class="grid xl:flex lg:grid-cols-4 md:grid-cols-2 grid-cols-1 w-full gap-4">
<div class="flex items-center gap-2">
<span>姓名</span>
<Input class="search-item" placeholder="请输入姓名" v-model:value="searchParams.nickname" />
</Space>
<Space class="form-item">
<Input class="search-item flex-1" placeholder="请输入姓名" v-model:value="searchParams.nickname" />
</div>
<div class="flex items-center gap-2">
<span>账号</span>
<Input class="search-item" placeholder="请输入账号" v-model:value="searchParams.account" />
</Space>
<Space class="form-item">
<Input class="search-item flex-1" placeholder="请输入账号" v-model:value="searchParams.account" />
</div>
<div class="flex items-center gap-2">
<span>类型</span>
<Select class="search-item" v-model:value="searchParams.role" style="width: 200px;">
<Select class="search-item flex-1" v-model:value="searchParams.role" style="width: 200px;">
<SelectOption v-for="(it, opIndex) in AllRoleList" :key="opIndex" :value="it.value">{{ it.label
}}
</SelectOption>
</Select>
</Space>
<Space class="form-item" :size="15">
</div>
<div class="flex items-center gap-2" :size="15">
<Button :icon="h(SearchOutlined)" type="primary" @click="handleSearch">查询</Button>
<Button v-if="userInfo?.role == 'root'" :icon="h(PlusOutlined)" class="btn-info" @click="editUser = { id: 0 }">新增</Button>
</Space>
</Space>
</div>
</div>
</div>
<div class="search-result-table">
<div>

View File

@ -70,7 +70,7 @@ function onValuesChange() {
<Form.Item label="密码" name="password" :rules="passwordRules">
<Input placeholder="请输入6-12位密码" type="password" v-model:value="userData.password" />
<template #extra v-if="editUser?.id">
<div>留空不修改密码</div>
<div>留空不修改密码</div>
</template>
</Form.Item>

View File

@ -32,13 +32,13 @@ export const routes:RouteRecordRaw[] = [
component: () => import('./pages/result/index.vue')
},
// {
// path: 'ttt',
// name: 'ttt',
// path: 'input',
// name: 'input',
// meta: {
// title: '输出计算',
// icon:'icon-calculator'
// title: '输入指标',
// icon:'icon-add'
// },
// component: () => import('./pages/T.vue')
// component: () => import('./pages/input/index.vue')
// },
{
path: 'product-data',

View File

@ -18,6 +18,17 @@ export async function getList(param: ProductSearchParam) {
await sleep(200);
return await post<DataList<ProductInfoModel>>(`/product/all`, param);
}
export async function getProductDataInput(product_id: number) {
await sleep(200);
return await post<DataList<ProductDataInputModel>>(`/input/all`, { product_id });
}
export async function saveProductDataInput(data: Partial<ProductDataInputModel>) {
await sleep(200);
return await post<DataList<ProductDataInputModel>>(`/input/save`, data);
}
export async function deleteProductDataInput(id: number) {
return await post<DataList<ProductDataInputModel>>(`/input/delete`, { id });
}
export function deleteProduct(id: number) {
return post(`/product/delete`, { id })
@ -26,3 +37,9 @@ export async function saveProduct(params: Partial<ProductInfoModel>) {
await sleep(200);
return await post(`/product/save`, params);
}
export async function getAllProductInput(){
const result = await post<DataList<ProductDataInputModel>>(`/input/all`)
return result.list;
}

View File

@ -14,58 +14,6 @@ type InputValue = {
}
}
/*
{
"weight": 50,
"niaosu": 12,
"ruineng": 10,
"ruidai": 0,
"ruixian": 0,
"ruigao": 0,
"ruisu": 0,
"nengquanli": 0,
"kangquanli": 0,
"kangquangan": 0,
"baipuli": 0,
"ailunduo": 0,
"weiwo": 0,
"jiaweiti": 0,
"yilijia": 0,
"ruiyixi": 0,
"nengquansu": 0,
"ansu": 0,
"quanansu": 0,
"yilijia100": 0,
"shui": 0,
"anjisuan_ruye": 0,
"yilijia100_ruye": 0,
"quanansu_ruye": 0,
"ansu_ruye": 0,
"nengquansu_ruye": 0,
"ruqingdanbailiang": 0,
"ruianji": 0,
"quanyingda": 0,
"likawen": 0,
"lefanming85": 0,
"lefanming114": 0,
"anjisuan": 0,
"litai": 0,
"lineng": 0,
"liwen": 0,
"youwen": 0,
"yingtuolipite20": 0,
"yingtuolipite30": 0,
"putaotangluhuana5": 0,
"putaotang5": 0,
"putaotang10": 0,
"putaotang50": 0,
"luhuana09": 0,
"luhuana10": 0,
"geliefusi": 0,
"luhuajia": 0,
"baidanbai": 0
}
*/
const inputList: InputValue[] = [
{name: '体重', key: 'weight',},
{name: '24h尿素', key: 'niaosu',},

View File

@ -54,7 +54,12 @@
.overflow-auto{
scrollbar-gutter: stable;
}
th,td{
text-align: left;
}
.text-center{
text-align: center;
}
[type=reset],
[type=submit],
button,
@ -210,12 +215,12 @@ img {
}
.menu-text{
display: block;
@include media-breakpoint-down(lg) {
font-size: 12px;;
}
@include media-breakpoint-down(md) {
display: none;
}
//@include media-breakpoint-down(lg) {
// font-size: 12px;;
//}
//@include media-breakpoint-down(md) {
// display: none;
//}
}
.search-form {
@ -261,11 +266,11 @@ img {
min-width: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
border-bottom: 1px solid #e8e8ec;
padding: 15px 16px;
padding: 15px 10px;
}
th {

View File

@ -25,6 +25,28 @@ declare type ProductInfoModel = {
updated_at: Date | string;
status: number;
}
interface ProductDataInputModel {
id: number;
/**
* ID(ProductInfoModel.id)
*/
product_id: number;
/**
*
*/
name: string;
/**
*
*/
key: string;
type?: string;
placeholder: string;
unit: string;
created_at: Date | string;
updated_at: Date | string;
status: number;
}
declare type ResultExpression = {
id: number;
@ -63,4 +85,5 @@ interface ResultItem {
title:string;
key:string;
value:number;
}
}

View File

@ -16,7 +16,7 @@ const themeConfig = {
export default {
content: [
'./index.html',
'./src/**/*.{mjs,js,ts,jsx,tsx,html,vue}'
'./src/**/*.{mjs,js,ts,jsx,tsx,html,vue,scss}'
],
theme: {
extend: {

View File

@ -6,7 +6,7 @@ console.log(
['NODE', 'NODE_ENV', 'npm_execpath', 'OS'].map(key => (process.env[key]))
)
const devServer = {
default: 'http://localhost:3001',
default: 'http://localhost:23002',
test: 'http://43.136.175.109:50001'
}