软件开发已经进入了新的时代,前后端之间的壁垒逐渐消解。软件开发工程师应该具备更全面的知识体系、更强的岗位、业务适应能力。而AI coding的能力现在愈发强大,使用自然语言的描述,现在的大模型就能给出一份完整的代码;依托公司JoyCode平台的技术支持,我们可进一步探索基于大模型的全栈开发实践路径。
抱着借助JoyCode进行全栈开发实践的想法,本文在“标准化巡检打分”这一需求上进行了从端到端的全链路JoyCode辅助开发的实践。该需求旨在实现以下核心功能:1)支持终端管理人员对站点标准化程度进行线上评分;2)提供问题整改及复审闭环管理;3)允许配置标准化检查项与审核人员权限。
使用JoyCode进行全栈开发的总流程如下,全程依托JoyCode进行代码生成,通过多轮对话迭代优化AI输出结果,并结合必要的人工微调,最终完成了“标准化巡检打分”这一需求的全栈开发。
UI设计图:使用Relay提供的工具,由设计稿转成的静态vue代码这段代码是静态页面代码,请帮我使用flex布局修改成自适应高宽的、列表中的卡片使用v-for动态生成、其中的class名称帮我修改成语义化的类名,不要用mod,cnt这种不可读的
<template> <div class="inspection-container"> <!-- Fixed Category Navigation --> <div class="category-nav" ref="categoryNav"> <div v-for="category in categories" :key="category.id" class="category-tab" :class="{ 'active': activeCategory === category.id, 'has-failures': hasFailures(category.id) }" @click="scrollToCategory(category.id)" > <span>{{ category.name }}</span> <div v-if="hasFailures(category.id)" class="failure-indicator"></div> </div> </div>
<!-- Inspection Content --> <div class="inspection-content" ref="contentContainer" @scroll="handleScroll"> <div class="instructions"> <p>请勾选不合格项并录入不合格原因</p> <p class="hint">点击问号会弹出检查标准页面,并且自动定位到对应标准说明位置</p> </div>
<!-- All Categories Displayed --> <div v-for="category in categories" :key="'category-'+category.id" class="inspection-section" :ref="'category-'+category.id" > <div class="category-header"> <h2>{{ category.name }}</h2> <button class="info-button" @click="showStandards(category.id)"> <img src="//img12.360buyimg.com/ling/jfs/t1/287266/15/1006/1042/680f2af9F0a1295c4/c49a82370a53a843.png" alt="Info"> </button> </div>
<div v-for="item in category.items" :key="item.id" class="inspection-item" :class="{ 'failed': selectedFailures.includes(item.id) }" @click="toggleFailure(item.id)" > <div class="checkbox"> <div class="checkmark" v-if="selectedFailures.includes(item.id)"></div> </div> <span class="item-name">{{ item.name }}</span> <div class="action-area" v-if="selectedFailures.includes(item.id)"> <span class="reason-text">填写原因</span> <button class="reason-button" @click.stop="showReasonInput(item.id)"> <img src="//img14.360buyimg.com/ling/jfs/t1/282331/7/25786/288/680e4684Fca58754b/f905097e1453955e.png" alt="Edit"> </button> </div> </div> </div> </div>
<!-- Footer with Summary --> <footer class="inspection-footer"> <div class="failure-summary"> <span class="count">{{ selectedFailures.length }}</span> <span class="label">项不合格</span> </div> <button class="submit-button" :disabled="selectedFailures.length === 0" @click="submitInspection" > 提交 </button> </footer> </div></template>
<script>export default { data() { return { activeCategory: 0, selectedFailures: [], scrollTimeout: null, categories: [ { id: 0, name: '品牌形象', items: [ { id: 'brand-1', name: '门头VI' }, { id: 'brand-2', name: '员工形象' } ] }, { id: 1, name: '场内布局', items: [ { id: 'layout-1', name: '场地布局' }, { id: 'layout-2', name: '功能区规范' }, { id: 'layout-3', name: '路区标识' }, { id: 'layout-4', name: '公告栏配置' }, { id: 'layout-5', name: '海报' }, { id: 'layout-6', name: '警示标识' } ] }, { id: 2, name: '场地6S', items: [ { id: '6s-1', name: '场所环境-卫生' }, { id: '6s-2', name: '场所环境-定位' }, { id: '6s-3', name: '公告张贴' } ] }, { id: 3, name: '场地安全', items: [ { id: 'safety-1', name: '用电规范-充电' }, { id: 'safety-2', name: '用电规范-布线' }, { id: 'safety-3', name: '消防-禁烟' }, { id: 'safety-4', name: '消防-灭火器' } ] }, { id: 4, name: '监控设备', items: [ { id: 'monitor-1', name: '监控设备-LCV联网' }, { id: 'monitor-2', name: '监控设备-覆盖' } ] }, { id: 5, name: '站内作业规范', items: [ { id: 'work-1', name: '暴力操作' }, { id: 'work-2', name: '定置定位' }, { id: 'work-3', name: '日清操作' }, { id: 'work-4', name: '虚假操作' }, { id: 'work-5', name: '异常处置 | 三无' }, { id: 'work-6', name: '异常处置 | 拦截' }, { id: 'work-7', name: '异常处置 | 破损' }, { id: 'work-8', name: '异常处置 | 错到' }, { id: 'work-9', name: '异常处置区 | 码放' }, { id: 'work-10', name: '异常处置区 | 弃件' }, { id: 'work-11', name: '异常处置区 | 报废' }, { id: 'work-12', name: '异常处置区 | 售后' }, { id: 'work-13', name: '派件滞留区 | 仓管-码放' }, { id: 'work-14', name: '派件滞留区 | 仓管-再投' }, { id: 'work-15', name: '派件滞留区 | 小哥-码放' }, { id: 'work-16', name: '派件滞留区 | 小哥-再投' }, { id: 'work-17', name: '发出件暂存区 | 发货' }, { id: 'work-18', name: '发出件暂存区 | 集包' } ] }, { id: 6, name: '耗材管理', items: [ { id: 'supply-1', name: '耗材储备' }, { id: 'supply-2', name: '耗材执行' } ] }, { id: 7, name: '车辆管理', items: [ { id: 'vehicle-1', name: '车体形象' }, { id: 'vehicle-2', name: '车辆停放' }, { id: 'vehicle-3', name: '部件检查 | 后视镜' }, { id: 'vehicle-4', name: '部件检查 | 灯光' }, { id: 'vehicle-5', name: '部件检查 | 制动' }, { id: 'vehicle-6', name: '部件检查 | 喇叭' } ] } ] } }, mounted() { this.setupIntersectionObserver() }, methods: { setupIntersectionObserver() { const options = { root: this.$refs.contentContainer, rootMargin: '0px', threshold: 0.5 }
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const categoryId = parseInt(entry.target.id.split('-')[1]) this.activeCategory = categoryId this.scrollCategoryIntoView(categoryId) } }) }, options)
this.categories.forEach(category => { const element = this.$refs[`category-${category.id}`][0] if (element) { observer.observe(element) } }) }, scrollCategoryIntoView(categoryId) { const nav = this.$refs.categoryNav const tabs = nav.querySelectorAll('.category-tab') const activeTab = tabs[categoryId] if (activeTab) { const navWidth = nav.clientWidth const tabLeft = activeTab.offsetLeft const tabWidth = activeTab.clientWidth const scrollLeft = tabLeft - (navWidth - tabWidth) / 2 nav.scrollTo({ left: scrollLeft, behavior: 'smooth' }) } }, scrollToCategory(categoryId) { const element = this.$refs[`category-${categoryId}`][0] if (element) { this.$refs.contentContainer.scrollTo({ top: element.offsetTop - 60, // Adjust for header height behavior: 'smooth' }) } }, handleScroll() { // Debounce scroll events clearTimeout(this.scrollTimeout) this.scrollTimeout = setTimeout(() => { // The intersection observer will handle active category updates }, 50) }, toggleFailure(itemId) { const index = this.selectedFailures.indexOf(itemId) if (index === -1) { this.selectedFailures.push(itemId) } else { this.selectedFailures.splice(index, 1) } }, hasFailures(categoryId) { const category = this.categories.find(c => c.id === categoryId) if (!category) return false return category.items.some(item => this.selectedFailures.includes(item.id)) }, showReasonInput(itemId) { // Implement reason input dialog console.log('Show reason input for:', itemId) }, showStandards(categoryId) { // Implement standards display console.log('Show standards for category:', categoryId) }, submitInspection() { // Implement submission logic console.log('Submitting inspection with failures:', this.selectedFailures) } }}</script>
<style scoped> /* 样式省略 */</style>Copy