Browse Source

rebase 冲突

feature/three
LiLongLong 3 months ago
parent
commit
ec73a6bf6f
  1. 1
      package.json
  2. 22
      src/apis/crafts.ts
  3. 1
      src/assets/images/icon_add_s.svg
  4. 1
      src/assets/images/icon_arr_s.svg
  5. 1
      src/assets/images/icon_del_s.svg
  6. 36
      src/assets/styles/tailwind.css
  7. 1
      src/main.ts
  8. 18
      src/stores/useLiquidsStore.ts
  9. 217
      src/views/craft/AddCraftDialog.vue
  10. 40
      src/views/craft/TransferLeft.vue
  11. 118
      src/views/craft/TransferRight.vue
  12. 114
      src/views/craft/craftType.ts
  13. 148
      src/views/craft/index.vue

1
package.json

@ -43,7 +43,6 @@
"postcss-url": "^10.1.3", "postcss-url": "^10.1.3",
"postcss-viewport-units": "^0.1.6", "postcss-viewport-units": "^0.1.6",
"postcss-write-svg": "^3.0.1", "postcss-write-svg": "^3.0.1",
"tailwindcss": "^4.1.4",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
"ws": "^8.18.1" "ws": "^8.18.1"

22
src/apis/crafts.ts

@ -0,0 +1,22 @@
import http from 'libs/http'
interface Craft {
id?: number
name?: string
steps?: string
oresId?: number
}
export const getCraftList = (params: any): Promise<any> => http.get(`/crafts/list/${params.oresId}`)
export const createCraft = (params: Craft): Promise<any> => http.post('/crafts', params)
export const updateCraft = (params: Craft): Promise<any> => http.put(`/crafts`, params)
export const delCraft = (ids: string): Promise<any> => http.delete(`/crafts/${ids}`)
// 开始执行工艺
export const startCraft = (params: { heatId: string }): Promise<any> => http.post(`/crafts/start`, params)
// 加热区配置工艺
export const setCraft = (params: { heatId?: string | number, craftId?: string | number }): Promise<any> => http.post(`/crafts/set`, params)

1
src/assets/images/icon_add_s.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="26.303199768066406" height="26.303173065185547" viewBox="0 0 26.303199768066406 26.303173065185547"><g><path d="M24.5875,14.8666L14.8674,14.8666L14.8674,24.5882C14.8674,25.5356,14.099,26.3032,13.1516,26.3032C12.2043,26.3032,11.4359,25.5356,11.4359,24.5882L11.4359,14.8666L1.71574,14.8666C0.767578,14.8666,0,14.099,0,13.1516C0,12.2046,0.767666,11.4366,1.71574,11.4366L11.4359,11.4366L11.4359,1.71495C11.4359,0.76793,12.2042,0,13.1516,0C14.099,0,14.8673,0.767959,14.8673,1.71495L14.8673,11.4367L24.5874,11.4367C25.5356,11.4367,26.3032,12.2046,26.3032,13.1515C26.3032,14.0989,25.5356,14.8665,24.5874,14.8665L24.5875,14.8666Z" fill="#479CF1" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

1
src/assets/images/icon_arr_s.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="15" height="23" viewBox="0 0 15 23"><g transform="matrix(-1,0,0,-1,30,46)"><path d="M27.436500000000002,23C27.436500000000002,23,30,25.37044,30,25.37044C30,25.37044,20.12696,34.5,20.12696,34.5C20.12696,34.5,30,43.629599999999996,30,43.629599999999996C30,43.629599999999996,27.436500000000002,46,27.436500000000002,46C27.436500000000002,46,15,34.5,15,34.5C15,34.5,27.436500000000002,23,27.436500000000002,23C27.436500000000002,23,27.436500000000002,23,27.436500000000002,23Z" fill-rule="evenodd" fill="#384D5D" fill-opacity="1"/></g></svg>

1
src/assets/images/icon_del_s.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="33" height="33" viewBox="0 0 33 33"><defs><clipPath id="master_svg0_685_8832"><rect x="0" y="0" width="33" height="33" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_685_8832)"><g><path d="M28.5707296875,29.2627375C27.6653296875,30.1682375,26.1906296875,30.1682375,25.2831296875,29.2627375L4.4580476875,8.4376975C3.5526096875,7.5301975,3.5505466875,6.0575675,4.4580476875,5.1500705C5.3614196875,4.2425705,6.8361096875000005,4.2425705,7.7477296875,5.1500705L28.5707296875,25.9730375C29.4761296875,26.8847375,29.4803296875,28.3552375,28.5707296875,29.2627375ZM28.5460296875,8.4273875L7.7229796875000005,29.2503375C6.8134196875,30.1599375,5.3407996875,30.1599375,4.4332966875,29.2503375C3.5257966875,28.3449375,3.5257966875,26.8743375,4.4353596875,25.9627375L25.2583296875,5.1418205C26.1679296875,4.2343205,27.6426296875,4.2343205,28.5460296875,5.1397585C29.4555296875,6.0472575,29.4514296875,7.519887499999999,28.5460296875,8.4273875Z" fill="#7F7F7F" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

36
src/assets/styles/tailwind.css

@ -1,36 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.btn-dark {
display: flex;
justify-content: center;
align-items: center;
background: var(--primaryColor);
border: solid 1px var(--primaryColor);
border-radius: 4px;
color: white;
}
.btn-light {
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
border-radius: 4px;
color: var(--primaryColor);
border: solid 1px var(--primaryColor);
}
.btn-light:active {
background-color: #e5e5e5;
}
.btn-light-disabled {
color: #d6d6d6;
border: solid 1px #d6d6d6;
}
.component-page {
height: calc(100vh - var(--headerHeight) - var(--footerHeight));
width: calc(100vw - var(--menuAreaWidth));
background-color: #fff;
}
}

1
src/main.ts

@ -11,6 +11,7 @@ import App from './app.vue'
import router from './router' import router from './router'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import 'assets/styles/main.scss' import 'assets/styles/main.scss'
import 'assets/styles/tailwind.css'
const app = createApp(App) const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {

18
src/stores/useLiquidsStore.ts

@ -0,0 +1,18 @@
import { defineStore } from 'pinia'
interface liquids {
id: number
name: string
}
export const useLiquidStore = defineStore('liquid', () => {
const liquids: liquids[] = [{
id: 1,
name: '硫酸',
},{
id: 2,
name: '硝酸',
}]
return {
liquids,
}
})

217
src/views/craft/AddCraftDialog.vue

@ -0,0 +1,217 @@
<script lang="ts" setup>
import type { Craft, StepCmd, StepStruct, TransferRightType } from './craftType'
import { ElMessage } from 'element-plus'
import { ref } from 'vue'
import { StepCmdDescMap } from './craftType'
import TransferLeft from './TransferLeft.vue'
import TransferRight from './TransferRight.vue'
const emit = defineEmits<{
(e: 'ok', craft: Craft): void
}>()
const visible = ref(false)
const stepStructs = ref<StepStruct[]>([])
const craftObj = ref<Craft>({})
const transferRight = ref<TransferRightType | null>(null)
const stepCmds: StepCmd[] = [
// 'upTray',
// 'downTray',
'addLiquid',
// 'moveToSol',
// 'moveToHeat',
'shaking',
'startHeating',
// 'stopHeating',
'takePhoto',
// 'delay',
]
const openDialog = () => {
visible.value = true
}
const closeDialog = () => {
stepStructs.value = []
craftObj.value.name = ''
visible.value = false
}
const editDialog = (craftInfo: Craft) => {
console.log('craftInfo---', craftInfo)
craftObj.value = { ...craftInfo }
if (craftInfo && craftInfo.steps) {
const step = JSON.parse(craftInfo.steps)
console.log('step---', step)
stepStructs.value = step
}
openDialog()
}
function onConfirm() {
if (!craftObj.value.name) {
ElMessage.warning('请输入工艺名称')
return
}
craftObj.value.steps = JSON.stringify(stepStructs.value)
console.log('craftObj-22--', craftObj.value)
emit('ok', craftObj.value)
}
function addStep(step: StepCmd) {
let st: StepStruct
if (step === 'addLiquid') {
st = {
method: step,
params: {
tubeSolList: [{
tubeNum: 1,
addLiquidList: [{
solId: 1,
volume: 10,
}],
}],
},
}
}
else if (step === 'startHeating') {
st = {
method: step,
params: {
temperature: 100,
},
}
}
else if (step === 'delay') {
st = {
method: step,
params: {
second: 10,
},
}
}
else if (step === 'shaking') {
st = {
method: step,
params: {
second: 30,
},
}
}
else {
st = {
method: step,
}
}
stepStructs.value = [...stepStructs.value, st]
}
function onStepItemDel(order: number) {
stepStructs.value = stepStructs.value.filter((s, i) => i !== order - 1)
}
function transferChange(stepData: StepStruct, order: number) {
console.log('order === ', stepStructs.value, stepData, order)
// if (order) {
// stepStructs.value[order - 1] = stepData
// }
// console.log('stepStructs.value==1===', stepStructs.value)
}
defineExpose({
openDialog,
closeDialog,
editDialog,
})
</script>
<template>
<el-dialog v-model="visible" title="添加工艺" style="width:70vw; height:65vh">
<div>
<div class="mt-5 mb-8 flex items-center">
<label class="font-medium mr-4">工艺名称</label>
<el-input
v-model.trim="craftObj.name"
style="width: 200px"
size="small"
type="text"
placeholder="请输入名称"
class="flex-auto bg-[#f6f6f6] h-11 leading-10 rounded-sm px-4"
/>
</div>
<div class="craft-title">
<div>
工艺步骤
</div>
<div class="title-right">
选择的步骤
</div>
</div>
<div class="step-content">
<div class="transfer-left">
<TransferLeft v-for="cmd in stepCmds" :key="cmd" :title="StepCmdDescMap[cmd]" @click="addStep(cmd)" />
</div>
<div v-if="stepStructs && stepStructs.length" class="transfer-right">
<TransferRight v-for="(step, idx) in stepStructs" ref="transferRight" :key="idx" :order="idx + 1" :step="step" @del="onStepItemDel" @transfer-change="transferChange" />
</div>
<div v-else>
<el-empty description="description">
<template #description>
未选择工艺步骤
</template>
</el-empty>
</div>
</div>
<div class="footer">
<el-button size="small" @click="closeDialog">
取消
</el-button>
<el-button type="primary" size="small" @click="onConfirm">
确定
</el-button>
</div>
</div>
</el-dialog>
</template>
<style lang="scss" scoped>
.transfer-left{
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.4rem;
width: 12.5rem;
place-items: center;
height: 3rem;
}
.transfer-right{
max-height: 40vh;
overflow: auto;
}
.step-content{
margin-top:1rem;
display: grid;
grid-template-columns: 1fr 1fr;
height: 21rem;
}
.footer{
display: flex;
height: 5rem;
justify-content: center;
align-items: center;
}
.craft-title{
display: grid;
grid-template-columns: 1fr 1fr;
div{
font-size:12px;
margin-top: 5px;
}
.title-right{
display: flex;
justify-content: center;
}
}
</style>

40
src/views/craft/TransferLeft.vue

@ -0,0 +1,40 @@
<script lang="ts" setup>
defineProps<{ title: string }>()
</script>
<template>
<div class="transfer-left btn-light">
{{ title }}
<img
src="@/assets/images/icon_add_s.svg"
alt="add"
class="add_icon"
>
</div>
</template>
<style lang="scss" scoped>
.transfer-left{
display: flex;
}
.btn-light{
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
border-radius: 4px;
color: '#1989fa';
border: solid 1px '#1989fa';
height: 11px;
}
.add_icon {
right: 1rem;
width: .875rem;
}
@media (min-width: 56.25rem) {
.add_icon {
right: 1.875rem;
}
}
</style>

118
src/views/craft/TransferRight.vue

@ -0,0 +1,118 @@
<script lang="ts" setup>
import type { StepStruct } from './craftType'
import { useLiquidStore } from '@/stores/useLiquidsStore'
import { onMounted, ref, watch } from 'vue'
import { StepCmdDescMap, tubeSolList } from './craftType'
const props = defineProps<{
order: number
step: StepStruct
}>()
const $emit = defineEmits<{
(e: 'del', order: number): void
(e: 'transferChange', stepData: StepStruct, order: number): void
}>()
const liquidStore = useLiquidStore()
const stepInfo = ref(props.step)
onMounted(() => {
console.log('liquidStore---', props.step)
})
watch(stepInfo, (newVal) => {
console.log('newVale === ', newVal)
$emit('transferChange', newVal, props.order)
}, {
deep: true,
})
// const onDel = () => {
// emit('del', props.order)
// }
</script>
<template>
<div class="right-contaner">
<section class="right-main">
<span class="right-seq">{{ order }}</span>
<span class="right-base">{{ StepCmdDescMap[stepInfo.method] }}</span>
<div class="text-item" @click="$emit('del', order)">
<img class="item-img" src="@/assets/images/icon_del_s.svg" alt="del">
</div>
</section>
<template v-if="stepInfo.method !== 'takePhoto'">
<section v-if="stepInfo.method === 'addLiquid'" class="right-liquid right-base">
<div v-for="(tubeItem, index) in stepInfo.params.tubeSolList" :key="index" class="right-liquid">
<el-select v-model="tubeItem.tubeNum" size="small" placeholder="Select" style="width: 100px" class="right-base">
<el-option v-for="item in tubeSolList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<div v-for="(liquidItem, liquidIndex) in tubeItem.addLiquidList" :key="liquidIndex" class="right-liquid right-base">
<el-select v-model="liquidItem.solId" size="small" placeholder="Select" style="width: 100px" class="right-base">
<el-option v-for="item in liquidStore.liquids" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<div>
<el-input v-model.number="liquidItem.volume" size="small" style="width: 100px" />
<span class="ml-2">ml</span>
</div>
</div>
</div>
</section>
<section v-if="stepInfo.method === 'shaking' || stepInfo.method === 'delay'" class="right-shaking">
<div class="flex items-center right-base">
<el-input v-model.number="stepInfo.params.second" style="width: 100px" size="small right-base" />
<span class="ml-2"></span>
</div>
</section>
</template>
</div>
<div style="height:5px;background: white;" />
</template>
<style lang="scss" scoped>
.right-contaner{
background-color: rgb(82 148 215 / .06);
border-radius: 10px;
}
.right-main{
display: flex;
align-items: center;
}
.right-base{
font-size: 1rem;
line-height: 1.5rem;
margin-left: 1.25rem;
}
.text-item{
margin-left: auto;
width: 2.5rem;
height: 2.5rem;
display: flex;
justify-content: center;
align-items: center;
.item-img{
width:1rem
}
}
.right-liquid{
display: flex;
height: 2.5rem;
}
.right-shaking{
display: flex;
height: 2.5rem;
}
.right-seq{
padding-left: 20px;
color: #19b370;
}
.el-select-dropdown__item{
display: flex;
align-items: center;
}
</style>

114
src/views/craft/craftType.ts

@ -0,0 +1,114 @@
interface UpTrayStepStruct {
method: 'upTray'
}
interface DownTrayStepStruct {
method: 'downTray'
}
interface LiquidStruct {
solId?: number
volume?: number
}
export interface TubeSolStruct {
tubeNum: number
addLiquidList: LiquidStruct[]
};
interface AddLiquidStepStruct {
method: 'addLiquid'
params: {
solId?: number
volume?: number
tubeSolList?: TubeSolStruct[]
}
}
interface MoveToSolStepStruct {
method: 'moveToSol'
}
interface MoveToHeaterStepStruct {
method: 'moveToHeat'
}
interface ShakingStepStruct {
method: 'shaking'
params: {
second: number
}
}
interface StartHeatingStepStruct {
method: 'startHeating'
params: {
temperature: number
}
}
interface StopHeatingStepStruct {
method: 'stopHeating'
}
interface TakePhotoStepStruct {
method: 'takePhoto'
}
interface DelayStepStruct {
method: 'delay'
params: {
second: number
}
}
export type StepStruct =
| UpTrayStepStruct
| DownTrayStepStruct
| AddLiquidStepStruct
| MoveToSolStepStruct
| MoveToHeaterStepStruct
| ShakingStepStruct
| StartHeatingStepStruct
| StopHeatingStepStruct
| TakePhotoStepStruct
| DelayStepStruct
export type StepCmd = StepStruct['method']
export interface AddCraftType {
openDialog: () => void
closeDialog: () => void
editDialog: (params: Craft) => void
}
export interface TransferRightType {
getstepInfo: () => void
}
export const StepCmdDescMap: { [k in StepCmd]: string } = {
upTray: '抬起托盘',
downTray: '降下托盘',
addLiquid: '添加溶液',
moveToSol: '移至加液',
moveToHeat: '移至加热',
shaking: '摇匀',
startHeating: '开始加热',
stopHeating: '停止加热',
takePhoto: '拍照',
delay: '等待',
}
export interface Craft {
id?: number
name?: string
steps?: string
oresId?: number
}
const list = []
for (let i = 0; i < 16; i++) {
list.push({
id: i + 1,
name: `${i + 1}号试管`,
})
}
export const tubeSolList = list

148
src/views/craft/index.vue

@ -1,44 +1,172 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { AddCraftType, Craft } from './craftType'
import { createCraft, delCraft, getCraftList, setCraft, startCraft, updateCraft } from '@/apis/crafts'
import { ElMessage, ElMessageBox } from 'element-plus'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import AddCraftDialog from './AddCraftDialog.vue'
const tableData = ref([]) const tableData = ref([])
const addCraftRef = ref<AddCraftType | null>(null)
const selectable = ref()
const multipleSelection = ref<Craft[]>()
const heatVisible = ref(false)
const heatId = ref()
const oresId = 1
onMounted(() => { onMounted(() => {
console.log('--------')
queryCrafList()
}) })
const onAddCraft = () => {
const queryCrafList = () => {
const params = {
oresId: 1,
}
getCraftList(params).then((res) => {
tableData.value = res
})
}
const onAddCraft = () => {
if (addCraftRef.value) {
addCraftRef.value.openDialog()
}
} }
const onEditCraft = () => { const onEditCraft = () => {
if (addCraftRef.value && multipleSelection.value) {
addCraftRef.value.editDialog(multipleSelection.value[0])
}
}
const handleSelectionChange = (rows: Craft[]) => {
if (rows && rows.length) {
console.log('rows---', rows)
multipleSelection.value = rows
}
} }
const onDelCraft = () => { const onDelCraft = () => {
if (!multipleSelection.value || !multipleSelection.value.length) {
ElMessage.warning('请选择要删除的数据')
return
}
ElMessageBox.confirm(
'确认删除选中的数据吗?',
'确认提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
if (multipleSelection.value && multipleSelection.value.length) {
const ids = multipleSelection.value.map(item => item.id)
delCraft(ids.join(',')).then((res) => {
console.log('删除成功', res)
ElMessage.success('删除成功')
queryCrafList()
})
}
})
}
const onSelectHeatId = () => {
if (!multipleSelection.value || multipleSelection.value.length !== 1) {
ElMessage.warning('每次只可执行一次工艺')
return
}
heatVisible.value = true
}
const confirmCraftEdit = (craft: Craft) => {
// const req = createCraft({ name: craft.name, steps: craft.steps, oresId })
let req
if (craft.id) {
req = updateCraft(craft)
}
else {
req = createCraft({ name: craft.name, steps: craft.steps, oresId })
}
req.then(() => {
ElMessage.success('保存成功')
queryCrafList()
if (addCraftRef.value) {
addCraftRef.value.closeDialog()
}
})
}
//
const onStart = () => {
if (!heatId.value) {
ElMessage.warning('请选择加热区')
return
}
if (multipleSelection.value && multipleSelection.value.length && heatId) {
const craft = multipleSelection.value[0]
//
const craftId = craft.id
if (craftId && heatId.value) {
const params = {
craftId: craft.id,
heatId: heatId.value,
}
setCraft(params).then(() => {
console.log('配置成功==')
startCraft({ heatId: heatId.value }).then(() => {
console.log('开始执行')
ElMessage.success('工艺已开始执行')
heatVisible.value = false
})
})
}
}
} }
</script> </script>
<template> <template>
<div class="component-page"> <div class="component-page">
<section class="flex items-center h-20 gap-3 pl-3"> <section class="flex items-center h-20 gap-3 pl-3">
<el-button type="primary" @click="onAddCraft">
<el-button type="primary" size="small" @click="onAddCraft">
添加工艺 添加工艺
</el-button> </el-button>
<el-button type="primary" @click="onEditCraft">
<el-button type="primary" size="small" @click="onEditCraft">
编辑工艺 编辑工艺
</el-button> </el-button>
<el-button type="primary" @click="onDelCraft">
编辑工艺
<el-button type="primary" size="small" @click="onDelCraft">
删除工艺
</el-button>
<el-button type="primary" size="small" @click="onSelectHeatId">
执行工艺
</el-button> </el-button>
</section> </section>
<main> <main>
<el-table :data="tableData" stripe style="width: 100%">
<el-table-column prop="name" label="工艺名称" width="180" />
<el-table-column prop="orgName" label="矿石名称" width="180" />
<el-table :data="tableData" style="width: 100%" size="small" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="selectable" />
<el-table-column prop="name" label="工艺名称" />
<el-table-column prop="orgName" label="矿石名称">
<template #default="scope">
<!-- 测试数据 -->
<span v-if="scope.row.oresId === 1">硫酸</span>
<span v-else>硝酸</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期" /> <el-table-column prop="createTime" label="创建日期" />
</el-table> </el-table>
</main> </main>
<AddCraftDialog ref="addCraftRef" @ok="confirmCraftEdit" />
<!-- 执行工艺选择加热区 -->
<el-dialog v-model="heatVisible" title="执行工艺" width="30vw">
<div style="display: flex; justify-content: center;align-items: center;">
<label>选择加热区</label>
<el-select v-model="heatId" style="width:200px">
<el-option v-for="el in 6" :key="el" :label="`加热区${el}`" :value="el" />
</el-select>
</div>
<div style="display: flex; justify-content: center;align-items: center; height:100px">
<el-button type="primary" @click="onStart">
开始执行
</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
Loading…
Cancel
Save